v0.16.0
Loading...
Searching...
No Matches
EshelbianTopologicalDerivativePush.cpp
Go to the documentation of this file.
1/**
2 * @file EshelbianTopologicalDerivativePush.cpp
3 * @author your name (you@domain.com)
4 * @brief
5 * @version 0.1
6 * @date 2026-02-25
7 *
8 * @copyright Copyright (c) 2026
9 *
10 */
11
12namespace EshelbianPlasticity {
13
15 EshelbianCore &ep, boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe,
16 ForcesAndSourcesCore::GaussHookFun interior_integration_hook,
17 SmartPetscObj<Vec> lambda_vec = SmartPetscObj<Vec>()) {
18
19 // This calculates field data in the interior, used by other operators.
20
21 auto data_at_pts_ptr = boost::make_shared<DataAtIntegrationPts>();
22
23 auto bubble_cache =
24 boost::make_shared<CGGUserPolynomialBase::CachePhi>(0, 0, MatrixDouble());
25 fe->getUserPolynomialBase() =
26 boost::make_shared<CGGUserPolynomialBase>(bubble_cache);
27 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
28 fe->getOpPtrVector(), {HDIV, H1, L2}, ep.materialH1Positions,
29 ep.frontAdjEdges);
30
31 // set integration rule
32 fe->getRuleHook = [](int, int, int) { return -1; };
33 fe->setRuleHook = interior_integration_hook;
34
35 // calculate fields values
36 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
37 ep.piolaStress, data_at_pts_ptr->getApproxPAtPts()));
38 fe->getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
39 ep.bubbleField, data_at_pts_ptr->getApproxPAtPts(), MBMAXTYPE));
40 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorDivergence<3, 3>(
41 ep.piolaStress, data_at_pts_ptr->getDivPAtPts()));
42
44 fe->getOpPtrVector().push_back(
45 ep.physicalEquations->returnOpCalculateStretchFromStress(
46 data_at_pts_ptr, ep.physicalEquations));
47 } else {
48 fe->getOpPtrVector().push_back(
49 new OpCalculateTensor2SymmetricFieldValues<3>(
50 ep.stretchTensor, data_at_pts_ptr->getLogStretchTensorAtPts(),
51 MBTET));
52 }
53
54 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
55 ep.rotAxis, data_at_pts_ptr->getRotAxisAtPts(), MBTET));
56 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
57 ep.spatialL2Disp, data_at_pts_ptr->getSmallWL2AtPts(), MBTET));
58
59 // H1 displacements
60 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
61 ep.spatialH1Disp, data_at_pts_ptr->getSmallWH1AtPts()));
62 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
63 ep.spatialH1Disp, data_at_pts_ptr->getSmallWGradH1AtPts()));
64 fe->getOpPtrVector().push_back(
65 new OpCalculateRotationAndSpatialGradient(data_at_pts_ptr));
66
68 } else {
69 fe->getOpPtrVector().push_back(ep.physicalEquations->returnOpJacobian(
70 false, false, data_at_pts_ptr, ep.physicalEquations));
71 }
72
73 if (lambda_vec) {
74 fe->getOpPtrVector().push_back(
75 new OpCalculateHVecTensorField<SPACE_DIM, SPACE_DIM>(
76 ep.piolaStress, data_at_pts_ptr->getVarPiolaPts(), nullptr,
77 lambda_vec));
78 fe->getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
79 ep.bubbleField, data_at_pts_ptr->getVarPiolaPts(), nullptr, lambda_vec,
80 MBMAXTYPE));
81 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorDivergence<3, 3>(
82 ep.piolaStress, data_at_pts_ptr->getDivVarPiolaPts(), lambda_vec));
83
84 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
85 ep.spatialL2Disp, data_at_pts_ptr->getVarWL2Pts(), lambda_vec, MBTET));
86 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
87 ep.rotAxis, data_at_pts_ptr->getVarRotAxisPts(), lambda_vec, MBTET));
88 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
89 ep.rotAxis, data_at_pts_ptr->getVarGradRotAxisPts(), lambda_vec, MBTET));
90
92 fe->getOpPtrVector().push_back(
93 ep.physicalEquations->returnOpCalculateVarStretchFromStress(
94 data_at_pts_ptr, ep.physicalEquations));
95 } else {
96 fe->getOpPtrVector().push_back(
97 new OpCalculateTensor2SymmetricFieldValues<3>(
98 ep.stretchTensor, data_at_pts_ptr->getVarLogStreachPts(),
99 lambda_vec, MBTET));
100 }
101 }
102
103 return data_at_pts_ptr;
104}
105
107 EshelbianCore &ep, const std::string &fe_name,
108 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe,
109 ForcesAndSourcesCore::GaussHookFun boundary_integration_hook) {
110
111 // This calculates field data on the boundary, used by other operators.
112
113 auto &m_field = ep.mField;
114
115 using BoundaryEle =
116 PipelineManager::ElementsAndOpsByDim<SPACE_DIM>::BoundaryEle;
117 using EleOnSide =
118 PipelineManager::ElementsAndOpsByDim<SPACE_DIM>::FaceSideEle;
119 using SideEleOp = EleOnSide::UserDataOperator;
120 using BdyEleOp = BoundaryEle::UserDataOperator;
121
122 // First: Iterate over skeleton FEs adjacent to Domain FEs
123 // Note: BoundaryEle, i.e. uses the skeleton integration rule
124 auto op_loop_skeleton_side =
125 new OpLoopSide<BoundaryEle>(m_field, fe_name, SPACE_DIM - 1, Sev::noisy);
126 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
127 return -1;
128 };
129 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
130 boundary_integration_hook;
131
132 CHKERR
133 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
134 op_loop_skeleton_side->getOpPtrVector(), {L2}, ep.materialH1Positions,
135 ep.frontAdjEdges);
136
137 // Second: iterate over domain FEs adjacent to the skeleton, in particular
138 // the domain element.
139 auto broken_data_ptr = boost::make_shared<std::vector<BrokenBaseSideData>>();
140 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
141 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
142 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
143 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
144 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
145 CHKERR
146 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
147 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
149 op_loop_domain_side->getOpPtrVector().push_back(
150 new OpGetBrokenBaseSideData<SideEleOp>(ep.piolaStress, broken_data_ptr));
151 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
152 op_loop_domain_side->getOpPtrVector().push_back(
153 new OpCalculateHVecTensorField<SPACE_DIM, SPACE_DIM>(ep.piolaStress,
154 flux_mat_ptr));
155 op_loop_domain_side->getOpPtrVector().push_back(
156 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
157 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
158
159 return std::make_tuple(op_loop_skeleton_side,
160 op_loop_domain_side->getSideFEPtr(), broken_data_ptr);
161}
162
164 EshelbianCore &ep, boost::shared_ptr<ForcesAndSourcesCore> fe,
165 boost::shared_ptr<DataAtIntegrationPts> data_at_pts_ptr,
166 boost::shared_ptr<TopologicalData> topo_ptr) {
167
168 // Calculate the interior objective derivative for the adjoint problem.
169
170 auto dJ_dx_vec = createDMVector(ep.dmElastic);
171
172 fe->getOpPtrVector().push_back(
173 new OpJ_dPImpl(ep.piolaStress, data_at_pts_ptr, topo_ptr, nullptr,
174 dJ_dx_vec, Tag()));
175 fe->getOpPtrVector().push_back(new OpJ_dBubbleImpl(
176 ep.bubbleField, data_at_pts_ptr, topo_ptr, nullptr, dJ_dx_vec, Tag()));
178 fe->getOpPtrVector().push_back(new OpJ_dUImpl(
179 ep.stretchTensor, data_at_pts_ptr, topo_ptr, nullptr, dJ_dx_vec,
180 Tag()));
181 }
182
183 // If we explicitly add rotation to J, add the corresponding rotational
184 // derivative operator.
185
186 fe->getOpPtrVector().push_back(
187 new OpJ_dwImpl(ep.spatialL2Disp, data_at_pts_ptr, topo_ptr, nullptr,
188 dJ_dx_vec, Tag()));
189 fe->getOpPtrVector().push_back(new OpJ_dOmegaImpl(
190 ep.rotAxis, data_at_pts_ptr, topo_ptr, nullptr, dJ_dx_vec, Tag()));
191
192 return dJ_dx_vec;
193}
194
196 EshelbianCore &ep, boost::shared_ptr<ForcesAndSourcesCore> fe,
197 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_data_ptr,
198 boost::shared_ptr<DataAtIntegrationPts> data_at_pts_ptr,
199 boost::shared_ptr<TopologicalData> topo_ptr, SmartPetscObj<Vec> dJ_dx_vec) {
201
202 // Calculate the boundary objective derivative for the adjoint problem.
203
204 fe->getOpPtrVector().push_back(new dJ_duGammaImpl(
205 ep.hybridSpatialDisp, data_at_pts_ptr, topo_ptr, nullptr, dJ_dx_vec,
206 Tag()));
207 fe->getOpPtrVector().push_back(
208 new dJ_dTractionImpl(broken_data_ptr, topo_ptr, nullptr, dJ_dx_vec,
209 Tag()));
211}
212
213SmartPetscObj<Vec> pushTopologicalSpatialOps(
214 EshelbianCore &ep, boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe,
215 ForcesAndSourcesCore::GaussHookFun interior_integration_hook,
216 ForcesAndSourcesCore::GaussHookFun boundary_integration_hook,
217 ObjectiveModelType eval_energy_model) {
218
219 auto data_at_pts_ptr =
220 pushInteriorTopologicalOpsImpl(ep, fe, interior_integration_hook);
221 auto [op_skeleton_side, domain_side_fe_ptr, broken_data_ptr] =
223 boundary_integration_hook);
224 fe->getOpPtrVector().push_back(op_skeleton_side);
225
226 auto topo_ptr = boost::make_shared<TopologicalData>();
227
228 switch (eval_energy_model) {
230 char objective_function_file_name[255] = "objective_function.py";
231 CHKERR PetscOptionsGetString(
232 PETSC_NULLPTR, PETSC_NULLPTR, "-objective_function",
233 objective_function_file_name, 255, PETSC_NULLPTR);
234 auto python_ptr =
235 create_python_objective_function(objective_function_file_name);
236 fe->getOpPtrVector().push_back(new OpTopologicalObjectivePythonImpl(
237 data_at_pts_ptr, topo_ptr, python_ptr, eval_energy_model));
238 } break;
240 fe->getOpPtrVector().push_back(new OpTopologicalObjectivePythonImpl(
241 data_at_pts_ptr, topo_ptr, nullptr, eval_energy_model));
242 } break;
243 default:
244 CHK_THROW_MESSAGE(MOFEM_INVALID_DATA, "Unknown objective model type");
245 }
246
247 auto dJ_dx_vec =
248 pushInteriorTopological_dJ_dx_Impl(ep, fe, data_at_pts_ptr, topo_ptr);
249
250 // Assume for (temporarily) that we do not have boundary contributions to
251 // dJ/dx. We add this once interior contributions are working and verified,
252 // and once we have a test case with non-zero boundary contribution. CHKERR
253 // pushBoundaryTopological_dJ_dx_Impl(
254 // ep, fe, broken_data_ptr, data_at_pts_ptr, topo_ptr, dJ_dx_vec);
255
256 return dJ_dx_vec;
257}
258
260 EshelbianCore &ep, boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe,
261 ForcesAndSourcesCore::GaussHookFun interior_integration_hook,
262 ForcesAndSourcesCore::GaussHookFun boundary_integration_hook,
263 boost::shared_ptr<double> J_ptr, SmartPetscObj<Vec> dJ_dX_vec,
264 ObjectiveModelType eval_energy_model) {
266
267 // This is derivative of dJ_dX, i.e. derivative with respect to material
268 // position, used by other operators.
269
270 auto data_at_pts_ptr =
271 pushInteriorTopologicalOpsImpl(ep, fe, interior_integration_hook);
272 auto [op_skeleton_side, domain_side_fe_ptr, broken_data_ptr] =
274 boundary_integration_hook);
275 fe->getOpPtrVector().push_back(op_skeleton_side);
276
277 auto topo_ptr = boost::make_shared<TopologicalData>();
278 switch (eval_energy_model) {
280 char objective_function_file_name[255] = "objective_function.py";
281 CHKERR PetscOptionsGetString(
282 PETSC_NULLPTR, PETSC_NULLPTR, "-objective_function",
283 objective_function_file_name, 255, PETSC_NULLPTR);
284 auto python_ptr =
285 create_python_objective_function(objective_function_file_name);
286 fe->getOpPtrVector().push_back(new OpTopologicalObjectivePythonImpl(
287 data_at_pts_ptr, topo_ptr, python_ptr, eval_energy_model));
288 } break;
290 fe->getOpPtrVector().push_back(new OpTopologicalObjectivePythonImpl(
291 data_at_pts_ptr, topo_ptr, nullptr, eval_energy_model));
292 } break;
293 default:
294 CHK_THROW_MESSAGE(MOFEM_INVALID_DATA, "Unknown objective model type");
295 }
296 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
297 ForcesAndSourcesCore::UserDataOperator::OPROW, ep.materialH1Positions,
298 topo_ptr->getJacobianAtPts(), SmartPetscObj<Vec>()));
299 fe->getOpPtrVector().push_back(new OpInvertMatrix<3>(
300 topo_ptr->getJacobianAtPts(), topo_ptr->getDetJacobianAtPts(),
301 topo_ptr->getInvJacobianAtPts()));
302 fe->getOpPtrVector().push_back(new OpInteriorJImpl(ep.materialH1Positions,
303 data_at_pts_ptr, topo_ptr,
304 J_ptr, dJ_dX_vec, Tag()));
305
306 // The boundary derivative is still missing here. The objective function has
307 // two integrals, one in the interior and one on the boundary. Only the
308 // interior integral is currently implemented, so OpBoundaryJImpl still needs
309 // to be added.
310
312}
313
315 EshelbianCore &ep, boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe,
316 ForcesAndSourcesCore::GaussHookFun interior_integration_hook,
317 ForcesAndSourcesCore::GaussHookFun boundary_integration_hook,
318 SmartPetscObj<Vec> lambda_vec, SmartPetscObj<Vec> dJ_dX_vec,
319 const double alpha, const double rho, const double alpha_omega,
320 boost::shared_ptr<double> J_ptr,
321 SmartPetscObj<Vec> topo_vec = SmartPetscObj<Vec>()) {
322
324
325 auto data_at_pts_ptr = pushInteriorTopologicalOpsImpl(
326 ep, fe, interior_integration_hook, lambda_vec);
327
328 auto add_hybridised_dJ_gradient = [&](auto fe_ptr) {
330 using BoundaryEle =
331 PipelineManager::ElementsAndOpsByDim<SPACE_DIM>::BoundaryEle;
332 using BdyEleOp = BoundaryEle::UserDataOperator;
333
334 auto [op_skeleton_side, domain_side_fe_ptr, broken_data_ptr] =
336 boundary_integration_hook);
337
338 using EleOnSide =
339 PipelineManager::ElementsAndOpsByDim<SPACE_DIM>::FaceSideEle;
340 using SideEleOp = EleOnSide::UserDataOperator;
341
342 auto var_piola_mat_ptr = boost::make_shared<MatrixDouble>();
343 domain_side_fe_ptr->getOpPtrVector().push_back(
344 new OpCalculateHVecTensorField<SPACE_DIM, SPACE_DIM>(
345 ep.piolaStress, var_piola_mat_ptr, nullptr, lambda_vec));
346 domain_side_fe_ptr->getOpPtrVector().push_back(
347 new OpSetVarFlux<SideEleOp>(broken_data_ptr, var_piola_mat_ptr));
348
349 auto broken_disp_data_ptr =
350 boost::make_shared<std::vector<BrokenBaseSideData>>();
351 domain_side_fe_ptr->getOpPtrVector().push_back(
352 new OpGetBrokenBaseSideData<SideEleOp>(ep.spatialL2Disp,
353 broken_disp_data_ptr));
354 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
355 domain_side_fe_ptr->getOpPtrVector().push_back(
356 new OpCalculateVectorFieldValues<SPACE_DIM>(ep.spatialL2Disp,
357 disp_mat_ptr));
358 domain_side_fe_ptr->getOpPtrVector().push_back(
359 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
360 auto var_disp_mat_ptr = boost::make_shared<MatrixDouble>();
361 domain_side_fe_ptr->getOpPtrVector().push_back(
362 new OpCalculateVectorFieldValues<SPACE_DIM>(
363 ep.spatialL2Disp, var_disp_mat_ptr, lambda_vec));
364 domain_side_fe_ptr->getOpPtrVector().push_back(
365 new OpSetVarFlux<SideEleOp>(broken_disp_data_ptr, var_disp_mat_ptr));
366
367 op_skeleton_side->getOpPtrVector().push_back(
368 new OpCalculateVectorFieldValues<SPACE_DIM>(
369 ep.hybridSpatialDisp, data_at_pts_ptr->getVarHybridDispAtPts(),
370 lambda_vec));
371 op_skeleton_side->getOpPtrVector().push_back(
372 new OpCalculateVectorFieldValues<SPACE_DIM>(
373 ep.hybridSpatialDisp, data_at_pts_ptr->getHybridDispAtPts()));
374 auto topo_ptr = boost::make_shared<TopologicalData>();
375 op_skeleton_side->getOpPtrVector().push_back(new OpGetHONormalsOnFace(
376 ep.materialH1Positions, topo_ptr->getTangent1AtPts(),
377 topo_ptr->getTangent2AtPts(), topo_ptr->getNormalAtPts()));
378
379 if (ep.alphaTau > 0.0) {
380 op_skeleton_side->getOpPtrVector().push_back(new OpTauStabilisation_dX(
381 ep.materialH1Positions, broken_disp_data_ptr,
382 data_at_pts_ptr->getHybridDispAtPts(),
383 data_at_pts_ptr->getVarHybridDispAtPts(), topo_ptr, ep.alphaTau,
384 dJ_dX_vec, J_ptr));
385 }
386
387 using OpTopoC_dHybrid =
388 FormsIntegrators<BdyEleOp>::Assembly<A>::LinearForm<
389 GAUSS>::OpTopoDerivativeBrokenSpaceConstrainDHybrid<SPACE_DIM>;
390 using OpTopoC_dFlux =
391 FormsIntegrators<BdyEleOp>::Assembly<A>::LinearForm<
392 GAUSS>::OpTopoDerivativeBrokenSpaceConstrainDFlux<SPACE_DIM>;
393 op_skeleton_side->getOpPtrVector().push_back(new OpTopoC_dHybrid(
394 ep.materialH1Positions, broken_data_ptr,
395 data_at_pts_ptr->getVarHybridDispAtPts(), topo_ptr->getTangent1AtPts(),
396 topo_ptr->getTangent2AtPts(), boost::make_shared<double>(1.0),
397 dJ_dX_vec, Tag(), J_ptr));
398 op_skeleton_side->getOpPtrVector().push_back(new OpTopoC_dFlux(
399 ep.materialH1Positions, broken_data_ptr,
400 data_at_pts_ptr->getHybridDispAtPts(), topo_ptr->getTangent1AtPts(),
401 topo_ptr->getTangent2AtPts(), boost::make_shared<double>(1.0),
402 dJ_dX_vec, Tag(), J_ptr));
403
404 fe_ptr->getOpPtrVector().push_back(op_skeleton_side);
406 };
407
408 CHK_THROW_MESSAGE(add_hybridised_dJ_gradient(fe),
409 "Failed to add hybridised dJ/dx gradient operators");
410
411 auto topo_ptr = boost::make_shared<TopologicalData>();
412 if (topo_vec) {
413 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
414 ForcesAndSourcesCore::UserDataOperator::OPROW, ep.materialH1Positions,
415 topo_ptr->getJacobianAtPts(), topo_vec));
416 } else {
417 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
418 ep.materialH1Positions, topo_ptr->getJacobianAtPts()));
419 }
420
421 fe->getOpPtrVector().push_back(new OpInvertMatrix<3>(
422 topo_ptr->getJacobianAtPts(), topo_ptr->getDetJacobianAtPts(),
423 topo_ptr->getInvJacobianAtPts()));
424
425 fe->getOpPtrVector().push_back(new OpSensitivityInteriorGradient(
426 ep.materialH1Positions, data_at_pts_ptr, topo_ptr, dJ_dX_vec, alpha, rho,
427 alpha_omega, J_ptr));
428 if (auto op = ep.physicalEquations->returnOpTopoSpatialPhysical(
429 ep.materialH1Positions, data_at_pts_ptr, dJ_dX_vec, topo_ptr,
430 ep.alphaU, J_ptr)) {
431 fe->getOpPtrVector().push_back(op);
432 }
433
434 auto body_time_scale =
435 boost::make_shared<EshelbianCore::DynamicRelaxationTimeScale>(
436 "body_force.txt");
437 auto add_body_force_opv = [&](auto &&meshset_vec_ptr) {
438 for (auto m : meshset_vec_ptr) {
439 auto op = new OpBodyForce_dX(
440 ep.mField, m->getMeshsetId(), ep.materialH1Positions, data_at_pts_ptr,
441 dJ_dX_vec, topo_ptr,
442 std::vector<boost::shared_ptr<ScalingMethod>>{body_time_scale},
443 J_ptr);
444 fe->getOpPtrVector().push_back(op);
445 }
446 };
447
448 const std::string body_force_block_name = "BODY_FORCE";
449
450 add_body_force_opv(
451
452 ep.mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
453
454 (boost::format("%s(.*)") % body_force_block_name).str()
455
456 ))
457
458 );
459
461}
462
464 EshelbianCore &ep, boost::shared_ptr<FaceElementForcesAndSourcesCore> fe,
465 ForcesAndSourcesCore::GaussHookFun interior_integration_hook,
466 ForcesAndSourcesCore::GaussHookFun boundary_integration_hook,
467 SmartPetscObj<Vec> lambda_vec, SmartPetscObj<Vec> dJ_dX_vec,
468 boost::shared_ptr<double> J_ptr,
469 SmartPetscObj<Vec> topo_vec = SmartPetscObj<Vec>()) {
471
472 if (!lambda_vec)
473 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_NULL,
474 "Lambda vector is required for boundary dJ/dx gradient");
475
476 fe->getRuleHook = [](int, int, int) { return -1; };
477 fe->setRuleHook = boundary_integration_hook;
478 CHKERR
479 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
480 fe->getOpPtrVector(), {L2}, ep.materialH1Positions, ep.frontAdjEdges);
481
482 auto get_broken_op_side = [&ep, lambda_vec](auto &pip) {
483 using EleOnSide =
484 PipelineManager::ElementsAndOpsByDim<SPACE_DIM>::FaceSideEle;
485 using SideEleOp = EleOnSide::UserDataOperator;
486 // Iterate over domain FEs adjacent to boundary.
487 auto broken_data_ptr =
488 boost::make_shared<std::vector<BrokenBaseSideData>>();
489 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
490 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
491 ep.mField, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
492 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
493 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
494 CHKERR
495 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
496 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
498 op_loop_domain_side->getOpPtrVector().push_back(
499 new OpGetBrokenBaseSideData<SideEleOp>(ep.piolaStress,
500 broken_data_ptr));
501 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
502 op_loop_domain_side->getOpPtrVector().push_back(
503 new OpCalculateHVecTensorField<SPACE_DIM, SPACE_DIM>(ep.piolaStress,
504 flux_mat_ptr));
505 op_loop_domain_side->getOpPtrVector().push_back(
506 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
507 auto var_flux_mat_ptr = boost::make_shared<MatrixDouble>();
508 op_loop_domain_side->getOpPtrVector().push_back(
509 new OpCalculateHVecTensorField<SPACE_DIM, SPACE_DIM>(
510 ep.piolaStress, var_flux_mat_ptr, nullptr, lambda_vec));
511 op_loop_domain_side->getOpPtrVector().push_back(
512 new OpSetVarFlux<SideEleOp>(broken_data_ptr, var_flux_mat_ptr));
513 pip.push_back(op_loop_domain_side);
514 return broken_data_ptr;
515 };
516
517 auto broken_data_ptr = get_broken_op_side(fe->getOpPtrVector());
518 auto topo_ptr = boost::make_shared<TopologicalData>();
519
520 auto lambda_hybrid_dip_ptr = boost::make_shared<MatrixDouble>();
521 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<SPACE_DIM>(
522 ep.hybridSpatialDisp, lambda_hybrid_dip_ptr, lambda_vec));
523 fe->getOpPtrVector().push_back(new OpDispBc_dX(
524 ep.materialH1Positions, broken_data_ptr, ep.bcSpatialDispVecPtr,
525 ep.timeScaleMap, topo_ptr, dJ_dX_vec, J_ptr));
526 fe->getOpPtrVector().push_back(new OpAnalyticalDispBc_dX(
527 ep.materialH1Positions, broken_data_ptr,
529 dJ_dX_vec, J_ptr));
530 fe->getOpPtrVector().push_back(new OpBrokenTractionBc_dX(
531 ep.materialH1Positions, ep.bcSpatialTractionVecPtr, lambda_hybrid_dip_ptr,
532 topo_ptr, ep.timeScaleMap, dJ_dX_vec, J_ptr));
533 fe->getOpPtrVector().push_back(new OpBrokenAnalyticalTractionBc_dX(
535 lambda_hybrid_dip_ptr, topo_ptr, ep.timeScaleMap, dJ_dX_vec, J_ptr));
536
537 // Boundary tau stabilisation still needs a material derivative if enabled.
538 // The skeleton jump term is handled in
539 // pushTopologicalInteriorOps_dJ_adjoint_gradient; boundary displacement and
540 // rotation penalties need their own BC-specific derivative operators.
541
543}
544
545} // namespace EshelbianPlasticity
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_INVALID_DATA
Definition definitions.h:36
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
MoFEMErrorCode pushTopologicalBoundaryOps_dJ_adjoint_gradient(EshelbianCore &ep, boost::shared_ptr< FaceElementForcesAndSourcesCore > fe, ForcesAndSourcesCore::GaussHookFun interior_integration_hook, ForcesAndSourcesCore::GaussHookFun boundary_integration_hook, SmartPetscObj< Vec > lambda_vec, SmartPetscObj< Vec > dJ_dX_vec, boost::shared_ptr< double > J_ptr, SmartPetscObj< Vec > topo_vec=SmartPetscObj< Vec >())
static auto pushBoundaryTopologicalOpsImpl(EshelbianCore &ep, const std::string &fe_name, boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe, ForcesAndSourcesCore::GaussHookFun boundary_integration_hook)
static auto pushInteriorTopologicalOpsImpl(EshelbianCore &ep, boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe, ForcesAndSourcesCore::GaussHookFun interior_integration_hook, SmartPetscObj< Vec > lambda_vec=SmartPetscObj< Vec >())
MoFEMErrorCode pushTopologicalMaterialOps(EshelbianCore &ep, boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe, ForcesAndSourcesCore::GaussHookFun interior_integration_hook, ForcesAndSourcesCore::GaussHookFun boundary_integration_hook, boost::shared_ptr< double > J_ptr, SmartPetscObj< Vec > dJ_dX_vec, ObjectiveModelType eval_energy_model)
static auto pushBoundaryTopological_dJ_dx_Impl(EshelbianCore &ep, boost::shared_ptr< ForcesAndSourcesCore > fe, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_data_ptr, boost::shared_ptr< DataAtIntegrationPts > data_at_pts_ptr, boost::shared_ptr< TopologicalData > topo_ptr, SmartPetscObj< Vec > dJ_dx_vec)
MoFEMErrorCode pushTopologicalInteriorOps_dJ_adjoint_gradient(EshelbianCore &ep, boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe, ForcesAndSourcesCore::GaussHookFun interior_integration_hook, ForcesAndSourcesCore::GaussHookFun boundary_integration_hook, SmartPetscObj< Vec > lambda_vec, SmartPetscObj< Vec > dJ_dX_vec, const double alpha, const double rho, const double alpha_omega, boost::shared_ptr< double > J_ptr, SmartPetscObj< Vec > topo_vec=SmartPetscObj< Vec >())
PipelineManager::ElementsAndOpsByDim< SPACE_DIM >::FaceSideEle EleOnSide
SmartPetscObj< Vec > pushTopologicalSpatialOps(EshelbianCore &ep, boost::shared_ptr< VolumeElementForcesAndSourcesCore > fe, ForcesAndSourcesCore::GaussHookFun interior_integration_hook, ForcesAndSourcesCore::GaussHookFun boundary_integration_hook, ObjectiveModelType eval_energy_model)
static auto pushInteriorTopological_dJ_dx_Impl(EshelbianCore &ep, boost::shared_ptr< ForcesAndSourcesCore > fe, boost::shared_ptr< DataAtIntegrationPts > data_at_pts_ptr, boost::shared_ptr< TopologicalData > topo_ptr)
constexpr AssemblyType A
FTensor::Index< 'm', 3 > m
boost::shared_ptr< Range > frontAdjEdges
const std::string skeletonElement
boost::shared_ptr< TractionBcVec > bcSpatialTractionVecPtr
MoFEM::Interface & mField
const std::string spatialL2Disp
std::map< std::string, boost::shared_ptr< ScalingMethod > > timeScaleMap
static enum StretchHandling stretchHandling
const std::string materialH1Positions
const std::string elementVolumeName
const std::string spatialH1Disp
const std::string piolaStress
const std::string bubbleField
boost::shared_ptr< AnalyticalDisplacementBcVec > bcSpatialAnalyticalDisplacementVecPtr
boost::shared_ptr< PhysicalEquations > physicalEquations
const std::string rotAxis
boost::shared_ptr< BcDispVec > bcSpatialDispVecPtr
const std::string skinElement
boost::shared_ptr< AnalyticalTractionBcVec > bcSpatialAnalyticalTractionVecPtr
const std::string hybridSpatialDisp
SmartPetscObj< DM > dmElastic
Elastic problem.
const std::string stretchTensor
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
BoundaryEle::UserDataOperator BdyEleOp
double rho
Definition plastic.cpp:145