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);
52 template <
typename NonlinearOperator,
typename UpdateType =
typename NonlinearOperator::
template ParameterValue<0>>
55 std::function<
void(
typename NonlinearOperator::template ParameterValue<0>&,
const UpdateType&)> p_updateFunction
56 = [](
typename NonlinearOperator::template ParameterValue<0>& a,
const UpdateType& b) { a += b; }) {
57 auto& x = nonLinOp.firstParameter();
60 if constexpr (not std::is_floating_point_v<UpdateType>) {
61 b.resizeLike(nonLinOp.derivative());
68 const auto e = nonLinOp.value();
71 if constexpr (not std::is_floating_point_v<UpdateType>)
72 gradfv = nonLinOp.derivative().dot(b);
74 gradfv = nonLinOp.derivative() * b;
76 auto ftfunc = [&](
auto t) {
77 p_updateFunction(x, t * b);
78 nonLinOp.template update<0>();
79 auto value = std::abs(nonLinOp.value() - e - t * gradfv);
84 const double slope = Impl::drawResultAndReturnSlope(
"Gradient", ftfunc, checkFlags.draw, 2);
86 const bool checkPassed = Dune::FloatCmp::le(2.0, slope, checkFlags.tolerance);
88 if (checkFlags.writeSlopeStatementIfFailed and not checkPassed) {
89 spdlog::info(
"Gradient check:");
90 spdlog::info(
"The slope should be 2. It seems to be {}.", slope);
92 spdlog::info(
"We consider this as sufficient.");
94 spdlog::info(
"The gradient seems wrong.");
113 template <
typename NonlinearOperator,
typename UpdateType =
typename NonlinearOperator::
template ParameterValue<0>>
116 std::function<
void(
typename NonlinearOperator::template ParameterValue<0>&,
const UpdateType&)> p_updateFunction
117 = [](
typename NonlinearOperator::template ParameterValue<0>& a,
const UpdateType& b) { a += b; }) {
118 auto& x = nonLinOp.firstParameter();
121 b.resizeLike(nonLinOp.derivative().row(0).transpose());
125 nonLinOp.updateAll();
126 const auto e = nonLinOp.value();
128 const auto jacofv = (nonLinOp.derivative() * b).eval();
130 auto ftfunc = [&](
auto t) {
131 p_updateFunction(x, t * b);
132 nonLinOp.template update<0>();
133 auto value = (nonLinOp.value() - e - t * jacofv).
norm();
138 const double slope = Impl::drawResultAndReturnSlope(
"Jacobian", ftfunc, checkFlags.draw, 2);
140 const bool checkPassed = Dune::FloatCmp::le(2.0, slope, checkFlags.tolerance);
142 if (checkFlags.writeSlopeStatementIfFailed and not checkPassed) {
143 spdlog::info(
"Jacobian check:");
144 spdlog::info(
"The slope should be 2. It seems to be {}.", slope);
146 spdlog::info(
"We consider this as sufficient.");
148 spdlog::info(
"The Jacobian seems wrong.");
150 nonLinOp.updateAll();
166 template <
typename NonlinearOperator,
typename UpdateType =
typename NonlinearOperator::
template ParameterValue<0>>
169 std::function<
void(
typename NonlinearOperator::template ParameterValue<0>&,
const UpdateType&)> p_updateFunction
170 = [](
typename NonlinearOperator::template ParameterValue<0>& a,
const UpdateType& b) { a += b; }) {
171 auto& x = nonLinOp.firstParameter();
174 if constexpr (not std::is_floating_point_v<UpdateType>) {
175 b.resizeLike(nonLinOp.derivative());
181 nonLinOp.updateAll();
182 const auto e = nonLinOp.value();
184 double gradfv, vhessv;
185 if constexpr (not std::is_floating_point_v<UpdateType>) {
186 gradfv = nonLinOp.derivative().dot(b);
187 vhessv = (nonLinOp.secondDerivative() * b).dot(b);
189 gradfv = nonLinOp.derivative() * b;
190 vhessv = nonLinOp.secondDerivative() * b * b;
193 auto ftfunc = [&](
auto t) {
194 p_updateFunction(x, t * b);
195 nonLinOp.template update<0>();
196 auto value = std::abs(nonLinOp.value() - e - t * gradfv - 0.5 * t * t * vhessv);
201 const double slope = Impl::drawResultAndReturnSlope(
"Hessian", ftfunc, checkFlags.draw, 3);
203 const bool checkPassed = Dune::FloatCmp::le(3.0, slope, checkFlags.tolerance);
205 if (checkFlags.writeSlopeStatementIfFailed and not checkPassed) {
206 spdlog::info(
"Hessian check:");
207 spdlog::info(
"The slope should be 3. It seems to be {}.", slope);
209 spdlog::info(
"We consider this as sufficient.");
211 spdlog::info(
"The Hessian seems wrong.");
213 nonLinOp.updateAll();
Implementation of the findLineSegment algorithm.
void draw(const GridView &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:258
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:114
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:167
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:53
Definition: algorithms.hh:17
Struct to hold flags for function checks.
Definition: functionsanitychecks.hh:34
bool draw
Definition: functionsanitychecks.hh:35
double tolerance
Definition: functionsanitychecks.hh:37
bool writeSlopeStatementIfFailed
Definition: functionsanitychecks.hh:36