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