14#include <dune/common/float_cmp.hh>
16#include <spdlog/spdlog.h>
28 double drawResultAndReturnSlope(std::string&& functionName,
const std::function<
double(
double)>& ftfunc,
bool draw,
29 int slopeOfReference);
53template <
typename NonlinearOperator,
typename UpdateType =
typename NonlinearOperator::
template ParameterValue<0>>
56 std::function<
void(
typename NonlinearOperator::template ParameterValue<0>&,
const UpdateType&)> p_updateFunction =
57 [](
typename NonlinearOperator::template ParameterValue<0>& a,
const UpdateType& b) { a += b; }) {
58 auto& x = nonLinOp.firstParameter();
61 if constexpr (not std::is_floating_point_v<UpdateType>) {
62 b.resizeLike(nonLinOp.derivative());
69 const auto e = nonLinOp.value();
72 if constexpr (not std::is_floating_point_v<UpdateType>)
73 gradfv = nonLinOp.derivative().dot(b);
75 gradfv = nonLinOp.derivative() * b;
77 auto ftfunc = [&](
auto t) {
78 p_updateFunction(x, t * b);
79 nonLinOp.template update<0>();
80 auto value = std::abs(nonLinOp.value() - e - t * gradfv);
85 const double slope = Impl::drawResultAndReturnSlope(
"Gradient", ftfunc, checkFlags.draw, 2);
87 const bool checkPassed = Dune::FloatCmp::le(2.0, slope, checkFlags.tolerance);
89 if (checkFlags.writeSlopeStatementIfFailed and not checkPassed) {
90 spdlog::info(
"Gradient check:");
91 spdlog::info(
"The slope should be 2. It seems to be {}.", slope);
93 spdlog::info(
"We consider this as sufficient.");
95 spdlog::info(
"The gradient seems wrong.");
114template <
typename NonlinearOperator,
typename UpdateType =
typename NonlinearOperator::
template ParameterValue<0>>
117 std::function<
void(
typename NonlinearOperator::template ParameterValue<0>&,
const UpdateType&)> p_updateFunction =
118 [](
typename NonlinearOperator::template ParameterValue<0>& a,
const UpdateType& b) { a += b; }) {
119 auto& x = nonLinOp.firstParameter();
122 b.resizeLike(nonLinOp.derivative().row(0).transpose());
126 nonLinOp.updateAll();
127 const auto e = nonLinOp.value();
129 const auto jacofv = (nonLinOp.derivative() * b).eval();
131 auto ftfunc = [&](
auto t) {
132 p_updateFunction(x, t * b);
133 nonLinOp.template update<0>();
134 auto value = (nonLinOp.value() - e - t * jacofv).
norm();
139 const double slope = Impl::drawResultAndReturnSlope(
"Jacobian", ftfunc, checkFlags.draw, 2);
141 const bool checkPassed = Dune::FloatCmp::le(2.0, slope, checkFlags.tolerance);
143 if (checkFlags.writeSlopeStatementIfFailed and not checkPassed) {
144 spdlog::info(
"Jacobian check:");
145 spdlog::info(
"The slope should be 2. It seems to be {}.", slope);
147 spdlog::info(
"We consider this as sufficient.");
149 spdlog::info(
"The Jacobian seems wrong.");
151 nonLinOp.updateAll();
167template <
typename NonlinearOperator,
typename UpdateType =
typename NonlinearOperator::
template ParameterValue<0>>
170 std::function<
void(
typename NonlinearOperator::template ParameterValue<0>&,
const UpdateType&)> p_updateFunction =
171 [](
typename NonlinearOperator::template ParameterValue<0>& a,
const UpdateType& b) { a += b; }) {
172 auto& x = nonLinOp.firstParameter();
175 if constexpr (not std::is_floating_point_v<UpdateType>) {
176 b.resizeLike(nonLinOp.derivative());
182 nonLinOp.updateAll();
183 const auto e = nonLinOp.value();
185 double gradfv, vhessv;
186 if constexpr (not std::is_floating_point_v<UpdateType>) {
187 gradfv = nonLinOp.derivative().dot(b);
188 vhessv = (nonLinOp.secondDerivative() * b).dot(b);
190 gradfv = nonLinOp.derivative() * b;
191 vhessv = nonLinOp.secondDerivative() * b * b;
194 auto ftfunc = [&](
auto t) {
195 p_updateFunction(x, t * b);
196 nonLinOp.template update<0>();
197 auto value = std::abs(nonLinOp.value() - e - t * gradfv - 0.5 * t * t * vhessv);
202 const double slope = Impl::drawResultAndReturnSlope(
"Hessian", ftfunc, checkFlags.draw, 3);
204 const bool checkPassed = Dune::FloatCmp::le(3.0, slope, checkFlags.tolerance);
206 if (checkFlags.writeSlopeStatementIfFailed and not checkPassed) {
207 spdlog::info(
"Hessian check:");
208 spdlog::info(
"The slope should be 3. It seems to be {}.", slope);
210 spdlog::info(
"We consider this as sufficient.");
212 spdlog::info(
"The Hessian seems wrong.");
214 nonLinOp.updateAll();
Implementation of the findLineSegment algorithm.
void draw(const GV &gridView, bool forever=false)
Draw function for visualizing the elements of a DUNE grid view.
Definition: griddrawer.hh:31
auto norm(const Eigen::MatrixBase< Derived > &v)
Adding free norm function to Eigen types.
Definition: linearalgebrahelper.hh:259
bool checkJacobian(NonlinearOperator &nonLinOp, CheckFlags checkFlags=CheckFlags(), std::function< void(typename NonlinearOperator::template ParameterValue< 0 > &, const UpdateType &)> p_updateFunction=[](typename NonlinearOperator::template ParameterValue< 0 > &a, const UpdateType &b) { a+=b;})
Checks the Jacobian of a nonlinear operator.
Definition: functionsanitychecks.hh:115
bool checkHessian(NonlinearOperator &nonLinOp, CheckFlags checkFlags=CheckFlags(), std::function< void(typename NonlinearOperator::template ParameterValue< 0 > &, const UpdateType &)> p_updateFunction=[](typename NonlinearOperator::template ParameterValue< 0 > &a, const UpdateType &b) { a+=b;})
Checks the Hessian of a nonlinear operator.
Definition: functionsanitychecks.hh:168
bool checkGradient(NonlinearOperator &nonLinOp, CheckFlags checkFlags=CheckFlags(), std::function< void(typename NonlinearOperator::template ParameterValue< 0 > &, const UpdateType &)> p_updateFunction=[](typename NonlinearOperator::template ParameterValue< 0 > &a, const UpdateType &b) { a+=b;})
Checks the gradient of a nonlinear operator.
Definition: functionsanitychecks.hh:54
Definition: algorithms.hh:17
Struct to hold flags for function checks.
Definition: functionsanitychecks.hh:35
bool draw
Definition: functionsanitychecks.hh:36
double tolerance
Definition: functionsanitychecks.hh:38
bool writeSlopeStatementIfFailed
Definition: functionsanitychecks.hh:37