194 {
196
197 auto &ep = *ctx_impl_ptr->
ep_ptr;
198 auto &m_field = ep.
mField;
201
202 auto fe_material =
203 boost::make_shared<VolumeElementForcesAndSourcesCore>(m_field);
204 auto J_ptr = boost::make_shared<double>(0);
206 boundary_integration_hook, J_ptr,
208
210 constexpr double eps = 1e-6;
211 auto random_vec = opt->setRandomFields(
212 ep.dmMaterial, {{ep.materialH1Positions, {-
eps,
eps}}},
nullptr,
215 CHKERR VecCopy(sol, a_vec);
216 CHKERR VecAXPY(a_vec, 1, random_vec);
218 CHKERR VecCopy(sol, b_vec);
219 CHKERR VecAXPY(b_vec, -1, random_vec);
220
221 *J_ptr = 0;
222 CHKERR VecGhostUpdateBegin(a_vec, INSERT_VALUES, SCATTER_FORWARD);
223 CHKERR VecGhostUpdateEnd(a_vec, INSERT_VALUES, SCATTER_FORWARD);
227 fe_material);
228 double J_plus = *J_ptr;
229 *J_ptr = 0;
230 CHKERR VecGhostUpdateBegin(b_vec, INSERT_VALUES, SCATTER_FORWARD);
231 CHKERR VecGhostUpdateEnd(b_vec, INSERT_VALUES, SCATTER_FORWARD);
235 fe_material);
236 double J_minus = *J_ptr;
237 double dJ_da = (J_plus - J_minus) / (2 *
eps);
238
239 double exact_dJ;
240 CHKERR VecDot(
g, random_vec, &exact_dJ);
241 double error = std::abs(dJ_da - exact_dJ);
242
244 <<
"J = " << *
f <<
", dJ/da = " << dJ_da <<
", exact dJ/da = " << exact_dJ
245 << ", error = " << error;
246
247 CHKERR VecGhostUpdateBegin(sol, INSERT_VALUES, SCATTER_FORWARD);
248 CHKERR VecGhostUpdateEnd(sol, INSERT_VALUES, SCATTER_FORWARD);
251
253}
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
Calculate directional derivative of the right hand side and compare it with tangent matrix derivative...