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 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
43 ep.rotAxis, data_at_pts_ptr->getRotAxisAtPts(), MBTET));
44
47 fe->getOpPtrVector(), ep.physicalEquations, data_at_pts_ptr,
49 } else {
50 fe->getOpPtrVector().push_back(
51 new OpCalculateTensor2SymmetricFieldValues<3>(
52 ep.stretchTensor, data_at_pts_ptr->getLogStretchTensorAtPts(),
53 MBTET));
54 }
55 CHK_THROW_MESSAGE(VecSetDM(ep.solTSStep, PETSC_NULLPTR), "VecSetDM failed");
56 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorField<3, 3>(
57 ep.piolaStress, data_at_pts_ptr->getApproxP0AtPts(), nullptr,
58 ep.solTSStep));
60 fe->getOpPtrVector().push_back(new OpCalculateTensor2SymmetricFieldValues<3>(
61 ep.stretchTensor, data_at_pts_ptr->getLogStretchTensor0AtPts(),
62 ep.solTSStep, MBTET));
63 }
64
65 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
66 ep.rotAxis, data_at_pts_ptr->getRotAxis0AtPts(), ep.solTSStep, MBTET));
67 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
68 ep.spatialL2Disp, data_at_pts_ptr->getSmallWL2AtPts(), MBTET));
69
70 // H1 displacements
71 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
72 ep.spatialH1Disp, data_at_pts_ptr->getSmallWH1AtPts()));
73 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
74 ep.spatialH1Disp, data_at_pts_ptr->getSmallWGradH1AtPts()));
75 fe->getOpPtrVector().push_back(
76 new OpCalculateRotationAndSpatialGradient(data_at_pts_ptr));
77
79 } else {
80 fe->getOpPtrVector().push_back(ep.physicalEquations->returnOpJacobian(
81 false, false, data_at_pts_ptr, ep.physicalEquations));
82 }
83
84 if (lambda_vec) {
85 fe->getOpPtrVector().push_back(
86 new OpCalculateHVecTensorField<SPACE_DIM, SPACE_DIM>(
87 ep.piolaStress, data_at_pts_ptr->getVarPiolaPts(), nullptr,
88 lambda_vec));
89 fe->getOpPtrVector().push_back(new OpCalculateHTensorTensorField<3, 3>(
90 ep.bubbleField, data_at_pts_ptr->getVarPiolaPts(), nullptr, lambda_vec,
91 MBMAXTYPE));
92 fe->getOpPtrVector().push_back(new OpCalculateHVecTensorDivergence<3, 3>(
93 ep.piolaStress, data_at_pts_ptr->getDivVarPiolaPts(), lambda_vec));
94
95 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
96 ep.spatialL2Disp, data_at_pts_ptr->getVarWL2Pts(), lambda_vec, MBTET));
97 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<3>(
98 ep.rotAxis, data_at_pts_ptr->getVarRotAxisPts(), lambda_vec, MBTET));
99 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
100 ep.rotAxis, data_at_pts_ptr->getVarGradRotAxisPts(), lambda_vec, MBTET));
101
103 fe->getOpPtrVector().push_back(
104 ep.physicalEquations->returnOpCalculateVarStretchFromStress(
105 data_at_pts_ptr, ep.physicalEquations));
106 } else {
107 fe->getOpPtrVector().push_back(
108 new OpCalculateTensor2SymmetricFieldValues<3>(
109 ep.stretchTensor, data_at_pts_ptr->getVarLogStreachPts(),
110 lambda_vec, MBTET));
111 }
112 }
113
114 return data_at_pts_ptr;
115}
116
118 EshelbianCore &ep, const std::string &fe_name,
119 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe,
120 ForcesAndSourcesCore::GaussHookFun boundary_integration_hook) {
121
122 // This calculates field data on the boundary, used by other operators.
123
124 auto &m_field = ep.mField;
125
126 using BoundaryEle =
127 PipelineManager::ElementsAndOpsByDim<SPACE_DIM>::BoundaryEle;
128 using EleOnSide =
129 PipelineManager::ElementsAndOpsByDim<SPACE_DIM>::FaceSideEle;
130 using SideEleOp = EleOnSide::UserDataOperator;
131 using BdyEleOp = BoundaryEle::UserDataOperator;
132
133 // First: Iterate over skeleton FEs adjacent to Domain FEs
134 // Note: BoundaryEle, i.e. uses the skeleton integration rule
135 auto op_loop_skeleton_side =
136 new OpLoopSide<BoundaryEle>(m_field, fe_name, SPACE_DIM - 1, Sev::noisy);
137 op_loop_skeleton_side->getSideFEPtr()->getRuleHook = [](int, int, int) {
138 return -1;
139 };
140 op_loop_skeleton_side->getSideFEPtr()->setRuleHook =
141 boundary_integration_hook;
142
143 CHKERR
144 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
145 op_loop_skeleton_side->getOpPtrVector(), {L2}, ep.materialH1Positions,
146 ep.frontAdjEdges);
147
148 // Second: iterate over domain FEs adjacent to the skeleton, in particular
149 // the domain element.
150 auto broken_data_ptr = boost::make_shared<std::vector<BrokenBaseSideData>>();
151 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
152 auto op_loop_domain_side = new OpBrokenLoopSide<EleOnSide>(
153 m_field, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
154 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
155 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
156 CHKERR
157 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
158 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
160 op_loop_domain_side->getOpPtrVector().push_back(
161 new OpGetBrokenBaseSideData<SideEleOp>(ep.piolaStress, broken_data_ptr));
162 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
163 op_loop_domain_side->getOpPtrVector().push_back(
164 new OpCalculateHVecTensorField<SPACE_DIM, SPACE_DIM>(ep.piolaStress,
165 flux_mat_ptr));
166 op_loop_domain_side->getOpPtrVector().push_back(
167 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
168 op_loop_skeleton_side->getOpPtrVector().push_back(op_loop_domain_side);
169
170 return std::make_tuple(op_loop_skeleton_side,
171 op_loop_domain_side->getSideFEPtr(), broken_data_ptr);
172}
173
175 EshelbianCore &ep, boost::shared_ptr<ForcesAndSourcesCore> fe,
176 boost::shared_ptr<DataAtIntegrationPts> data_at_pts_ptr,
177 boost::shared_ptr<TopologicalData> topo_ptr) {
178
179 // Calculate the interior objective derivative for the adjoint problem.
180
181 auto dJ_dx_vec = createDMVector(ep.dmElastic);
182
183 fe->getOpPtrVector().push_back(
184 new OpJ_dPImpl(ep.piolaStress, data_at_pts_ptr, topo_ptr, nullptr,
185 dJ_dx_vec, Tag()));
186 fe->getOpPtrVector().push_back(new OpJ_dBubbleImpl(
187 ep.bubbleField, data_at_pts_ptr, topo_ptr, nullptr, dJ_dx_vec, Tag()));
189 fe->getOpPtrVector().push_back(new OpJ_dUImpl(
190 ep.stretchTensor, data_at_pts_ptr, topo_ptr, nullptr, dJ_dx_vec,
191 Tag()));
192 }
193
194 // If we explicitly add rotation to J, add the corresponding rotational
195 // derivative operator.
196
197 fe->getOpPtrVector().push_back(
198 new OpJ_dwImpl(ep.spatialL2Disp, data_at_pts_ptr, topo_ptr, nullptr,
199 dJ_dx_vec, Tag()));
200 fe->getOpPtrVector().push_back(new OpJ_dOmegaImpl(
201 ep.rotAxis, data_at_pts_ptr, topo_ptr, nullptr, dJ_dx_vec, Tag()));
202
203 return dJ_dx_vec;
204}
205
207 EshelbianCore &ep, boost::shared_ptr<ForcesAndSourcesCore> fe,
208 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_data_ptr,
209 boost::shared_ptr<DataAtIntegrationPts> data_at_pts_ptr,
210 boost::shared_ptr<TopologicalData> topo_ptr, SmartPetscObj<Vec> dJ_dx_vec) {
212
213 // Calculate the boundary objective derivative for the adjoint problem.
214
215 fe->getOpPtrVector().push_back(new dJ_duGammaImpl(
216 ep.hybridSpatialDisp, data_at_pts_ptr, topo_ptr, nullptr, dJ_dx_vec,
217 Tag()));
218 fe->getOpPtrVector().push_back(
219 new dJ_dTractionImpl(broken_data_ptr, topo_ptr, nullptr, dJ_dx_vec,
220 Tag()));
222}
223
224SmartPetscObj<Vec> pushTopologicalSpatialOps(
225 EshelbianCore &ep, boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe,
226 ForcesAndSourcesCore::GaussHookFun interior_integration_hook,
227 ForcesAndSourcesCore::GaussHookFun boundary_integration_hook,
228 ObjectiveModelType eval_energy_model) {
229
230 auto data_at_pts_ptr =
231 pushInteriorTopologicalOpsImpl(ep, fe, interior_integration_hook);
232 auto [op_skeleton_side, domain_side_fe_ptr, broken_data_ptr] =
234 boundary_integration_hook);
235 fe->getOpPtrVector().push_back(op_skeleton_side);
236
237 auto topo_ptr = boost::make_shared<TopologicalData>();
238
239 switch (eval_energy_model) {
241 char objective_function_file_name[255] = "objective_function.py";
242 CHKERR PetscOptionsGetString(
243 PETSC_NULLPTR, PETSC_NULLPTR, "-objective_function",
244 objective_function_file_name, 255, PETSC_NULLPTR);
245 auto python_ptr =
246 create_python_objective_function(objective_function_file_name);
247 fe->getOpPtrVector().push_back(new OpTopologicalObjectivePythonImpl(
248 data_at_pts_ptr, topo_ptr, python_ptr, eval_energy_model));
249 } break;
251 fe->getOpPtrVector().push_back(new OpTopologicalObjectivePythonImpl(
252 data_at_pts_ptr, topo_ptr, nullptr, eval_energy_model));
253 } break;
254 default:
255 CHK_THROW_MESSAGE(MOFEM_INVALID_DATA, "Unknown objective model type");
256 }
257
258 auto dJ_dx_vec =
259 pushInteriorTopological_dJ_dx_Impl(ep, fe, data_at_pts_ptr, topo_ptr);
260
261 // Assume for (temporarily) that we do not have boundary contributions to
262 // dJ/dx. We add this once interior contributions are working and verified,
263 // and once we have a test case with non-zero boundary contribution. CHKERR
264 // pushBoundaryTopological_dJ_dx_Impl(
265 // ep, fe, broken_data_ptr, data_at_pts_ptr, topo_ptr, dJ_dx_vec);
266
267 return dJ_dx_vec;
268}
269
271 EshelbianCore &ep, boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe,
272 ForcesAndSourcesCore::GaussHookFun interior_integration_hook,
273 ForcesAndSourcesCore::GaussHookFun boundary_integration_hook,
274 boost::shared_ptr<double> J_ptr, SmartPetscObj<Vec> dJ_dX_vec,
275 ObjectiveModelType eval_energy_model) {
277
278 // This is derivative of dJ_dX, i.e. derivative with respect to material
279 // position, used by other operators.
280
281 auto data_at_pts_ptr =
282 pushInteriorTopologicalOpsImpl(ep, fe, interior_integration_hook);
283 auto [op_skeleton_side, domain_side_fe_ptr, broken_data_ptr] =
285 boundary_integration_hook);
286 fe->getOpPtrVector().push_back(op_skeleton_side);
287
288 auto topo_ptr = boost::make_shared<TopologicalData>();
289 switch (eval_energy_model) {
291 char objective_function_file_name[255] = "objective_function.py";
292 CHKERR PetscOptionsGetString(
293 PETSC_NULLPTR, PETSC_NULLPTR, "-objective_function",
294 objective_function_file_name, 255, PETSC_NULLPTR);
295 auto python_ptr =
296 create_python_objective_function(objective_function_file_name);
297 fe->getOpPtrVector().push_back(new OpTopologicalObjectivePythonImpl(
298 data_at_pts_ptr, topo_ptr, python_ptr, eval_energy_model));
299 } break;
301 fe->getOpPtrVector().push_back(new OpTopologicalObjectivePythonImpl(
302 data_at_pts_ptr, topo_ptr, nullptr, eval_energy_model));
303 } break;
304 default:
305 CHK_THROW_MESSAGE(MOFEM_INVALID_DATA, "Unknown objective model type");
306 }
307 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
308 ForcesAndSourcesCore::UserDataOperator::OPROW, ep.materialH1Positions,
309 topo_ptr->getJacobianAtPts(), SmartPetscObj<Vec>()));
310 fe->getOpPtrVector().push_back(new OpInvertMatrix<3>(
311 topo_ptr->getJacobianAtPts(), topo_ptr->getDetJacobianAtPts(),
312 topo_ptr->getInvJacobianAtPts()));
313 fe->getOpPtrVector().push_back(new OpInteriorJImpl(ep.materialH1Positions,
314 data_at_pts_ptr, topo_ptr,
315 J_ptr, dJ_dX_vec, Tag()));
316
317 // The boundary derivative is still missing here. The objective function has
318 // two integrals, one in the interior and one on the boundary. Only the
319 // interior integral is currently implemented, so OpBoundaryJImpl still needs
320 // to be added.
321
323}
324
326 EshelbianCore &ep, boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe,
327 ForcesAndSourcesCore::GaussHookFun interior_integration_hook,
328 ForcesAndSourcesCore::GaussHookFun boundary_integration_hook,
329 SmartPetscObj<Vec> lambda_vec, SmartPetscObj<Vec> dJ_dX_vec,
330 const double alpha, const double rho, const double alpha_viscous_omega,
331 boost::shared_ptr<double> J_ptr,
332 SmartPetscObj<Vec> topo_vec = SmartPetscObj<Vec>()) {
333
335
336 auto data_at_pts_ptr = pushInteriorTopologicalOpsImpl(
337 ep, fe, interior_integration_hook, lambda_vec);
338
339 auto add_hybridised_dJ_gradient = [&](auto fe_ptr) {
341 using BoundaryEle =
342 PipelineManager::ElementsAndOpsByDim<SPACE_DIM>::BoundaryEle;
343 using BdyEleOp = BoundaryEle::UserDataOperator;
344
345 auto [op_skeleton_side, domain_side_fe_ptr, broken_data_ptr] =
347 boundary_integration_hook);
348
349 using EleOnSide =
350 PipelineManager::ElementsAndOpsByDim<SPACE_DIM>::FaceSideEle;
351 using SideEleOp = EleOnSide::UserDataOperator;
352
353 auto var_piola_mat_ptr = boost::make_shared<MatrixDouble>();
354 domain_side_fe_ptr->getOpPtrVector().push_back(
355 new OpCalculateHVecTensorField<SPACE_DIM, SPACE_DIM>(
356 ep.piolaStress, var_piola_mat_ptr, nullptr, lambda_vec));
357 domain_side_fe_ptr->getOpPtrVector().push_back(
358 new OpSetVarFlux<SideEleOp>(broken_data_ptr, var_piola_mat_ptr));
359
360 auto broken_disp_data_ptr =
361 boost::make_shared<std::vector<BrokenBaseSideData>>();
362 domain_side_fe_ptr->getOpPtrVector().push_back(
363 new OpGetBrokenBaseSideData<SideEleOp>(ep.spatialL2Disp,
364 broken_disp_data_ptr));
365 auto disp_mat_ptr = boost::make_shared<MatrixDouble>();
366 domain_side_fe_ptr->getOpPtrVector().push_back(
367 new OpCalculateVectorFieldValues<SPACE_DIM>(ep.spatialL2Disp,
368 disp_mat_ptr));
369 domain_side_fe_ptr->getOpPtrVector().push_back(
370 new OpSetFlux<SideEleOp>(broken_disp_data_ptr, disp_mat_ptr));
371 auto var_disp_mat_ptr = boost::make_shared<MatrixDouble>();
372 domain_side_fe_ptr->getOpPtrVector().push_back(
373 new OpCalculateVectorFieldValues<SPACE_DIM>(
374 ep.spatialL2Disp, var_disp_mat_ptr, lambda_vec));
375 domain_side_fe_ptr->getOpPtrVector().push_back(
376 new OpSetVarFlux<SideEleOp>(broken_disp_data_ptr, var_disp_mat_ptr));
377
378 op_skeleton_side->getOpPtrVector().push_back(
379 new OpCalculateVectorFieldValues<SPACE_DIM>(
380 ep.hybridSpatialDisp, data_at_pts_ptr->getVarHybridDispAtPts(),
381 lambda_vec));
382 op_skeleton_side->getOpPtrVector().push_back(
383 new OpCalculateVectorFieldValues<SPACE_DIM>(
384 ep.hybridSpatialDisp, data_at_pts_ptr->getHybridDispAtPts()));
385 auto topo_ptr = boost::make_shared<TopologicalData>();
386 op_skeleton_side->getOpPtrVector().push_back(new OpGetHONormalsOnFace(
387 ep.materialH1Positions, topo_ptr->getTangent1AtPts(),
388 topo_ptr->getTangent2AtPts(), topo_ptr->getNormalAtPts()));
389
390 if (ep.alphaTau > 0.0) {
391 op_skeleton_side->getOpPtrVector().push_back(new OpTauStabilisation_dX(
392 ep.materialH1Positions, broken_disp_data_ptr,
393 data_at_pts_ptr->getHybridDispAtPts(),
394 data_at_pts_ptr->getVarHybridDispAtPts(), topo_ptr, ep.alphaTau,
395 dJ_dX_vec, J_ptr));
396 }
397
398 using OpTopoC_dHybrid =
399 FormsIntegrators<BdyEleOp>::Assembly<A>::LinearForm<
400 GAUSS>::OpTopoDerivativeBrokenSpaceConstrainDHybrid<SPACE_DIM>;
401 using OpTopoC_dFlux =
402 FormsIntegrators<BdyEleOp>::Assembly<A>::LinearForm<
403 GAUSS>::OpTopoDerivativeBrokenSpaceConstrainDFlux<SPACE_DIM>;
404 op_skeleton_side->getOpPtrVector().push_back(new OpTopoC_dHybrid(
405 ep.materialH1Positions, broken_data_ptr,
406 data_at_pts_ptr->getVarHybridDispAtPts(), topo_ptr->getTangent1AtPts(),
407 topo_ptr->getTangent2AtPts(), boost::make_shared<double>(1.0),
408 dJ_dX_vec, Tag(), J_ptr));
409 op_skeleton_side->getOpPtrVector().push_back(new OpTopoC_dFlux(
410 ep.materialH1Positions, broken_data_ptr,
411 data_at_pts_ptr->getHybridDispAtPts(), topo_ptr->getTangent1AtPts(),
412 topo_ptr->getTangent2AtPts(), boost::make_shared<double>(1.0),
413 dJ_dX_vec, Tag(), J_ptr));
414
415 fe_ptr->getOpPtrVector().push_back(op_skeleton_side);
417 };
418
419 CHK_THROW_MESSAGE(add_hybridised_dJ_gradient(fe),
420 "Failed to add hybridised dJ/dx gradient operators");
421
422 auto topo_ptr = boost::make_shared<TopologicalData>();
423 if (topo_vec) {
424 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
425 ForcesAndSourcesCore::UserDataOperator::OPROW, ep.materialH1Positions,
426 topo_ptr->getJacobianAtPts(), topo_vec));
427 } else {
428 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldGradient<3, 3>(
429 ep.materialH1Positions, topo_ptr->getJacobianAtPts()));
430 }
431
432 fe->getOpPtrVector().push_back(new OpInvertMatrix<3>(
433 topo_ptr->getJacobianAtPts(), topo_ptr->getDetJacobianAtPts(),
434 topo_ptr->getInvJacobianAtPts()));
435
436 fe->getOpPtrVector().push_back(new OpSensitivityInteriorGradient(
437 ep.materialH1Positions, data_at_pts_ptr, topo_ptr, dJ_dX_vec, alpha, rho,
438 alpha_viscous_omega, J_ptr));
439 if (auto op = ep.physicalEquations->returnOpTopoSpatialPhysical(
440 ep.materialH1Positions, data_at_pts_ptr, dJ_dX_vec, topo_ptr,
441 ep.alphaU, J_ptr)) {
442 fe->getOpPtrVector().push_back(op);
443 }
444
445 std::string body_force_history;
446 CHKERR ep.getStringArgumentFromJsonBlocksets("BODY_FORCE", "load_history",
447 body_force_history);
448 if (body_force_history.empty()) {
449 body_force_history = "body_force.txt";
450 } else {
451 MOFEM_LOG("EP", Sev::inform)
452 << "Body force load history from JSON: " << body_force_history;
453 }
454 auto body_time_scale =
455 boost::make_shared<EshelbianCore::DynamicRelaxationTimeScale>(
456 body_force_history);
457 auto add_body_force_opv = [&](auto &&meshset_vec_ptr) {
458 for (auto m : meshset_vec_ptr) {
459 auto op = new OpBodyForce_dX(
460 ep.mField, m->getMeshsetId(), ep.materialH1Positions, data_at_pts_ptr,
461 dJ_dX_vec, topo_ptr,
462 std::vector<boost::shared_ptr<ScalingMethod>>{body_time_scale},
463 J_ptr);
464 fe->getOpPtrVector().push_back(op);
465 }
466 };
467
468 const std::string body_force_block_name = "BODY_FORCE";
469
470 add_body_force_opv(
471
472 ep.mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(std::regex(
473
474 (boost::format("%s(.*)") % body_force_block_name).str()
475
476 ))
477
478 );
479
481}
482
484 EshelbianCore &ep, boost::shared_ptr<FaceElementForcesAndSourcesCore> fe,
485 ForcesAndSourcesCore::GaussHookFun interior_integration_hook,
486 ForcesAndSourcesCore::GaussHookFun boundary_integration_hook,
487 SmartPetscObj<Vec> lambda_vec, SmartPetscObj<Vec> dJ_dX_vec,
488 boost::shared_ptr<double> J_ptr,
489 SmartPetscObj<Vec> topo_vec = SmartPetscObj<Vec>()) {
491
492 if (!lambda_vec)
493 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_NULL,
494 "Lambda vector is required for boundary dJ/dx gradient");
495
496 fe->getRuleHook = [](int, int, int) { return -1; };
497 fe->setRuleHook = boundary_integration_hook;
498 CHKERR
499 EshelbianPlasticity::AddHOOps<SPACE_DIM - 1, SPACE_DIM, SPACE_DIM>::add(
500 fe->getOpPtrVector(), {L2}, ep.materialH1Positions, ep.frontAdjEdges);
501
502 auto get_broken_op_side = [&ep, lambda_vec](auto &pip) {
503 using EleOnSide =
504 PipelineManager::ElementsAndOpsByDim<SPACE_DIM>::FaceSideEle;
505 using SideEleOp = EleOnSide::UserDataOperator;
506 // Iterate over domain FEs adjacent to boundary.
507 auto broken_data_ptr =
508 boost::make_shared<std::vector<BrokenBaseSideData>>();
509 // Note: EleOnSide, i.e. uses on domain projected skeleton rule
510 auto op_loop_domain_side = new OpLoopSide<EleOnSide>(
511 ep.mField, ep.elementVolumeName, SPACE_DIM, Sev::noisy);
512 op_loop_domain_side->getSideFEPtr()->getUserPolynomialBase() =
513 boost::make_shared<CGGUserPolynomialBase>(nullptr, true);
514 CHKERR
515 EshelbianPlasticity::AddHOOps<SPACE_DIM, SPACE_DIM, SPACE_DIM>::add(
516 op_loop_domain_side->getOpPtrVector(), {HDIV, H1, L2},
518 op_loop_domain_side->getOpPtrVector().push_back(
519 new OpGetBrokenBaseSideData<SideEleOp>(ep.piolaStress,
520 broken_data_ptr));
521 auto flux_mat_ptr = boost::make_shared<MatrixDouble>();
522 op_loop_domain_side->getOpPtrVector().push_back(
523 new OpCalculateHVecTensorField<SPACE_DIM, SPACE_DIM>(ep.piolaStress,
524 flux_mat_ptr));
525 op_loop_domain_side->getOpPtrVector().push_back(
526 new OpSetFlux<SideEleOp>(broken_data_ptr, flux_mat_ptr));
527 auto var_flux_mat_ptr = boost::make_shared<MatrixDouble>();
528 op_loop_domain_side->getOpPtrVector().push_back(
529 new OpCalculateHVecTensorField<SPACE_DIM, SPACE_DIM>(
530 ep.piolaStress, var_flux_mat_ptr, nullptr, lambda_vec));
531 op_loop_domain_side->getOpPtrVector().push_back(
532 new OpSetVarFlux<SideEleOp>(broken_data_ptr, var_flux_mat_ptr));
533 pip.push_back(op_loop_domain_side);
534 return broken_data_ptr;
535 };
536
537 auto broken_data_ptr = get_broken_op_side(fe->getOpPtrVector());
538 auto topo_ptr = boost::make_shared<TopologicalData>();
539
540 auto lambda_hybrid_dip_ptr = boost::make_shared<MatrixDouble>();
541 fe->getOpPtrVector().push_back(new OpCalculateVectorFieldValues<SPACE_DIM>(
542 ep.hybridSpatialDisp, lambda_hybrid_dip_ptr, lambda_vec));
543 fe->getOpPtrVector().push_back(new OpDispBc_dX(
544 ep.materialH1Positions, broken_data_ptr, ep.bcSpatialDispVecPtr,
545 ep.timeScaleMap, topo_ptr, dJ_dX_vec, J_ptr));
546 fe->getOpPtrVector().push_back(new OpAnalyticalDispBc_dX(
547 ep.materialH1Positions, broken_data_ptr,
549 dJ_dX_vec, J_ptr));
550 fe->getOpPtrVector().push_back(new OpBrokenTractionBc_dX(
551 ep.materialH1Positions, ep.bcSpatialTractionVecPtr, lambda_hybrid_dip_ptr,
552 topo_ptr, ep.timeScaleMap, dJ_dX_vec, J_ptr));
553 fe->getOpPtrVector().push_back(new OpBrokenAnalyticalTractionBc_dX(
555 lambda_hybrid_dip_ptr, topo_ptr, ep.timeScaleMap, dJ_dX_vec, J_ptr));
556
557 // Boundary tau stabilisation still needs a material derivative if enabled.
558 // The skeleton jump term is handled in
559 // pushTopologicalInteriorOps_dJ_adjoint_gradient; boundary displacement and
560 // rotation penalties need their own BC-specific derivative operators.
561
563}
564
565} // 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.
#define MOFEM_LOG(channel, severity)
Log.
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)
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_viscous_omega, boost::shared_ptr< double > J_ptr, SmartPetscObj< Vec > topo_vec=SmartPetscObj< Vec >())
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)
void pushOpCalculateStretchFromStress(OpVector &op_vector, boost::shared_ptr< PhysicalEquations > physics_ptr, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< ExternalStrainVec > external_strain_vec_ptr, const std::map< std::string, boost::shared_ptr< ScalingMethod > > &smv, boost::shared_ptr< MatrixDouble > strain_ptr=nullptr)
Push pointwise external-pressure evaluation before stress recovery.
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< ExternalStrainVec > externalStrainVecPtr
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
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
MoFEMErrorCode getStringArgumentFromJsonBlocksets(const std::string &type_name, const std::string &param_name, std::string &param_value)
static bool isNoStretch()
const std::string hybridSpatialDisp
SmartPetscObj< Vec > solTSStep
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