v0.16.3
Loading...
Searching...
No Matches
EshelbianTopologicalDerivativeOperators.cpp
Go to the documentation of this file.
1/**
2 * @file EshelbianTopologicalDerivative.cpp
3 * @brief
4 * @version 0.1
5 * @date 2026-02-11
6 *
7 * @copyright Copyright (c) 2026
8 *
9 */
10
11
12using namespace EshelbianPlasticity;
13using namespace ShapeOptimization;
14
15namespace EshelbianPlasticity {
16
17// dr/dX topological derivative for Eshelbian plasticity model
18
19template <typename AssembleOp>
21 using OP = AssembleOp;
22
24 const std::string &field_name,
25 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
26 boost::shared_ptr<TopologicalData> topo_ptr,
27 boost::shared_ptr<double> J_ptr, SmartPetscObj<Vec> assemble_vec,
28 Tag topo_tag)
29 : OP(field_name, data_ptr, OP::OPROW), JPtr(J_ptr),
30 assembleVec(assemble_vec), topoTag(topo_tag), topoData(topo_ptr) {}
31
32 MoFEMErrorCode assemble(int side, EntityType type, EntData &data) override {
34 if (type == MBVERTEX) {
35 // Note it is iterated over vertices, since geometry is now in H1.
36 if (JPtr) {
37 *JPtr += locJ;
38 }
39 }
40 if (assembleVec) {
41 double *vec_ptr = OP::nF.data().data();
42 const int nb_dofs = data.getIndices().size();
43 int *ind_ptr = data.getIndices().data().data();
44 CHKERR VecSetValues(assembleVec, nb_dofs, ind_ptr, vec_ptr, ADD_VALUES);
45 }
46 if (topoTag) {
47 const auto field_ents = data.getFieldEntities();
48 std::vector<EntityHandle> ents(field_ents.size());
49 std::transform(field_ents.begin(), field_ents.end(), ents.begin(),
50 [](const auto *fe) { return fe->getEnt(); });
51 if (field_ents.empty())
53 if (type_from_handle(ents[0]) != MBVERTEX)
55 auto &moab = OP::getMoab();
56 VectorDouble topo_values(OP::nF.size());
57 CHKERR moab.tag_set_data(topoTag, ents.data(), ents.size(),
58 topo_values.data().data());
59 noalias(topo_values) += OP::nF;
60 CHKERR moab.tag_set_data(topoTag, ents.data(), ents.size(),
61 OP::nF.data().data());
62 }
64 }
65
66protected:
67 double locJ;
68 boost::shared_ptr<double> JPtr;
69 SmartPetscObj<Vec> assembleVec;
71 boost::shared_ptr<TopologicalData> topoData;
72};
73
80
86
88 : public FormsIntegrators<FaceUserDataOperator>::Assembly<A>::OpBrokenBase {
89
90 using OP = typename FormsIntegrators<FaceUserDataOperator>::Assembly<
92
94 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
95 boost::shared_ptr<TopologicalData> topo_ptr,
96 boost::shared_ptr<double> J_ptr,
97 SmartPetscObj<Vec> assemble_vec,
98 Tag topo_tag,
99 boost::shared_ptr<Range> ents_ptr = nullptr)
100 : OP(broken_base_side_data, ents_ptr), JPtr(J_ptr),
101 assembleVec(assemble_vec), topoTag(topo_tag),
102 topoData(topo_ptr) {}
103
104 MoFEMErrorCode aSsemble(EntData &data) override {
106 if (assembleVec) {
107 double *vec_ptr = OP::locF.data().data();
108 const int nb_dofs = data.getIndices().size();
109 int *ind_ptr = data.getIndices().data().data();
110 CHKERR VecSetValues(assembleVec, nb_dofs, ind_ptr, vec_ptr, ADD_VALUES);
111 }
112 if (topoTag) {
113 const auto field_ents = data.getFieldEntities();
114 std::vector<EntityHandle> ents(field_ents.size());
115 std::transform(field_ents.begin(), field_ents.end(), ents.begin(),
116 [](const auto *fe) { return fe->getEnt(); });
117 if (field_ents.empty())
119 if (type_from_handle(ents[0]) != MBVERTEX)
121 auto &moab = getMoab();
122 VectorDouble topo_values(OP::locF.size());
123 CHKERR moab.tag_set_data(topoTag, ents.data(), ents.size(),
124 topo_values.data().data());
125 topo_values += OP::locF;
126 CHKERR moab.tag_set_data(topoTag, ents.data(), ents.size(),
127 OP::locF.data().data());
128 }
130 }
131
132protected:
133 boost::shared_ptr<double> JPtr;
134 SmartPetscObj<Vec> assembleVec;
136 boost::shared_ptr<TopologicalData> topoData;
137};
138
141 OpAssembleVolumeTopologicalDerivativeImpl;
142
143 MoFEMErrorCode integrate(EntData &data);
144};
145
148 OpAssembleVolumeTopologicalDerivativeImpl;
149
150 MoFEMErrorCode integrate(EntData &data);
151};
152
155 OpAssembleVolumeTopologicalDerivativeImpl;
156
157 MoFEMErrorCode integrate(EntData &data);
158};
159
162 OpAssembleVolumeTopologicalDerivativeImpl;
163
164 MoFEMErrorCode integrate(EntData &data);
165};
166
169 OpAssembleFaceTopologicalDerivativeImpl;
170
171 MoFEMErrorCode integrate(EntData &data);
172};
173
177 OpAssembleBrokenFaceTopologicalDerivativeImplBase;
178
179 MoFEMErrorCode iNtegrate(EntData &data);
180};
181
184 const std::string &field_name,
185 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_disp_data_ptr,
186 boost::shared_ptr<MatrixDouble> hybrid_disp_ptr,
187 boost::shared_ptr<MatrixDouble> var_hybrid_disp_ptr,
188 boost::shared_ptr<TopologicalData> topo_ptr, const double alpha_tau,
189 SmartPetscObj<Vec> vec, boost::shared_ptr<double> J_ptr = nullptr,
190 Tag tag = Tag())
192 J_ptr, vec, tag),
193 brokenDispDataPtr(broken_disp_data_ptr), hybridDispPtr(hybrid_disp_ptr),
194 varHybridDispPtr(var_hybrid_disp_ptr), alphaTau(alpha_tau) {}
195
196 MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override;
197
198private:
199 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenDispDataPtr;
200 boost::shared_ptr<MatrixDouble> hybridDispPtr;
201 boost::shared_ptr<MatrixDouble> varHybridDispPtr;
202 double alphaTau;
203};
204
207 const std::string &field_name,
208 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
209 boost::shared_ptr<BcDispVec> bc_disp_ptr,
210 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv,
211 boost::shared_ptr<TopologicalData> topo_ptr, SmartPetscObj<Vec> vec,
212 boost::shared_ptr<double> J_ptr = nullptr, Tag tag = Tag())
214 J_ptr, vec, tag),
215 brokenSideDataPtr(broken_side_data_ptr), bcDispPtr(bc_disp_ptr),
216 scalingMethodsMap(smv) {}
217
218 MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override;
219
220private:
221 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
222 boost::shared_ptr<BcDispVec> bcDispPtr;
223 std::map<std::string, boost::shared_ptr<ScalingMethod>> scalingMethodsMap;
224};
225
226template <typename OP_PTR>
228 OP_PTR op_ptr, const std::string &block_name) {
229
230 auto nb_gauss_pts = op_ptr->getGaussPts().size2();
231
232 auto ts_time = op_ptr->getTStime();
233 auto ts_time_step = op_ptr->getTStimeStep();
234
237 ts_time_step = EshelbianCore::physicalDt;
238 }
239
240 MatrixDouble m_ref_coords = op_ptr->getCoordsAtGaussPts();
241 MatrixDouble m_ref_normals = op_ptr->getNormalsAtGaussPts();
242
243 auto v_analytical_expr =
244 analytical_expr_function(ts_time_step, ts_time, nb_gauss_pts,
245 m_ref_coords, m_ref_normals, block_name);
246
247 if (PetscUnlikely(!v_analytical_expr.size2())) {
249 "Analytical expression is empty or does not exist, "
250 "check python file");
251 }
252
253 return v_analytical_expr;
254}
255
258 const std::string &field_name,
259 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
260 boost::shared_ptr<AnalyticalDisplacementBcVec> bc_disp_ptr,
261 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv,
262 boost::shared_ptr<TopologicalData> topo_ptr, SmartPetscObj<Vec> vec,
263 boost::shared_ptr<double> J_ptr = nullptr, Tag tag = Tag())
265 J_ptr, vec, tag),
266 brokenSideDataPtr(broken_side_data_ptr), bcDispPtr(bc_disp_ptr),
267 scalingMethodsMap(smv) {}
268
269 MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override;
270
271private:
272 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
273 boost::shared_ptr<AnalyticalDisplacementBcVec> bcDispPtr;
274 std::map<std::string, boost::shared_ptr<ScalingMethod>> scalingMethodsMap;
275};
276
280 std::string field_name, boost::shared_ptr<TractionBcVec> bc_data,
281 boost::shared_ptr<MatrixDouble> lambda_hybrid_ptr,
282 boost::shared_ptr<TopologicalData> topo_ptr,
283 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv,
284 SmartPetscObj<Vec> vec, boost::shared_ptr<double> J_ptr = nullptr,
285 Tag tag = Tag())
287 J_ptr, vec, tag),
288 bcData(bc_data), lambdaHybridPtr(lambda_hybrid_ptr), topoData(topo_ptr),
289 scalingMethodsMap(smv) {}
290
291 MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override;
292
293protected:
294 boost::shared_ptr<TractionBcVec> bcData;
295 boost::shared_ptr<MatrixDouble> lambdaHybridPtr;
296 boost::shared_ptr<TopologicalData> topoData;
297 std::map<std::string, boost::shared_ptr<ScalingMethod>> scalingMethodsMap;
298};
299
303 std::string field_name,
304 boost::shared_ptr<AnalyticalTractionBcVec> bc_data,
305 boost::shared_ptr<MatrixDouble> lambda_hybrid_ptr,
306 boost::shared_ptr<TopologicalData> topo_ptr,
307 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv,
308 SmartPetscObj<Vec> vec, boost::shared_ptr<double> J_ptr = nullptr,
309 Tag tag = Tag())
311 J_ptr, vec, tag),
312 bcData(bc_data), lambdaHybridPtr(lambda_hybrid_ptr), topoData(topo_ptr),
313 scalingMethodsMap(smv) {}
314
315 MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override;
316
317protected:
318 boost::shared_ptr<AnalyticalTractionBcVec> bcData;
319 boost::shared_ptr<MatrixDouble> lambdaHybridPtr;
320 boost::shared_ptr<TopologicalData> topoData;
321 std::map<std::string, boost::shared_ptr<ScalingMethod>> scalingMethodsMap;
322};
323
326 OpAssembleVolumeTopologicalDerivativeImpl;
327
328 MoFEMErrorCode integrate(EntData &data);
329};
330
333 OpAssembleVolumeTopologicalDerivativeImpl;
334
335 MoFEMErrorCode integrate(EntData &data);
336};
337
339 : public ForcesAndSourcesCore::UserDataOperator {
340 using OP = ForcesAndSourcesCore::UserDataOperator;
341
343 boost::shared_ptr<DataAtIntegrationPts> data_at_pts_ptr,
344 boost::shared_ptr<TopologicalData> topo_p,
345 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
346 const ObjectiveModelType eval_energy_model = PYTHON_MODEL)
347 : OP(NOSPACE, OP::OPSPACE), dataAtPts(data_at_pts_ptr), topoData(topo_p),
348 pythonPtr(python_ptr), evalEnergyModel(eval_energy_model) {}
349
350 MoFEMErrorCode doWork(int side, EntityType type, EntData &data);
351
352
353
354
355private:
357 boost::shared_ptr<DataAtIntegrationPts> dataAtPts;
358 boost::shared_ptr<TopologicalData> topoData;
359 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
360};
361
363 EntityType type,
364 EntData &data) {
366
367#ifndef NDEBUG
368 if (!dataAtPts)
369 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
370 "DataAtIntegrationPts pointer is null");
371 if (!topoData)
372 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
373 "Topological data pointer is null");
374#endif // NDEBUG
375
376 const int nb_gauss_pts = getGaussPts().size2();
377 if (!nb_gauss_pts)
379
380 const auto &features = dataAtPts->physicsPtr->getFeatures();
381 const auto variable_compliance_mask =
385
386 auto stress_full_ptr = boost::make_shared<MatrixDouble>();
387 auto get_stress_full =
388 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
389 DL>::size(*stress_full_ptr, nb_gauss_pts);
390 stress_full_ptr->clear();
391 auto strain_full_ptr = boost::make_shared<MatrixDouble>();
392 auto get_strain_full =
393 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
394 DL>::size(*strain_full_ptr, nb_gauss_pts);
395 strain_full_ptr->clear();
396
397 auto t_stress = get_stress_full();
398 auto t_strain = get_strain_full();
399
400 auto t_biot = dataAtPts->getFTensorAdjointPdstretch(nb_gauss_pts);
401 auto t_u = dataAtPts->getFTensorStretch(nb_gauss_pts);
402
403 auto next = [&]() {
404 ++t_stress;
405 ++t_strain;
406 ++t_biot;
407 ++t_u;
408 };
409
411
412 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
413 // we have to handle all variants, that will render how the Jacobian
414 // gradient is evaluated.
415 t_stress(i, j) = t_biot(i, j);
416 t_strain(i, j) = t_u(i, j);
417 next();
418 }
419
420 auto evaluate_python_objective = [&]() {
422 if (!pythonPtr)
423 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
424 "ObjectiveFunctionData pointer is null");
425
426 auto &coords = OP::getCoordsAtGaussPts();
427 CHKERR pythonPtr->evalInteriorObjectiveFunction(
428 coords, dataAtPts->getSmallWL2AtPts(), stress_full_ptr, strain_full_ptr,
429 topoData->getObjAtPts(), false);
430 CHKERR pythonPtr->evalInteriorObjectiveGradientStrain(
431 coords, dataAtPts->getSmallWL2AtPts(), stress_full_ptr, strain_full_ptr,
432 topoData->getObjDStrainAtPts(), false);
433 CHKERR pythonPtr->evalInteriorObjectiveGradientU(
434 coords, dataAtPts->getSmallWL2AtPts(), stress_full_ptr, strain_full_ptr,
435 topoData->getObjDDisplacementAtPts(), false);
436 CHKERR pythonPtr->evalInteriorObjectiveGradientStress(
437 coords, dataAtPts->getSmallWL2AtPts(), stress_full_ptr, strain_full_ptr,
438 topoData->getObjDStressAtPts(), false);
440 };
441
442 auto evaluate_energy_of_hencky_model = [&]() {
444
445 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
446 *topoData->getObjDDisplacementAtPts(), nb_gauss_pts);
447 topoData->getObjDDisplacementAtPts()->clear();
448 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
449 DL>::size(*topoData->getObjDStressAtPts(), nb_gauss_pts);
450 topoData->getObjDStressAtPts()->clear();
451 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
452 *topoData->getObjDRotationAtPts(), nb_gauss_pts);
453
454 auto eval_evergy = [&](auto &&t_D) {
455 auto get_obj =
456 MatrixSizeHelper<GetFTensor1FromMatType<1, -1, DL>, DL>::size(
457 *topoData->getObjAtPts(), nb_gauss_pts);
458 auto get_dstrain_obj =
459 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
460 DL>::size(*topoData->getObjDStrainAtPts(),
461 nb_gauss_pts);
462 auto t_obj = get_obj();
463 auto t_dstrain_obj = get_dstrain_obj();
464 auto t_log_u = dataAtPts->getFTensorLogStretchTotal(nb_gauss_pts);
465 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
466 t_obj(0) = 0.5 * (t_log_u(i, j) * t_D(i, j, k, l) * t_log_u(k, l));
467 t_dstrain_obj(i, j) = t_D(i, j, k, l) * t_log_u(k, l);
468 ++t_log_u;
469 ++t_obj;
470 ++t_dstrain_obj;
471 ++t_D;
472 }
473 };
474
476 eval_evergy(
477 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(dataAtPts->matD));
478 } else {
479 eval_evergy(getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->matD));
480 }
481
482 topoData->getObjDRotationAtPts()->clear();
484 };
485
486 auto evaluate_energy_of_hencky_model_nostreach = [&]() {
488
489 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
490 *topoData->getObjDDisplacementAtPts(), nb_gauss_pts);
491 topoData->getObjDDisplacementAtPts()->clear();
492 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
493 DL>::size(*topoData->getObjDStrainAtPts(), nb_gauss_pts);
494 topoData->getObjDStrainAtPts()->clear();
495 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
496 *topoData->getObjDRotationAtPts(), nb_gauss_pts);
497 topoData->getObjDRotationAtPts()->clear();
498
499 auto eval_evergy = [&](auto &&t_inv_D) {
500 auto get_obj =
501 MatrixSizeHelper<GetFTensor1FromMatType<1, -1, DL>, DL>::size(
502 *topoData->getObjAtPts(), nb_gauss_pts);
503 auto get_dstress_obj =
504 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
505 DL>::size(*topoData->getObjDStressAtPts(),
506 nb_gauss_pts);
507 auto t_obj = get_obj();
508 auto t_dstress_obj = get_dstress_obj();
509 auto t_stress = dataAtPts->getFTensorAdjointPdstretch(nb_gauss_pts);
510 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
511 t_obj(0) =
512 0.5 * (t_stress(i, j) * t_inv_D(i, j, k, l) * t_stress(k, l));
513 t_dstress_obj(i, j) = t_inv_D(i, j, k, l) * t_stress(k, l);
514 ++t_stress;
515 ++t_obj;
516 ++t_dstress_obj;
517 ++t_inv_D;
518 }
519 };
520
521 if ((features & variable_compliance_mask).none()) {
522 eval_evergy(
523 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(dataAtPts->matInvD));
524 } else {
525 eval_evergy(
526 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->matInvD));
527 }
529 };
530
531 auto conversion_of_biot_stress = [&]() {
533 // Python differentiates the objective with respect to Biot stress. The
534 // material equations need the corresponding Piola and rotation derivatives.
535 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
536 *topoData->getObjDRotationAtPts(), nb_gauss_pts);
537 topoData->getObjDRotationAtPts()->clear();
538
539 auto t_obj_dbiot = topoData->getFTensorObjDStress(nb_gauss_pts);
540 auto t_obj_domega = topoData->getFTensorObjDRotation(nb_gauss_pts);
541 auto t_R = dataAtPts->getFTensorRotMat(nb_gauss_pts);
542 auto t_P = dataAtPts->getFTensorApproxP(nb_gauss_pts);
543 auto t_grad_h1 = dataAtPts->getFTensorSmallWGradH1(nb_gauss_pts);
544 auto t_omega = dataAtPts->getFTensorRotAxis(nb_gauss_pts);
545
551 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
552
553 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
555 t_dJ_dbiot(l, o) = t_obj_dbiot(l, o);
556
558 case SMALL_ROT:
559 // In the linear/small formulation Python sees the Piola field itself:
560 // B = P. There is no rotation or H1-gradient pullback to apply.
561 t_obj_dbiot(i, k) = t_dJ_dbiot(i, k);
562 t_obj_domega(m) = 0;
563 break;
564 case NO_H1_CONFIGURATION: {
567 case LARGE_ROT:
568 t_diff_R(i, l, m) =
569 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, l, m);
570 break;
571 default:
572 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
573 "rotationSelector not handled");
574 }
575
576 // Python sees B = R^T P.
577 t_obj_dbiot(i, k) = t_R(i, l) * t_dJ_dbiot(l, k);
578 t_obj_domega(m) = t_dJ_dbiot(l, k) * t_diff_R(i, l, m) * t_P(i, k);
579 } break;
580 case LARGE_ROT:
581 case MODERATE_ROT: {
583 t_h1(o, k) = t_kd(o, k) + t_grad_h1(o, k);
584
587 case SMALL_ROT:
588 t_diff_R(i, l, m) = levi_civita(i, l, m);
589 break;
590 case LARGE_ROT:
591 t_diff_R(i, l, m) =
592 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, l, m);
593 break;
594 default:
595 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
596 "rotationSelector not handled");
597 }
598
599 // Python sees B = R^T P H1^T.
600 t_obj_dbiot(i, k) = t_R(i, l) * (t_dJ_dbiot(l, o) * t_h1(o, k));
601 t_obj_domega(m) =
602 t_dJ_dbiot(l, o) * (t_diff_R(i, l, m) * t_P(i, k)) * t_h1(o, k);
603 } break;
604 default:
605 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
606 "gradApproximator not handled");
607 }
608
609 ++t_obj_dbiot;
610 ++t_obj_domega;
611 ++t_R;
612 ++t_P;
613 ++t_grad_h1;
614 ++t_omega;
615 }
616
618 };
619
620 auto conversion_of_stretch = [&]() {
622 // Python sees the physical stretch tensor. The stretch field stores log
623 // stretch, so convert dJ/dU to dJ/dlogU once here.
624 auto t_obj_dstretch = topoData->getFTensorObjDStrain(nb_gauss_pts);
625 auto t_diff_stretch = dataAtPts->getFTensorDiffStretch(nb_gauss_pts);
626
631
632 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
634 t_dJ_dstretch(i, j) = t_obj_dstretch(i, j);
635
636 t_obj_dstretch(k, l) = t_dJ_dstretch(i, j) * t_diff_stretch(i, j, k, l);
637
638 ++t_obj_dstretch;
639 ++t_diff_stretch;
640 }
641
643 };
644
645 auto conversion_of_stretch_to_stress_for_no_stretch = [&](auto t_inv_D) {
647 // In no-stretch mode, log stretch is computed from the stress field. Fold
648 // the objective stretch derivative into the stress derivative buffer.
649 auto t_obj_dstress = topoData->getFTensorObjDStress(nb_gauss_pts);
650 auto t_obj_dstretch = topoData->getFTensorObjDStrain(nb_gauss_pts);
651
656
657 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
659 t_dstretch_dstress(i, j) =
660 ((t_obj_dstretch(k, l) || t_obj_dstretch(l, k)) / 2.) *
661 t_inv_D(k, l, i, j);
662
663 t_obj_dstress(i, j) += t_dstretch_dstress(i, j);
664
665 ++t_obj_dstress;
666 ++t_obj_dstretch;
667 ++t_inv_D;
668 }
669
671 };
672
673 switch (evalEnergyModel) {
674 case PYTHON_MODEL:
675 CHKERR evaluate_python_objective();
676 CHKERR conversion_of_biot_stress();
678 if ((features & variable_compliance_mask).none()) {
679 CHKERR conversion_of_stretch_to_stress_for_no_stretch(
680 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(dataAtPts->matInvD));
681 } else {
682 CHKERR conversion_of_stretch_to_stress_for_no_stretch(
683 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->matInvD));
684 }
685 } else {
686 CHKERR conversion_of_stretch();
687 }
688 break;
689 case HENCKY_MODEL:
691 CHKERR evaluate_energy_of_hencky_model_nostreach();
692 CHKERR conversion_of_biot_stress();
693 } else {
694 CHKERR evaluate_energy_of_hencky_model();
695 }
696 break;
697 default:
698 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
699 "Objective model type not handled");
700 }
701
703}
704
705MoFEMErrorCode OpInteriorJImpl::integrate(EntData &data) {
707 locJ = 0;
708
709#ifndef NDEBUG
710 if (!topoData)
711 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
712 "Topological data pointer is null");
713#endif // NDEBUG
714
715 const int nb_dofs = data.getIndices().size();
716 if (!nb_dofs)
718
719 const int nb_integration_pts = getGaussPts().size2();
720
721 const auto v = getVolume();
722 auto t_w = getFTensor0IntegrationWeight();
723 auto t_obj = topoData->getFTensorObj(nb_integration_pts);
724 auto t_obj_dP = topoData->getFTensorObjDStress(nb_integration_pts);
725 auto t_obj_dStrain = topoData->getFTensorObjDStrain(nb_integration_pts);
726 auto t_obj_dU = topoData->getFTensorObjDDisplacement(nb_integration_pts);
727 auto t_P = dataAtPts->getFTensorApproxP(nb_integration_pts);
728 auto t_det = topoData->getFTensorDetJacobian(nb_integration_pts);
729 auto t_inv_jac = topoData->getFTensorInvJacobian(nb_integration_pts);
730 auto t_jac = topoData->getFTensorJacobian(nb_integration_pts);
731
732 auto next = [&]() {
733 ++t_w;
734 ++t_obj;
735 ++t_obj_dP;
736 ++t_obj_dStrain;
737 ++t_obj_dU;
738 ++t_P;
739 ++t_det;
740 ++t_inv_jac;
741 ++t_jac;
742 };
743
745 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
746
747 auto get_ftensor1 = [](auto &v) {
749 &v[0], &v[1], &v[2]);
750 };
751
752 nF.clear();
753
754 const int nb_base_functions = data.getN().size2();
755 auto t_base_diff = data.getFTensor1DiffN<SPACE_DIM>();
756 for (int gg = 0; gg != nb_integration_pts; ++gg) {
757 locJ += (t_w * v * t_det) * t_obj;
758
760 t_cof(i, j) = t_det * t_inv_jac(j, i);
761
763 t_dJ_dX(I, J) =
764
765 t_obj * t_cof(I, J)
766
767 +
768
769 t_obj_dP(i, j) * (t_kd(j, I) * (t_kd(k, J) * t_P(i, k)) -
770 t_inv_jac(I, J) * t_jac(j, k) * t_P(i, k));
771
772 auto t_nf = get_ftensor1(nF);
773 int bb = 0;
774 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
775 t_nf(i) += (t_w * v) * t_dJ_dX(i, j) * t_base_diff(j);
776 ++t_nf;
777 ++t_base_diff;
778 }
779 for (; bb != nb_base_functions; ++bb)
780 ++t_base_diff;
781
782 next();
783 }
784
786}
787
788MoFEMErrorCode OpJ_dPImpl::integrate(EntData &data) {
790
791#ifndef NDEBUG
792 if (!topoData)
793 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
794 "Topological data pointer is null");
795#endif // NDEBUG
796
797 const int nb_dofs = data.getIndices().size();
798 if (!nb_dofs)
800
801 const int nb_integration_pts = data.getN().size1();
802
803 const auto v = getVolume();
804 auto t_w = getFTensor0IntegrationWeight();
805 const int nb_base_functions = data.getN().size2() / SPACE_DIM;
806 auto t_row_base_fun = data.getFTensor1N<SPACE_DIM>();
807
810
811 auto get_ftensor1 = [](auto &v) {
813 &v[0], &v[1], &v[2]);
814 };
815
816 auto t_obj_dP = topoData->getFTensorObjDStress(nb_integration_pts);
817
818 for (int gg = 0; gg != nb_integration_pts; ++gg) {
819 const double a = v * t_w;
820 auto t_nf = get_ftensor1(nF);
821
822 int bb = 0;
823 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
824 t_nf(i) += a * t_row_base_fun(j) * t_obj_dP(i, j);
825 ++t_nf;
826 ++t_row_base_fun;
827 }
828 for (; bb != nb_base_functions; ++bb)
829 ++t_row_base_fun;
830
831 ++t_w;
832 ++t_obj_dP;
833 }
834
836}
837
838MoFEMErrorCode OpJ_dBubbleImpl::integrate(EntData &data) {
840
841#ifndef NDEBUG
842 if (!topoData)
843 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
844 "Topological data pointer is null");
845#endif // NDEBUG
846
847 const int nb_dofs = data.getIndices().size();
848 if (!nb_dofs)
850
851 const int nb_integration_pts = data.getN().size1();
852
853 const auto v = getVolume();
854 auto t_w = getFTensor0IntegrationWeight();
855 const int nb_base_functions = data.getN().size2() / (SPACE_DIM * SPACE_DIM);
856 auto t_row_base_fun = data.getFTensor2N<SPACE_DIM, SPACE_DIM>();
857 auto t_obj_dP = topoData->getFTensorObjDStress(nb_integration_pts);
858
861
862 auto get_ftensor0 = [](auto &v) {
864 };
865
866 for (int gg = 0; gg != nb_integration_pts; ++gg) {
867 const double a = v * t_w;
868 auto t_nf = get_ftensor0(nF);
869
870 int bb = 0;
871 for (; bb != nb_dofs; ++bb) {
872 t_nf += a * t_row_base_fun(i, j) * t_obj_dP(i, j);
873 ++t_nf;
874 ++t_row_base_fun;
875 }
876 for (; bb != nb_base_functions; ++bb)
877 ++t_row_base_fun;
878
879 ++t_w;
880 ++t_obj_dP;
881 }
882
884}
885
886MoFEMErrorCode OpJ_dwImpl::integrate(EntData &data) {
888
889#ifndef NDEBUG
890 if (!topoData)
891 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
892 "Topological data pointer is null");
893#endif // NDEBUG
894
895 const int nb_dofs = data.getIndices().size();
896 if (!nb_dofs)
898
899 const int nb_integration_pts = data.getN().size1();
900
901 const auto v = getVolume();
902 auto t_w = getFTensor0IntegrationWeight();
903 const int nb_base_functions = data.getN().size2();
904 auto t_row_base_fun = data.getFTensor0N();
905 auto t_obj_dw = topoData->getFTensorObjDDisplacement(nb_integration_pts);
906
908
909 auto get_ftensor1 = [](auto &v) {
911 &v[0], &v[1], &v[2]);
912 };
913
914 for (int gg = 0; gg != nb_integration_pts; ++gg) {
915 const double a = v * t_w;
916 auto t_nf = get_ftensor1(nF);
917
918 int bb = 0;
919 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
920 t_nf(i) += a * t_row_base_fun * t_obj_dw(i);
921 ++t_nf;
922 ++t_row_base_fun;
923 }
924 for (; bb != nb_base_functions; ++bb)
925 ++t_row_base_fun;
926
927 ++t_w;
928 ++t_obj_dw;
929 }
930
932}
933
934MoFEMErrorCode OpJ_dOmegaImpl::integrate(EntData &data) {
936
937#ifndef NDEBUG
938 if (!topoData)
939 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
940 "Topological data pointer is null");
941#endif // NDEBUG
942
943 const int nb_dofs = data.getIndices().size();
944 if (!nb_dofs)
946
947 const int nb_integration_pts = data.getN().size1();
948
949 const auto v = getVolume();
950 auto t_w = getFTensor0IntegrationWeight();
951 const int nb_base_functions = data.getN().size2();
952 auto t_row_base_fun = data.getFTensor0N();
953 auto t_obj_domega = topoData->getFTensorObjDRotation(nb_integration_pts);
954
956
957 auto get_ftensor1 = [](auto &v) {
959 &v[0], &v[1], &v[2]);
960 };
961
962 for (int gg = 0; gg != nb_integration_pts; ++gg) {
963 const double a = v * t_w;
964 auto t_nf = get_ftensor1(nF);
965
966 int bb = 0;
967 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
968 t_nf(i) += a * t_row_base_fun * t_obj_domega(i);
969 ++t_nf;
970 ++t_row_base_fun;
971 }
972 for (; bb != nb_base_functions; ++bb)
973 ++t_row_base_fun;
974
975 ++t_w;
976 ++t_obj_domega;
977 }
978
980}
981
982MoFEMErrorCode dJ_duGammaImpl::integrate(EntData &data) {
984
985#ifndef NDEBUG
986 if (!topoData)
987 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
988 "Topological data pointer is null");
989#endif // NDEBUG
990
991 const int nb_dofs = data.getIndices().size();
992 if (!nb_dofs)
994
995 const int nb_integration_pts = data.getN().size1();
996
997 auto t_w = getFTensor0IntegrationWeight();
998 const int nb_base_functions = data.getN().size2();
999 auto t_row_base_fun = data.getFTensor0N();
1000 auto t_obj_du_gamma =
1001 topoData->getFTensorObjDDisplacement(nb_integration_pts);
1002
1004
1005 auto get_ftensor1 = [](auto &v) {
1007 &v[0], &v[1], &v[2]);
1008 };
1009
1010 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1011 const double a = t_w * getMeasure();
1012 auto t_nf = get_ftensor1(nF);
1013
1014 int bb = 0;
1015 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1016 t_nf(i) += a * t_row_base_fun * t_obj_du_gamma(i);
1017 ++t_nf;
1018 ++t_row_base_fun;
1019 }
1020 for (; bb != nb_base_functions; ++bb)
1021 ++t_row_base_fun;
1022
1023 ++t_w;
1024 ++t_obj_du_gamma;
1025 }
1026
1028}
1029
1032
1033#ifndef NDEBUG
1034 if (!topoData)
1035 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1036 "Topological data pointer is null");
1037#endif // NDEBUG
1038
1039 const int nb_dofs = data.getIndices().size();
1040 if (!nb_dofs)
1042
1043 const int nb_integration_pts = OP::getGaussPts().size2();
1044
1045 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1046 auto t_w = OP::getFTensor0IntegrationWeight();
1047 const int nb_base_functions = data.getN().size2() / SPACE_DIM;
1048 auto t_row_base_fun = data.getFTensor1N<SPACE_DIM>();
1049 auto t_obj_dtraction =
1050 topoData->getFTensorObjDDisplacement(nb_integration_pts);
1051
1054
1055 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1056 auto t_nf = getFTensor1FromPtr<SPACE_DIM>(&*OP::locF.begin());
1057 int bb = 0;
1058 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1059 t_nf(i) +=
1060 t_w * (t_row_base_fun(j) * t_normal(j)) * t_obj_dtraction(i) * 0.5;
1061 ++t_nf;
1062 ++t_row_base_fun;
1063 }
1064 for (; bb != nb_base_functions; ++bb)
1065 ++t_row_base_fun;
1066
1067 ++t_w;
1068 ++t_normal;
1069 ++t_obj_dtraction;
1070 }
1071
1073}
1074
1075MoFEMErrorCode OpTauStabilisation_dX::integrate(int, EntityType,
1076 EntData &data) {
1078 locJ = 0;
1079
1080#ifndef NDEBUG
1081 if (!topoData)
1082 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1083 "Topological data pointer is null");
1084 if (!brokenDispDataPtr)
1085 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1086 "Broken displacement data pointer is null");
1087 if (!hybridDispPtr)
1088 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1089 "Hybrid displacement pointer is null");
1090 if (!varHybridDispPtr)
1091 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1092 "Adjoint hybrid displacement pointer is null");
1093#endif // NDEBUG
1094
1095 const int nb_dofs = data.getIndices().size();
1096 if (!nb_dofs)
1098
1099 const int nb_integration_pts = getGaussPts().size2();
1100 const int nb_base_functions = data.getN().size2();
1101
1102#ifndef NDEBUG
1103 if (this->nF.size() != nb_dofs)
1104 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1105 "Size of nF %ld != nb_dofs %d", this->nF.size(), nb_dofs);
1106 if (data.getDiffN().size1() != nb_integration_pts)
1107 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1108 "Differential of base functions should have the same number of "
1109 "integration points as the data");
1110 if (data.getDiffN().size2() != nb_base_functions * 2)
1111 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1112 "Differential of base functions should have the same number of "
1113 "base functions as the data");
1114#endif // NDEBUG
1115
1119
1120 auto &coords = getCoords();
1121 // Tau scale is based on the mesh triangle coordinates, not on the perturbed
1122 // material-position field. Treat h as constant with respect to X.
1123 const double h = std::get<2>(Tools::getTricircumcenter3d(coords.data().data()));
1124
1125 auto t_w = getFTensor0IntegrationWeight();
1126 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1127 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1128 auto t_u_hybrid = getFTensor1FromMat<SPACE_DIM, -1, DL>(*hybridDispPtr);
1129 auto t_var_u_hybrid =
1130 getFTensor1FromMat<SPACE_DIM, -1, DL>(*varHybridDispPtr);
1131 auto t_diff_base = data.getFTensor1DiffN<2>();
1132
1133 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1135 t_normal(j) =
1136 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1137
1138 double area = std::sqrt(t_normal(i) * t_normal(i));
1140 t_da(i) = t_normal(i) / area;
1141 area /= 2.;
1142 t_da(i) /= 2.;
1143
1144 double tau_density = 0;
1145 for (auto &bd : *brokenDispDataPtr) {
1146 auto t_u_broken =
1147 getFTensor1FromMat<SPACE_DIM, -1, DL>(bd.getFlux(), nb_integration_pts);
1148 auto t_var_u_broken = getFTensor1FromMat<SPACE_DIM, -1, DL>(
1149 bd.getVarFlux(), nb_integration_pts);
1150 for (int ss = 0; ss != gg; ++ss) {
1151 ++t_u_broken;
1152 ++t_var_u_broken;
1153 }
1154
1155 // This is the adjoint-weighted material derivative of the four tau
1156 // stabilisation residual blocks:
1157 // u_gamma-u_gamma, L2-L2, u_gamma-L2, and L2-u_gamma.
1158 const double hybrid_hybrid = t_var_u_hybrid(i) * t_u_hybrid(i);
1159 const double broken_broken = t_var_u_broken(i) * t_u_broken(i);
1160 const double hybrid_broken = -t_var_u_hybrid(i) * t_u_broken(i);
1161 const double broken_hybrid = -t_var_u_broken(i) * t_u_hybrid(i);
1162 tau_density +=
1163 hybrid_hybrid + broken_broken + hybrid_broken + broken_hybrid;
1164 }
1165
1166 const double tau = alphaTau / h;
1167 locJ += t_w * tau * area * tau_density;
1168
1169 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1170 int rr = 0;
1171 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1173 t_normal_dX(j, I) =
1174 (FTensor::levi_civita(i, j, I) * t_tangent2(i)) * t_diff_base(N0) +
1175 (FTensor::levi_civita(I, j, k) * t_tangent1(k)) * t_diff_base(N1);
1176
1177 t_nf(I) +=
1178 t_w * alphaTau * tau_density * (t_da(i) * t_normal_dX(i, I)) / h;
1179 ++t_diff_base;
1180 ++t_nf;
1181 }
1182 for (; rr != nb_base_functions; ++rr)
1183 ++t_diff_base;
1184
1185 ++t_w;
1186 ++t_tangent1;
1187 ++t_tangent2;
1188 ++t_u_hybrid;
1189 ++t_var_u_hybrid;
1190 }
1191
1193}
1194
1195MoFEMErrorCode OpDispBc_dX::integrate(int, EntityType type, EntData &data) {
1197 locJ = 0;
1198
1199#ifndef NDEBUG
1200 if (!brokenSideDataPtr)
1201 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1202 "Broken side data pointer is null");
1203#endif // NDEBUG
1204
1205
1206 const int nb_dofs = data.getIndices().size();
1207 if (!nb_dofs)
1209
1210 const int nb_integration_pts = getGaussPts().size2();
1211 const int nb_base_functions = data.getN().size2();
1212
1213#ifndef NDEBUG
1214 if (data.getDiffN().size1() != nb_integration_pts)
1215 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1216 "Differential of base functions should have the same number of "
1217 "integration points as the data");
1218 if (data.getDiffN().size2() != nb_base_functions * 2)
1219 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1220 "Differential of base functions should have the same number of "
1221 "base functions as the data");
1222#endif // NDEBUG
1223
1224 double time = getFEMethod()->ts_t;
1227
1229
1232
1233 const EntityHandle fe_ent = getFEEntityHandle();
1234 for (auto &bc : *bcDispPtr) {
1235 if (bc.faces.find(fe_ent) == bc.faces.end())
1236 continue;
1237
1238 double scale = 1;
1239 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1240 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1241 } else {
1242 MOFEM_LOG("SELF", Sev::warning)
1243 << "No scaling method found for " << bc.blockName;
1244 }
1245
1246 FTensor::Tensor1<double, SPACE_DIM> t_bc_disp(bc.vals[0], bc.vals[1],
1247 bc.vals[2]);
1248 t_bc_disp(i) *= scale;
1249
1250 for (auto &bd : *brokenSideDataPtr) {
1251 auto t_w = getFTensor0IntegrationWeight();
1252 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1253 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1254 auto t_var_flux =
1255 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(bd.getVarFlux());
1256 auto t_diff_base = data.getFTensor1DiffN<2>();
1257
1258 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1259 const double a = 0.5 * bd.getSense() * t_w;
1260
1262 t_normal(j) =
1263 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1264
1265 locJ += a * t_bc_disp(i) * (t_var_flux(i, j) * t_normal(j));
1266
1267 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1268 int bb = 0;
1269 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1270 // The H(div) contravariant Piola trace P . n dA is invariant with
1271 // respect to material-position perturbations. The normal variation is
1272 // cancelled by the Piola variation of the flux, so this BC contributes
1273 // to locJ but not to the exact dX vector.
1274 ++t_nf;
1275 ++t_diff_base;
1276 }
1277 for (; bb != nb_base_functions; ++bb)
1278 ++t_diff_base;
1279
1280 ++t_w;
1281 ++t_tangent1;
1282 ++t_tangent2;
1283 ++t_var_flux;
1284 }
1285 }
1286
1287 }
1288
1289
1291}
1292
1293MoFEMErrorCode OpAnalyticalDispBc_dX::integrate(int, EntityType type,
1294 EntData &data) {
1296 locJ = 0;
1297
1298#ifndef NDEBUG
1299 if (!brokenSideDataPtr)
1300 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1301 "Broken side data pointer is null");
1302#endif // NDEBUG
1303
1304 const int nb_dofs = data.getIndices().size();
1305 if (!nb_dofs)
1307
1308 const int nb_integration_pts = getGaussPts().size2();
1309 const int nb_base_functions = data.getN().size2();
1310
1311#ifndef NDEBUG
1312 if (data.getDiffN().size1() != nb_integration_pts)
1313 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1314 "Differential of base functions should have the same number of "
1315 "integration points as the data");
1316 if (data.getDiffN().size2() != nb_base_functions * 2)
1317 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1318 "Differential of base functions should have the same number of "
1319 "base functions as the data");
1320#endif // NDEBUG
1321
1325
1326 const EntityHandle fe_ent = getFEEntityHandle();
1327 for (auto &bc : *bcDispPtr) {
1328 if (bc.faces.find(fe_ent) == bc.faces.end())
1329 continue;
1330
1331 auto v_analytical_expr =
1332 getTopologicalAnalyticalExpr(this, bc.blockName);
1333
1334 for (auto &bd : *brokenSideDataPtr) {
1335 auto t_w = getFTensor0IntegrationWeight();
1336 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1337 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1338 auto t_var_flux =
1339 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(bd.getVarFlux());
1340 auto t_diff_base = data.getFTensor1DiffN<2>();
1341 auto t_bc_disp =
1342 getFTensor1FromMat<SPACE_DIM, -1, DL>(v_analytical_expr);
1343
1344 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1345 const double a = 0.5 * bd.getSense() * t_w;
1346
1348 t_normal(j) =
1349 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1350
1351 locJ += a * t_bc_disp(i) * (t_var_flux(i, j) * t_normal(j));
1352
1353 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1354 int bb = 0;
1355 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1356 // The H(div) contravariant Piola trace P . n dA is invariant with
1357 // respect to material-position perturbations. The normal variation is
1358 // cancelled by the Piola variation of the flux, so this BC contributes
1359 // to locJ but not to the exact dX vector.
1360 ++t_nf;
1361 ++t_diff_base;
1362 }
1363 for (; bb != nb_base_functions; ++bb)
1364 ++t_diff_base;
1365
1366 ++t_w;
1367 ++t_tangent1;
1368 ++t_tangent2;
1369 ++t_var_flux;
1370 ++t_bc_disp;
1371 }
1372 }
1373 }
1374
1376}
1377
1378MoFEMErrorCode OpBrokenTractionBc_dX::integrate(int side, EntityType type,
1379 EntData &data) {
1381 locJ = 0;
1382
1386
1387 int nb_dofs = data.getFieldData().size();
1388 int nb_integration_pts = getGaussPts().size2();
1389 int nb_base_functions = data.getN().size2();
1390
1391 double time = getFEMethod()->ts_t;
1394 }
1395
1396#ifndef NDEBUG
1397 if (this->nF.size() != nb_dofs)
1398 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1399 "Size of nF %ld != nb_dofs %d", this->nF.size(), nb_dofs);
1400#endif // NDEBUG
1401
1402 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
1404
1405 auto t_val = getFTensor1FromPtr<3>(&*bc.vals.begin());
1406 auto t_diff_base = data.getFTensor1DiffN<2>();
1407 auto t_w = getFTensor0IntegrationWeight();
1408 auto t_coords = getFTensor1CoordsAtGaussPts();
1409
1410 auto t_var_u_gamma = getFTensor1FromMat<SPACE_DIM>(lambdaHybridPtr);
1411 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1412 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1413
1414 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1415
1417 t_normal(j) =
1418 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1419
1420 double a = sqrt(t_normal(i) * t_normal(i));
1422 t_da(i) = t_normal(i) / a;
1423 a /= 2.;
1424 t_da(i) /= 2.;
1425
1426 const auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
1427 locJ -= (time_scale * t_w * a * tau) * (t_val(i) * t_var_u_gamma(i));
1428
1429 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1430 int rr = 0;
1431 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1433 t_normal_dX(j, I) =
1434 (FTensor::levi_civita(i, j, I) * t_tangent2(i)) * t_diff_base(N0) +
1435 (FTensor::levi_civita(I, j, k) * t_tangent1(k)) * t_diff_base(N1);
1436 t_nf(I) -= (time_scale * t_w * tau) * (t_val(i) * t_var_u_gamma(i)) *
1437 (t_da(i) * t_normal_dX(i, I));
1438 ++t_diff_base;
1439 ++t_nf;
1440 }
1441 for (; rr != nb_base_functions; ++rr)
1442 ++t_diff_base;
1443
1444 ++t_w;
1445 ++t_coords;
1446 ++t_var_u_gamma;
1447 ++t_tangent1;
1448 ++t_tangent2;
1449 }
1450
1452 };
1453
1454 // get entity of face
1455 EntityHandle fe_ent = getFEEntityHandle();
1456 for (auto &bc : *(bcData)) {
1457 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1458
1459 double time_scale = 1;
1460 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1461 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1462 }
1463
1464 if (nb_dofs) {
1465 if (std::regex_match(bc.blockName, std::regex(".*COOK.*"))) {
1466 auto calc_tau = [](double, double y, double) {
1467 y -= 44;
1468 y /= (60 - 44);
1469 return -y * (y - 1) / 0.25;
1470 };
1471 CHKERR integrate_rhs(bc, calc_tau, time_scale);
1472 } else {
1473 CHKERR integrate_rhs(
1474 bc, [](double, double, double) { return 1; }, time_scale);
1475 }
1476 }
1477 }
1478 }
1480}
1481
1483 EntityType type,
1484 EntData &data) {
1486 locJ = 0;
1487
1494
1495 int nb_dofs = data.getFieldData().size();
1496 int nb_integration_pts = getGaussPts().size2();
1497 int nb_base_functions = data.getN().size2();
1498
1499#ifndef NDEBUG
1500 if (this->nF.size() != nb_dofs)
1501 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1502 "Size of nF %ld != nb_dofs %d", this->nF.size(), nb_dofs);
1503#endif // NDEBUG
1504
1505 auto integrate_rhs = [&](auto &bc) {
1507
1508 auto v_analytical_expr =
1509 getTopologicalAnalyticalExpr(this, bc.blockName);
1510
1511 auto t_val = getFTensor1FromMat<SPACE_DIM, -1, DL>(v_analytical_expr);
1512 auto t_diff_base = data.getFTensor1DiffN<2>();
1513 auto t_w = getFTensor0IntegrationWeight();
1514
1515 auto t_var_u_gamma = getFTensor1FromMat<SPACE_DIM>(lambdaHybridPtr);
1516 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1517 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1518
1519 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1520
1522 t_normal(j) =
1523 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1524
1525 double a = sqrt(t_normal(i) * t_normal(i));
1527 t_da(i) = t_normal(i) / a;
1528 a /= 2.;
1529 t_da(i) /= 2.;
1530
1531 locJ -= (t_w * a) * (t_val(i) * t_var_u_gamma(i));
1532
1533 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1534 int rr = 0;
1535 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1537 t_normal_dX(j, I) =
1538 (FTensor::levi_civita(i, j, I) * t_tangent2(i)) * t_diff_base(N0) +
1539 (FTensor::levi_civita(I, j, k) * t_tangent1(k)) * t_diff_base(N1);
1540 t_nf(I) -= t_w * (t_val(i) * t_var_u_gamma(i)) *
1541 (t_da(i) * t_normal_dX(i, I));
1542 ++t_diff_base;
1543 ++t_nf;
1544 }
1545 for (; rr != nb_base_functions; ++rr)
1546 ++t_diff_base;
1547
1548 ++t_w;
1549 ++t_val;
1550 ++t_var_u_gamma;
1551 ++t_tangent1;
1552 ++t_tangent2;
1553 }
1554
1556 };
1557
1558 EntityHandle fe_ent = getFEEntityHandle();
1559 for (auto &bc : *(bcData)) {
1560 if (bc.faces.find(fe_ent) != bc.faces.end() && nb_dofs) {
1561 CHKERR integrate_rhs(bc);
1562 }
1563 }
1564
1566}
1567
1568MoFEMErrorCode OpJ_dUImpl::integrate(EntData &data) {
1570
1571#ifndef NDEBUG
1572 if (!topoData)
1573 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1574 "Topological data pointer is null");
1575#endif // NDEBUG
1576
1577 const int nb_dofs = data.getIndices().size();
1578 if (!nb_dofs)
1580
1581 const int nb_integration_pts = data.getN().size1();
1582
1583 const auto v = getVolume();
1584 auto t_w = getFTensor0IntegrationWeight();
1585 const int nb_base_functions = data.getN().size2();
1586 auto t_row_base_fun = data.getFTensor0N();
1587
1588 auto t_obj_dlog_stretch = topoData->getFTensorObjDStrain(nb_integration_pts);
1589
1592 FTensor::Index<'L', size_symm> L;
1593 auto t_L = FTensor::SymmLTensor<double, 3>();
1594
1595 auto get_ftensor1 = [](auto &v) {
1597 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1598 };
1599
1600 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1601 const double a = v * t_w;
1602 auto t_nf = get_ftensor1(OP::nF);
1603
1605 t_obj_dU(L) = t_obj_dlog_stretch(i, j) * t_L(i, j, L);
1606
1607 int bb = 0;
1608 for (; bb != nb_dofs / size_symm; ++bb) {
1609 t_nf(L) += a * t_row_base_fun * t_obj_dU(L);
1610 ++t_nf;
1611 ++t_row_base_fun;
1612 }
1613 for (; bb != nb_base_functions; ++bb)
1614 ++t_row_base_fun;
1615
1616 ++t_w;
1617 ++t_obj_dlog_stretch;
1618 }
1619
1621}
1622
1626 const std::string field_name,
1627 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1628 boost::shared_ptr<TopologicalData> topo_ptr,
1629 SmartPetscObj<Vec> assemble_vec, const double alpha, const double rho,
1630 const double alpha_viscous_omega = 0,
1631 boost::shared_ptr<double> J_ptr = nullptr)
1633 field_name, data_ptr, topo_ptr, J_ptr, assemble_vec, Tag()),
1634 alphaW(alpha), alphaRho(rho),
1635 alphaViscousOmega(alpha_viscous_omega) {}
1636
1637 MoFEMErrorCode integrate(EntData &data) {
1639#ifndef NDEBUG
1641 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1642 "L2 user base scale is set to %d, current inplementation only "
1643 "hanlde case for false",
1645 }
1646#endif // NDEBUG
1647
1648#ifndef NDEBUG
1649 if (!dataAtPts)
1650 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1651 "DataAtIntegrationPts pointer is null");
1652#endif // NDEBUG
1653
1654 const int nb_dofs = data.getIndices().size();
1655 if (!nb_dofs)
1657
1658 const int nb_integration_pts = getGaussPts().size2();
1659
1660 const auto v = getVolume();
1661 auto t_w = getFTensor0IntegrationWeight();
1662 // OpSpatialEquilibrium
1663 auto t_div_P = dataAtPts->getFTensorDivP(nb_integration_pts);
1664 auto t_var_w = dataAtPts->getFTensorVarWL2(nb_integration_pts);
1665 // OpSpatialRotation
1666 auto t_approx_P = dataAtPts->getFTensorApproxP(nb_integration_pts);
1667 auto t_omega = dataAtPts->getFTensorRotAxis(nb_integration_pts);
1668 auto t_u_h1 = dataAtPts->getFTensorStretchH1(nb_integration_pts);
1669 auto t_var_omega = dataAtPts->getFTensorVarRotAxis(nb_integration_pts);
1670 // OpSpatialConsistencyP
1671 auto t_h = dataAtPts->getFTensorSmallH(nb_integration_pts);
1672 auto t_var_P = dataAtPts->getFTensorVarPiola(nb_integration_pts);
1673 auto t_w_l2 = dataAtPts->getFTensorSmallWL2(nb_integration_pts);
1674 auto t_var_div_P = dataAtPts->getFTensorDivVarPiola(nb_integration_pts);
1675
1676 auto t_jac = topoData->getFTensorJacobian(nb_integration_pts);
1677
1678 auto get_ftensor1 = [](auto &v) {
1680 &v[0], &v[1], &v[2]);
1681 };
1682
1683 auto next = [&]() {
1684 ++t_w;
1685 ++t_div_P;
1686 ++t_var_w;
1687 ++t_approx_P;
1688 ++t_omega;
1689 ++t_u_h1;
1690 ++t_var_omega;
1691 ++t_h;
1692 ++t_var_P;
1693 ++t_w_l2;
1694 ++t_var_div_P;
1695 ++t_jac;
1696 };
1697
1704
1707
1708 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1709
1710 locJ = 0;
1711 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1712 double a = v * t_w;
1713
1715 // rotation
1717 case SMALL_ROT:
1718 t_diff_R(i, j, k) = levi_civita(i, j, k);
1719 break;
1720 case LARGE_ROT:
1721 t_diff_R(i, j, k) =
1722 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, j, k);
1723 break;
1724 default:
1725 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1726 "rotationSelector not handled");
1727 }
1728
1730 t_diff;
1731 t_diff(i, j, l, k) = t_kd(i, l) * t_kd(j, k);
1732
1733 // OpSpatialEqulibrium
1734 {
1735 const auto beta = a * (t_div_P(i) * t_var_w(i));
1736 locJ -= beta;
1737 }
1738 // OpSpatialEquilibrium
1739 {
1740 double beta;
1744 case LARGE_ROT:
1745 case MODERATE_ROT:
1746 beta =
1747
1748 ((t_diff_R(j, k, m) * t_var_omega(m)) * t_u_h1(k, l))
1749
1750 * (t_approx_P(j, n) * t_jac(l, n));
1751
1752 t_beta_dX(I, J) =
1753
1754 ((t_diff_R(j, k, m) * t_var_omega(m)) * t_u_h1(k, l))
1755
1756 * (t_approx_P(j, n) * t_diff(l, n, I, J));
1757
1758 break;
1759 case SMALL_ROT:
1760 beta =
1761
1762 (levi_civita(i, j, k) * t_var_omega(k))
1763
1764 * (t_approx_P(i, n) * t_jac(j, n));
1765
1766 t_beta_dX(I, J) =
1767
1768 (t_diff_R(i, j, k) * t_var_omega(k))
1769
1770 * (t_approx_P(i, n) * t_diff(j, n, I, J));
1771
1772 break;
1773 default:
1774 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1775 "gradApproximator not handled");
1776 break;
1777 };
1778
1779 locJ -= a * beta;
1780 auto t_nf = get_ftensor1(nF);
1781 auto t_base_diff = data.getFTensor1DiffN<3>(gg, 0);
1782 for (int bb = 0; bb != nb_dofs / SPACE_DIM; ++bb) {
1783 t_nf(i) -= a * (t_beta_dX(i, j) * t_base_diff(j));
1784 ++t_nf;
1785 ++t_base_diff;
1786 }
1787 }
1788 // OpSpatialConsistency
1789 {
1790 const auto beta =
1791 (t_h(i, j) - t_kd(i, j)) * (t_var_P(i, n) * t_jac(j, n));
1793 t_beta_dX(I, J) =
1794 (t_h(i, j) - t_kd(i, j)) * (t_var_P(i, n) * t_diff(j, n, I, J));
1795 locJ -= a * beta;
1796 auto t_nf = get_ftensor1(nF);
1797 auto t_base_diff = data.getFTensor1DiffN<3>(gg, 0);
1798 for (int bb = 0; bb != nb_dofs / SPACE_DIM; ++bb) {
1799 t_nf(i) -= a * (t_beta_dX(i, j) * t_base_diff(j));
1800 ++t_nf;
1801 ++t_base_diff;
1802 }
1803 }
1804 // OpSpatialConsistency, cont
1805 {
1806 const auto beta = t_w_l2(i) * t_var_div_P(i);
1807 locJ -= a * beta;
1808 }
1809
1810
1811 next();
1812 }
1813
1815 }
1816
1817private:
1818 const double alphaW;
1819 const double alphaRho;
1820 const double alphaViscousOmega;
1821};
1822
1823
1827 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1828 SmartPetscObj<Vec> assemble_vec,
1829 boost::shared_ptr<TopologicalData> topo_ptr,
1830 const double alpha, const double rho,
1831 const double alpha_viscous_omega = 0)
1833 field_name, data_ptr, topo_ptr, nullptr, assemble_vec, Tag()),
1834 alphaW(alpha), alphaRho(rho) {
1835 if (alpha_viscous_omega)
1838 "OpSensitivityInterior_dX with alpha_viscous_omega != 0 is not "
1839 "implemented yet");
1840 }
1841
1842 MoFEMErrorCode integrate(EntData &data) {
1844
1845#ifndef NDEBUG
1846 if (!dataAtPts)
1847 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1848 "DataAtIntegrationPts pointer is null");
1849#endif // NDEBUG
1850
1851 const int nb_dofs = data.getIndices().size();
1852 if (!nb_dofs)
1854
1855 const int nb_integration_pts = getGaussPts().size2();
1856
1857 const auto v = getVolume();
1858 auto t_w = getFTensor0IntegrationWeight();
1859 auto t_div_P = dataAtPts->getFTensorDivP(nb_integration_pts);
1860 auto t_w_l2 = dataAtPts->getFTensorSmallWL2(nb_integration_pts);
1861 auto t_s_dot_w = dataAtPts->getFTensorSmallWL2Dot(nb_integration_pts);
1862 auto t_s_dot_dot_w =
1863 dataAtPts->getFTensorSmallWL2DotDot(nb_integration_pts);
1864 auto t_h = dataAtPts->getFTensorSmallH(nb_integration_pts);
1865 auto t_levi_kirchhoff =
1866 dataAtPts->getFTensorLeviKirchhoff(nb_integration_pts);
1867 auto t_omega_grad_dot =
1868 dataAtPts->getFTensorRotAxisGradDot(nb_integration_pts);
1869 auto t_R = dataAtPts->getFTensorRotMat(nb_integration_pts);
1870 auto t_u = dataAtPts->getFTensorStretch(nb_integration_pts);
1871
1872 auto t_var_w = dataAtPts->getFTensorVarWL2(nb_integration_pts);
1873 auto t_var_omega = dataAtPts->getFTensorVarRotAxis(nb_integration_pts);
1874 auto t_var_grad_omega =
1875 dataAtPts->getFTensorVarGradRotAxis(nb_integration_pts);
1876 auto t_var_P = dataAtPts->getFTensorVarPiola(nb_integration_pts);
1877 auto t_var_div_P = dataAtPts->getFTensorDivVarPiola(nb_integration_pts);
1878 auto t_det = topoData->getFTensorDetJacobian(nb_integration_pts);
1879 auto t_inv_jac = topoData->getFTensorInvJacobian(nb_integration_pts);
1880
1881 auto w_l2_dot_dot_at_pts = dataAtPts->getSmallWL2DotDotAtPts();
1882 if (w_l2_dot_dot_at_pts->size1() != nb_integration_pts ||
1883 w_l2_dot_dot_at_pts->size2() != SPACE_DIM) {
1884 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
1885 *w_l2_dot_dot_at_pts, nb_integration_pts);
1886 w_l2_dot_dot_at_pts->clear();
1887 }
1888
1889 const auto piola_scale = dataAtPts->piolaScale;
1890 const auto alpha_w = alphaW / piola_scale;
1891 const auto alpha_rho = alphaRho / piola_scale;
1892
1893 const int nb_base_functions = data.getN().size2();
1894 auto t_base_diff = data.getFTensor1DiffN<3>();
1895
1896 auto get_ftensor1 = [](auto &v) {
1898 &v[0], &v[1], &v[2]);
1899 };
1900
1901 auto next = [&]() {
1902 ++t_w;
1903 ++t_div_P;
1904 ++t_w_l2;
1905 ++t_s_dot_w;
1906 ++t_s_dot_dot_w;
1907 ++t_h;
1908 ++t_levi_kirchhoff;
1909 ++t_omega_grad_dot;
1910 ++t_R;
1911 ++t_u;
1912
1913 ++t_var_w;
1914 ++t_var_omega;
1915 ++t_var_grad_omega;
1916 ++t_var_P;
1917 ++t_var_div_P;
1918
1919 ++t_det;
1920 ++t_inv_jac;
1921 };
1922
1928 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1929
1930 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1931
1932 // Calculate the variation of the gradient due to geometry change
1934 t_cof(i, j) = t_det * t_inv_jac(j, i);
1935
1936 double consistency_residual = 0;
1938 consistency_residual =
1939 -0.5 * t_var_P(k, m) * (t_R(k, l) * t_u(l, m)) -
1940 0.5 * t_var_P(k, l) * (t_R(k, m) * t_u(l, m)) +
1941 t_var_P(k, l) * t_kd(k, l);
1942 } else {
1944 t_residuum_P(k, m) = t_h(k, m) - t_kd(k, m);
1945 consistency_residual =
1946 t_var_P(k, m) * (-t_residuum_P(k, m));
1947 }
1948
1949 auto t_nf = get_ftensor1(nF);
1950 int bb = 0;
1951 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1952
1954 t_div_base(i) = -(1 / t_det) * (t_inv_jac(j, i) * t_base_diff(j));
1955
1956 // OpSpatialEquilibrium
1957 t_nf(i) += (t_w * v) *
1958 (t_var_w(k) * (-t_div_P(k) + alpha_w * t_s_dot_w(k) +
1959 alpha_rho * t_s_dot_dot_w(k))) *
1960 t_cof(i, j) * t_base_diff(j);
1961 t_nf(i) += (t_w * v) * (-(t_var_w(k) * t_div_P(k))) * t_div_base(i);
1962
1963 // OpSpatialRotation
1964 t_nf(i) += (t_w * v) * (t_var_omega(k) * (-t_levi_kirchhoff(k))) *
1965 t_cof(i, j) * t_base_diff(j);
1966
1967 // OpSpatialConsistencyP
1968 t_nf(i) += (t_w * v * consistency_residual) * t_cof(i, j) *
1969 t_base_diff(j);
1970
1971 // OpSpatialConsistencyDivTerm
1972 t_nf(i) += (t_w * v) * (t_var_div_P(k) * (-t_w_l2(k))) * t_cof(i, j) *
1973 t_base_diff(j);
1974 t_nf(i) += (t_w * v) * (t_var_div_P(k) * (-t_w_l2(k))) * t_div_base(i);
1975
1976 ++t_nf;
1977 ++t_base_diff;
1978 }
1979 for (; bb != nb_base_functions; ++bb)
1980 ++t_base_diff;
1981
1982 next();
1983 }
1984
1986 }
1987
1988private:
1989 const double alphaW;
1990 const double alphaRho;
1991};
1992
1996 const std::string &field_name,
1997 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1998 SmartPetscObj<Vec> assemble_vec,
1999 boost::shared_ptr<TopologicalData> topo_ptr,
2000 std::vector<boost::shared_ptr<ScalingMethod>> smv,
2001 boost::shared_ptr<double> J_ptr = nullptr)
2003 field_name, data_ptr, topo_ptr, J_ptr, assemble_vec, Tag()),
2004 scalingMethods(smv) {
2005 CHK_THROW_MESSAGE(getMeshsetData(m_field, ms_id), "Get meshset data");
2006 }
2007
2008 MoFEMErrorCode integrate(EntData &data) {
2010
2011 locJ = 0;
2012
2013 if (entsPtr) {
2014 if (entsPtr->find(this->getFEEntityHandle()) == entsPtr->end())
2016 }
2017
2018#ifndef NDEBUG
2019 if (!dataAtPts)
2020 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2021 "DataAtIntegrationPts pointer is null");
2022#endif // NDEBUG
2023
2024 const int nb_dofs = data.getIndices().size();
2025 if (!nb_dofs)
2027
2028 const int nb_integration_pts = getGaussPts().size2();
2029
2030 const auto v = getVolume();
2031 auto t_w = getFTensor0IntegrationWeight();
2032 auto t_var_w_l2 = dataAtPts->getFTensorVarWL2(nb_integration_pts);
2033 auto t_det = topoData->getFTensorDetJacobian(nb_integration_pts);
2034 auto t_inv_jac = topoData->getFTensorInvJacobian(nb_integration_pts);
2035
2036 const int nb_base_functions = data.getN().size2();
2037 auto t_base_diff = data.getFTensor1DiffN<3>();
2038
2039 auto get_ftensor1 = [](auto &v) {
2041 &v[0], &v[1], &v[2]);
2042 };
2043
2044 auto next = [&]() {
2045 ++t_w;
2046 ++t_var_w_l2;
2047 ++t_inv_jac;
2048 ++t_det;
2049 };
2050
2052
2053 auto get_scale = [&](const double t) {
2054 double s = 1;
2055 for (auto &o : scalingMethods) {
2056
2057
2058 s *= o->getScale(t);
2059 }
2060 return s;
2061 };
2062
2063 auto scale = get_scale(getFEMethod()->ts_t);
2064
2065 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2066 const double alpha = scale * t_w * v;
2067
2068 double adjount = t_var_w_l2(i) * tForce(i);
2069 locJ += (alpha * t_det) * adjount;
2070
2072 t_cof(i, j) = t_det * t_inv_jac(j, i);
2073
2074 auto t_nf = get_ftensor1(nF);
2075 int bb = 0;
2076 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
2077 t_nf(i) += (alpha * adjount) * t_cof(i, J) * t_base_diff(J);
2078
2079 ++t_nf;
2080 ++t_base_diff;
2081 }
2082 for (; bb != nb_base_functions; ++bb)
2083 ++t_base_diff;
2084
2085 next();
2086 }
2087
2089 }
2090
2091protected:
2092
2093 MoFEMErrorCode getMeshsetData(MoFEM::Interface &m_field, int ms_id) {
2095
2096 auto cubit_meshset_ptr =
2097 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(ms_id,
2098 BLOCKSET);
2099
2100 std::vector<double> block_data;
2101 CHKERR cubit_meshset_ptr->getAttributes(block_data);
2102
2103 if (block_data.size() != SPACE_DIM) {
2104 MOFEM_LOG("SELF", Sev::warning)
2105 << "BLOCKSET is expected to have " << SPACE_DIM
2106 << " attributes but has size " << block_data.size();
2107 if (block_data.size() < SPACE_DIM) {
2108 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2109 "Size of attribute in BLOCKSET is too small");
2110 }
2111 }
2112
2113 for (unsigned int ii = 0; ii != SPACE_DIM; ++ii) {
2114 tForce(ii) = block_data[ii];
2115 }
2116
2117 MOFEM_LOG("WORLD", Sev::noisy)
2118 << "Flux blockset " << cubit_meshset_ptr->getName();
2119 MOFEM_LOG("WORLD", Sev::noisy)
2120 << "Number of attributes " << block_data.size();
2121
2122 this->entsPtr = boost::make_shared<Range>();
2123 CHKERR m_field.get_moab().get_entities_by_handle(cubit_meshset_ptr->meshset,
2124 *(entsPtr), true);
2125
2126 MOFEM_LOG("WORLD", Sev::noisy) << "tForce vector initialised: " << tForce;
2127 MOFEM_LOG("WORLD", Sev::noisy) << "Number of elements " << entsPtr->size();
2128
2129
2130
2132 }
2133
2135 boost::shared_ptr<Range> entsPtr;
2136 std::vector<boost::shared_ptr<ScalingMethod>> scalingMethods;
2137};
2138
2139} // namespace EshelbianPlasticity
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
std::string type
#define FTENSOR_INDEXES(DIM,...)
#define FTENSOR_INDEX(DIM, I)
constexpr double a
constexpr int SPACE_DIM
Kronecker Delta class.
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ NOSPACE
Definition definitions.h:83
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ BLOCKSET
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
const char features[]
constexpr auto t_kd
#define MOFEM_LOG(channel, severity)
Log.
FTensor::Index< 'i', SPACE_DIM > i
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
EntitiesFieldData::EntData EntData
static MatrixDouble getTopologicalAnalyticalExpr(OP_PTR op_ptr, const std::string &block_name)
static constexpr auto size_symm
MatrixDouble analytical_expr_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_ref_coords, MatrixDouble &m_ref_normals, const std::string block_name)
constexpr std::enable_if<(Dim0<=2 &&Dim1<=2), Tensor2_Expr< Levi_Civita< T >, T, Dim0, Dim1, i, j > >::type levi_civita(const Index< i, Dim0 > &, const Index< j, Dim1 > &)
levi_civita functions to make for easy adhoc use
constexpr IntegrationType I
constexpr AssemblyType A
double h
constexpr double t
plate stiffness
Definition plate.cpp:58
constexpr auto field_name
FTensor::Index< 'm', 3 > m
static PetscBool l2UserBaseScale
static enum RotSelector rotSelector
static enum RotSelector gradApproximator
static double physicalDt
static PetscBool physicalTimeFlg
static double currentPhysicalTime
MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override
boost::shared_ptr< AnalyticalDisplacementBcVec > bcDispPtr
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenSideDataPtr
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
OpAnalyticalDispBc_dX(const std::string &field_name, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_side_data_ptr, boost::shared_ptr< AnalyticalDisplacementBcVec > bc_disp_ptr, std::map< std::string, boost::shared_ptr< ScalingMethod > > smv, boost::shared_ptr< TopologicalData > topo_ptr, SmartPetscObj< Vec > vec, boost::shared_ptr< double > J_ptr=nullptr, Tag tag=Tag())
OpAssembleBrokenFaceTopologicalDerivativeImplBase(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, boost::shared_ptr< TopologicalData > topo_ptr, boost::shared_ptr< double > J_ptr, SmartPetscObj< Vec > assemble_vec, Tag topo_tag, boost::shared_ptr< Range > ents_ptr=nullptr)
OpAssembleTopologicalObjectiveDerivativeImplBase(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< TopologicalData > topo_ptr, boost::shared_ptr< double > J_ptr, SmartPetscObj< Vec > assemble_vec, Tag topo_tag)
MoFEMErrorCode assemble(int side, EntityType type, EntData &data) override
OpBodyForce_dX(MoFEM::Interface &m_field, int ms_id, const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, SmartPetscObj< Vec > assemble_vec, boost::shared_ptr< TopologicalData > topo_ptr, std::vector< boost::shared_ptr< ScalingMethod > > smv, boost::shared_ptr< double > J_ptr=nullptr)
MoFEMErrorCode getMeshsetData(MoFEM::Interface &m_field, int ms_id)
std::vector< boost::shared_ptr< ScalingMethod > > scalingMethods
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override
OpBrokenAnalyticalTractionBc_dX(std::string field_name, boost::shared_ptr< AnalyticalTractionBcVec > bc_data, boost::shared_ptr< MatrixDouble > lambda_hybrid_ptr, boost::shared_ptr< TopologicalData > topo_ptr, std::map< std::string, boost::shared_ptr< ScalingMethod > > smv, SmartPetscObj< Vec > vec, boost::shared_ptr< double > J_ptr=nullptr, Tag tag=Tag())
MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
OpBrokenTractionBc_dX(std::string field_name, boost::shared_ptr< TractionBcVec > bc_data, boost::shared_ptr< MatrixDouble > lambda_hybrid_ptr, boost::shared_ptr< TopologicalData > topo_ptr, std::map< std::string, boost::shared_ptr< ScalingMethod > > smv, SmartPetscObj< Vec > vec, boost::shared_ptr< double > J_ptr=nullptr, Tag tag=Tag())
OpDispBc_dX(const std::string &field_name, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_side_data_ptr, boost::shared_ptr< BcDispVec > bc_disp_ptr, std::map< std::string, boost::shared_ptr< ScalingMethod > > smv, boost::shared_ptr< TopologicalData > topo_ptr, SmartPetscObj< Vec > vec, boost::shared_ptr< double > J_ptr=nullptr, Tag tag=Tag())
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenSideDataPtr
MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override
OpSensitivityInteriorGradient(const std::string field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< TopologicalData > topo_ptr, SmartPetscObj< Vec > assemble_vec, const double alpha, const double rho, const double alpha_viscous_omega=0, boost::shared_ptr< double > J_ptr=nullptr)
OpSensitivityInterior_dX(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, SmartPetscObj< Vec > assemble_vec, boost::shared_ptr< TopologicalData > topo_ptr, const double alpha, const double rho, const double alpha_viscous_omega=0)
MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override
OpTauStabilisation_dX(const std::string &field_name, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_disp_data_ptr, boost::shared_ptr< MatrixDouble > hybrid_disp_ptr, boost::shared_ptr< MatrixDouble > var_hybrid_disp_ptr, boost::shared_ptr< TopologicalData > topo_ptr, const double alpha_tau, SmartPetscObj< Vec > vec, boost::shared_ptr< double > J_ptr=nullptr, Tag tag=Tag())
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenDispDataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpTopologicalObjectivePythonImpl(boost::shared_ptr< DataAtIntegrationPts > data_at_pts_ptr, boost::shared_ptr< TopologicalData > topo_p, boost::shared_ptr< ObjectiveFunctionData > python_ptr, const ObjectiveModelType eval_energy_model=PYTHON_MODEL)
@ NO_STRETCH_NONLINEAR
No-stretch nonlinear formulation.
static auto diffExp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:100
virtual moab::Interface & get_moab()=0
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
MatrixDouble & getDiffN(const FieldApproximationBase base)
get derivatives of base functions
const VectorFieldEntities & getFieldEntities() const
Get field entities (const version)
auto getFTensor2N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
auto getFTensor1DiffN(const FieldApproximationBase base)
Get derivatives of base functions.
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
const VectorDouble & getFieldData() const
Get DOF values on entity.
auto getFTensor1N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
const VectorInt & getIndices() const
Get global indices of degrees of freedom on entity.
auto getFTensor0IntegrationWeight()
Get integration weights.
const FEMethod * getFEMethod() const
Return raw pointer to Finite Element Method object.
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
VectorDouble nF
local right hand side vector
double rho
Definition plastic.cpp:144
double scale
Definition plastic.cpp:123