v0.16.0
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 auto stress_full_ptr = boost::make_shared<MatrixDouble>();
381 auto get_stress_full =
382 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
383 DL>::size(*stress_full_ptr, nb_gauss_pts);
384 stress_full_ptr->clear();
385 auto strain_full_ptr = boost::make_shared<MatrixDouble>();
386 auto get_strain_full =
387 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
388 DL>::size(*strain_full_ptr, nb_gauss_pts);
389 strain_full_ptr->clear();
390
391 auto t_stress = get_stress_full();
392 auto t_strain = get_strain_full();
393
394 auto t_biot = dataAtPts->getFTensorAdjointPdstretch(nb_gauss_pts);
395 auto t_u = dataAtPts->getFTensorStretch(nb_gauss_pts);
396
397 auto next = [&]() {
398 ++t_stress;
399 ++t_strain;
400 ++t_biot;
401 ++t_u;
402 };
403
405
406 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
407 // we have to handle all variants, that will render how the Jacobian
408 // gradient is evaluated.
409 t_stress(i, j) = t_biot(i, j);
410 t_strain(i, j) = t_u(i, j);
411 next();
412 }
413
414 auto evaluate_python_objective = [&]() {
416 if (!pythonPtr)
417 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
418 "ObjectiveFunctionData pointer is null");
419
420 auto &coords = OP::getCoordsAtGaussPts();
421 CHKERR pythonPtr->evalInteriorObjectiveFunction(
422 coords, dataAtPts->getSmallWL2AtPts(), stress_full_ptr, strain_full_ptr,
423 topoData->getObjAtPts(), false);
424 CHKERR pythonPtr->evalInteriorObjectiveGradientStrain(
425 coords, dataAtPts->getSmallWL2AtPts(), stress_full_ptr, strain_full_ptr,
426 topoData->getObjDStrainAtPts(), false);
427 CHKERR pythonPtr->evalInteriorObjectiveGradientU(
428 coords, dataAtPts->getSmallWL2AtPts(), stress_full_ptr, strain_full_ptr,
429 topoData->getObjDDisplacementAtPts(), false);
430 CHKERR pythonPtr->evalInteriorObjectiveGradientStress(
431 coords, dataAtPts->getSmallWL2AtPts(), stress_full_ptr, strain_full_ptr,
432 topoData->getObjDStressAtPts(), false);
434 };
435
436 auto evaluate_energy_of_hencky_model = [&]() {
438
439 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
440 *topoData->getObjDDisplacementAtPts(), nb_gauss_pts);
441 topoData->getObjDDisplacementAtPts()->clear();
442 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
443 DL>::size(*topoData->getObjDStressAtPts(), nb_gauss_pts);
444 topoData->getObjDStressAtPts()->clear();
445 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
446 *topoData->getObjDRotationAtPts(), nb_gauss_pts);
447
448 auto eval_evergy = [&](auto &&t_D) {
449 auto get_obj =
450 MatrixSizeHelper<GetFTensor1FromMatType<1, -1, DL>, DL>::size(
451 *topoData->getObjAtPts(), nb_gauss_pts);
452 auto get_dstrain_obj =
453 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
454 DL>::size(*topoData->getObjDStrainAtPts(),
455 nb_gauss_pts);
456 auto t_obj = get_obj();
457 auto t_dstrain_obj = get_dstrain_obj();
458 auto t_log_u = dataAtPts->getFTensorLogStretchTotal(nb_gauss_pts);
459 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
460 t_obj(0) = 0.5 * (t_log_u(i, j) * t_D(i, j, k, l) * t_log_u(k, l));
461 t_dstrain_obj(i, j) = t_D(i, j, k, l) * t_log_u(k, l);
462 ++t_log_u;
463 ++t_obj;
464 ++t_dstrain_obj;
465 ++t_D;
466 }
467 };
468
470 eval_evergy(
471 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(dataAtPts->matD));
472 } else {
473 eval_evergy(getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->matD));
474 }
475
476 topoData->getObjDRotationAtPts()->clear();
478 };
479
480 auto evaluate_energy_of_hencky_model_nostreach = [&]() {
482
483 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
484 *topoData->getObjDDisplacementAtPts(), nb_gauss_pts);
485 topoData->getObjDDisplacementAtPts()->clear();
486 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
487 DL>::size(*topoData->getObjDStrainAtPts(), nb_gauss_pts);
488 topoData->getObjDStrainAtPts()->clear();
489 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
490 *topoData->getObjDRotationAtPts(), nb_gauss_pts);
491 topoData->getObjDRotationAtPts()->clear();
492
493 auto eval_evergy = [&](auto &&t_inv_D) {
494 auto get_obj =
495 MatrixSizeHelper<GetFTensor1FromMatType<1, -1, DL>, DL>::size(
496 *topoData->getObjAtPts(), nb_gauss_pts);
497 auto get_dstress_obj =
498 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
499 DL>::size(*topoData->getObjDStressAtPts(),
500 nb_gauss_pts);
501 auto t_obj = get_obj();
502 auto t_dstress_obj = get_dstress_obj();
503 auto t_stress = dataAtPts->getFTensorAdjointPdstretch(nb_gauss_pts);
504 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
505 t_obj(0) =
506 0.5 * (t_stress(i, j) * t_inv_D(i, j, k, l) * t_stress(k, l));
507 t_dstress_obj(i, j) = t_inv_D(i, j, k, l) * t_stress(k, l);
508 ++t_stress;
509 ++t_obj;
510 ++t_dstress_obj;
511 ++t_inv_D;
512 }
513 };
514
516 eval_evergy(
517 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(dataAtPts->matInvD));
518 } else {
519 eval_evergy(
520 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->matInvD));
521 }
523 };
524
525 auto conversion_of_biot_stress = [&]() {
527 // Python differentiates the objective with respect to Biot stress. The
528 // material equations need the corresponding Piola and rotation derivatives.
529 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
530 *topoData->getObjDRotationAtPts(), nb_gauss_pts);
531 topoData->getObjDRotationAtPts()->clear();
532
533 auto t_obj_dbiot = topoData->getFTensorObjDStress(nb_gauss_pts);
534 auto t_obj_domega = topoData->getFTensorObjDRotation(nb_gauss_pts);
535 auto t_R = dataAtPts->getFTensorRotMat(nb_gauss_pts);
536 auto t_P = dataAtPts->getFTensorApproxP(nb_gauss_pts);
537 auto t_grad_h1 = dataAtPts->getFTensorSmallWGradH1(nb_gauss_pts);
538 auto t_omega = dataAtPts->getFTensorRotAxis(nb_gauss_pts);
539
545 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
546
547 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
549 t_dJ_dbiot(l, o) = t_obj_dbiot(l, o);
550
552 case SMALL_ROT:
553 // In the linear/small formulation Python sees the Piola field itself:
554 // B = P. There is no rotation or H1-gradient pullback to apply.
555 t_obj_dbiot(i, k) = t_dJ_dbiot(i, k);
556 t_obj_domega(m) = 0;
557 break;
558 case NO_H1_CONFIGURATION: {
561 case LARGE_ROT:
562 t_diff_R(i, l, m) =
563 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, l, m);
564 break;
565 default:
566 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
567 "rotationSelector not handled");
568 }
569
570 // Python sees B = R^T P.
571 t_obj_dbiot(i, k) = t_R(i, l) * t_dJ_dbiot(l, k);
572 t_obj_domega(m) = t_dJ_dbiot(l, k) * t_diff_R(i, l, m) * t_P(i, k);
573 } break;
574 case LARGE_ROT:
575 case MODERATE_ROT: {
577 t_h1(o, k) = t_kd(o, k) + t_grad_h1(o, k);
578
581 case SMALL_ROT:
582 t_diff_R(i, l, m) = levi_civita(i, l, m);
583 break;
584 case LARGE_ROT:
585 t_diff_R(i, l, m) =
586 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, l, m);
587 break;
588 default:
589 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
590 "rotationSelector not handled");
591 }
592
593 // Python sees B = R^T P H1^T.
594 t_obj_dbiot(i, k) = t_R(i, l) * (t_dJ_dbiot(l, o) * t_h1(o, k));
595 t_obj_domega(m) =
596 t_dJ_dbiot(l, o) * (t_diff_R(i, l, m) * t_P(i, k)) * t_h1(o, k);
597 } break;
598 default:
599 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
600 "gradApproximator not handled");
601 }
602
603 ++t_obj_dbiot;
604 ++t_obj_domega;
605 ++t_R;
606 ++t_P;
607 ++t_grad_h1;
608 ++t_omega;
609 }
610
612 };
613
614 auto conversion_of_stretch = [&]() {
616 // Python sees the physical stretch tensor. The stretch field stores log
617 // stretch, so convert dJ/dU to dJ/dlogU once here.
618 auto t_obj_dstretch = topoData->getFTensorObjDStrain(nb_gauss_pts);
619 auto t_diff_stretch = dataAtPts->getFTensorDiffStretch(nb_gauss_pts);
620
625
626 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
628 t_dJ_dstretch(i, j) = t_obj_dstretch(i, j);
629
630 t_obj_dstretch(k, l) = t_dJ_dstretch(i, j) * t_diff_stretch(i, j, k, l);
631
632 ++t_obj_dstretch;
633 ++t_diff_stretch;
634 }
635
637 };
638
639 auto conversion_of_stretch_to_stress_for_no_stretch = [&](auto t_inv_D) {
641 // In no-stretch mode, log stretch is computed from the stress field. Fold
642 // the objective stretch derivative into the stress derivative buffer.
643 auto t_obj_dstress = topoData->getFTensorObjDStress(nb_gauss_pts);
644 auto t_obj_dstretch = topoData->getFTensorObjDStrain(nb_gauss_pts);
645
650
651 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
653 t_dstretch_dstress(i, j) =
654 ((t_obj_dstretch(k, l) || t_obj_dstretch(l, k)) / 2.) *
655 t_inv_D(k, l, i, j);
656
657 t_obj_dstress(i, j) += t_dstretch_dstress(i, j);
658
659 ++t_obj_dstress;
660 ++t_obj_dstretch;
661 ++t_inv_D;
662 }
663
665 };
666
667 switch (evalEnergyModel) {
668 case PYTHON_MODEL:
669 CHKERR evaluate_python_objective();
670 CHKERR conversion_of_biot_stress();
673 CHKERR conversion_of_stretch_to_stress_for_no_stretch(
674 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(dataAtPts->matInvD));
675 } else {
676 CHKERR conversion_of_stretch_to_stress_for_no_stretch(
677 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->matInvD));
678 }
679 } else {
680 CHKERR conversion_of_stretch();
681 }
682 break;
683 case HENCKY_MODEL:
685 CHKERR evaluate_energy_of_hencky_model_nostreach();
686 CHKERR conversion_of_biot_stress();
687 } else {
688 CHKERR evaluate_energy_of_hencky_model();
689 }
690 break;
691 default:
692 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
693 "Objective model type not handled");
694 }
695
697}
698
699MoFEMErrorCode OpInteriorJImpl::integrate(EntData &data) {
701 locJ = 0;
702
703#ifndef NDEBUG
704 if (!topoData)
705 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
706 "Topological data pointer is null");
707#endif // NDEBUG
708
709 const int nb_dofs = data.getIndices().size();
710 if (!nb_dofs)
712
713 const int nb_integration_pts = getGaussPts().size2();
714
715 const auto v = getVolume();
716 auto t_w = getFTensor0IntegrationWeight();
717 auto t_obj = topoData->getFTensorObj(nb_integration_pts);
718 auto t_obj_dP = topoData->getFTensorObjDStress(nb_integration_pts);
719 auto t_obj_dStrain = topoData->getFTensorObjDStrain(nb_integration_pts);
720 auto t_obj_dU = topoData->getFTensorObjDDisplacement(nb_integration_pts);
721 auto t_P = dataAtPts->getFTensorApproxP(nb_integration_pts);
722 auto t_det = topoData->getFTensorDetJacobian(nb_integration_pts);
723 auto t_inv_jac = topoData->getFTensorInvJacobian(nb_integration_pts);
724 auto t_jac = topoData->getFTensorJacobian(nb_integration_pts);
725
726 auto next = [&]() {
727 ++t_w;
728 ++t_obj;
729 ++t_obj_dP;
730 ++t_obj_dStrain;
731 ++t_obj_dU;
732 ++t_P;
733 ++t_det;
734 ++t_inv_jac;
735 ++t_jac;
736 };
737
739 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
740
741 auto get_ftensor1 = [](auto &v) {
743 &v[0], &v[1], &v[2]);
744 };
745
746 nF.clear();
747
748 const int nb_base_functions = data.getN().size2();
749 auto t_base_diff = data.getFTensor1DiffN<SPACE_DIM>();
750 for (int gg = 0; gg != nb_integration_pts; ++gg) {
751 locJ += (t_w * v * t_det) * t_obj;
752
754 t_cof(i, j) = t_det * t_inv_jac(j, i);
755
757 t_dJ_dX(I, J) =
758
759 t_obj * t_cof(I, J)
760
761 +
762
763 t_obj_dP(i, j) * (t_kd(j, I) * (t_kd(k, J) * t_P(i, k)) -
764 t_inv_jac(I, J) * t_jac(j, k) * t_P(i, k));
765
766 auto t_nf = get_ftensor1(nF);
767 int bb = 0;
768 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
769 t_nf(i) += (t_w * v) * t_dJ_dX(i, j) * t_base_diff(j);
770 ++t_nf;
771 ++t_base_diff;
772 }
773 for (; bb != nb_base_functions; ++bb)
774 ++t_base_diff;
775
776 next();
777 }
778
780}
781
782MoFEMErrorCode OpJ_dPImpl::integrate(EntData &data) {
784
785#ifndef NDEBUG
786 if (!topoData)
787 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
788 "Topological data pointer is null");
789#endif // NDEBUG
790
791 const int nb_dofs = data.getIndices().size();
792 if (!nb_dofs)
794
795 const int nb_integration_pts = data.getN().size1();
796
797 const auto v = getVolume();
798 auto t_w = getFTensor0IntegrationWeight();
799 const int nb_base_functions = data.getN().size2() / SPACE_DIM;
800 auto t_row_base_fun = data.getFTensor1N<SPACE_DIM>();
801
804
805 auto get_ftensor1 = [](auto &v) {
807 &v[0], &v[1], &v[2]);
808 };
809
810 auto t_obj_dP = topoData->getFTensorObjDStress(nb_integration_pts);
811
812 for (int gg = 0; gg != nb_integration_pts; ++gg) {
813 const double a = v * t_w;
814 auto t_nf = get_ftensor1(nF);
815
816 int bb = 0;
817 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
818 t_nf(i) += a * t_row_base_fun(j) * t_obj_dP(i, j);
819 ++t_nf;
820 ++t_row_base_fun;
821 }
822 for (; bb != nb_base_functions; ++bb)
823 ++t_row_base_fun;
824
825 ++t_w;
826 ++t_obj_dP;
827 }
828
830}
831
832MoFEMErrorCode OpJ_dBubbleImpl::integrate(EntData &data) {
834
835#ifndef NDEBUG
836 if (!topoData)
837 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
838 "Topological data pointer is null");
839#endif // NDEBUG
840
841 const int nb_dofs = data.getIndices().size();
842 if (!nb_dofs)
844
845 const int nb_integration_pts = data.getN().size1();
846
847 const auto v = getVolume();
848 auto t_w = getFTensor0IntegrationWeight();
849 const int nb_base_functions = data.getN().size2() / (SPACE_DIM * SPACE_DIM);
850 auto t_row_base_fun = data.getFTensor2N<SPACE_DIM, SPACE_DIM>();
851 auto t_obj_dP = topoData->getFTensorObjDStress(nb_integration_pts);
852
855
856 auto get_ftensor0 = [](auto &v) {
858 };
859
860 for (int gg = 0; gg != nb_integration_pts; ++gg) {
861 const double a = v * t_w;
862 auto t_nf = get_ftensor0(nF);
863
864 int bb = 0;
865 for (; bb != nb_dofs; ++bb) {
866 t_nf += a * t_row_base_fun(i, j) * t_obj_dP(i, j);
867 ++t_nf;
868 ++t_row_base_fun;
869 }
870 for (; bb != nb_base_functions; ++bb)
871 ++t_row_base_fun;
872
873 ++t_w;
874 ++t_obj_dP;
875 }
876
878}
879
880MoFEMErrorCode OpJ_dwImpl::integrate(EntData &data) {
882
883#ifndef NDEBUG
884 if (!topoData)
885 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
886 "Topological data pointer is null");
887#endif // NDEBUG
888
889 const int nb_dofs = data.getIndices().size();
890 if (!nb_dofs)
892
893 const int nb_integration_pts = data.getN().size1();
894
895 const auto v = getVolume();
896 auto t_w = getFTensor0IntegrationWeight();
897 const int nb_base_functions = data.getN().size2();
898 auto t_row_base_fun = data.getFTensor0N();
899 auto t_obj_dw = topoData->getFTensorObjDDisplacement(nb_integration_pts);
900
902
903 auto get_ftensor1 = [](auto &v) {
905 &v[0], &v[1], &v[2]);
906 };
907
908 for (int gg = 0; gg != nb_integration_pts; ++gg) {
909 const double a = v * t_w;
910 auto t_nf = get_ftensor1(nF);
911
912 int bb = 0;
913 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
914 t_nf(i) += a * t_row_base_fun * t_obj_dw(i);
915 ++t_nf;
916 ++t_row_base_fun;
917 }
918 for (; bb != nb_base_functions; ++bb)
919 ++t_row_base_fun;
920
921 ++t_w;
922 ++t_obj_dw;
923 }
924
926}
927
928MoFEMErrorCode OpJ_dOmegaImpl::integrate(EntData &data) {
930
931#ifndef NDEBUG
932 if (!topoData)
933 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
934 "Topological data pointer is null");
935#endif // NDEBUG
936
937 const int nb_dofs = data.getIndices().size();
938 if (!nb_dofs)
940
941 const int nb_integration_pts = data.getN().size1();
942
943 const auto v = getVolume();
944 auto t_w = getFTensor0IntegrationWeight();
945 const int nb_base_functions = data.getN().size2();
946 auto t_row_base_fun = data.getFTensor0N();
947 auto t_obj_domega = topoData->getFTensorObjDRotation(nb_integration_pts);
948
950
951 auto get_ftensor1 = [](auto &v) {
953 &v[0], &v[1], &v[2]);
954 };
955
956 for (int gg = 0; gg != nb_integration_pts; ++gg) {
957 const double a = v * t_w;
958 auto t_nf = get_ftensor1(nF);
959
960 int bb = 0;
961 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
962 t_nf(i) += a * t_row_base_fun * t_obj_domega(i);
963 ++t_nf;
964 ++t_row_base_fun;
965 }
966 for (; bb != nb_base_functions; ++bb)
967 ++t_row_base_fun;
968
969 ++t_w;
970 ++t_obj_domega;
971 }
972
974}
975
976MoFEMErrorCode dJ_duGammaImpl::integrate(EntData &data) {
978
979#ifndef NDEBUG
980 if (!topoData)
981 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
982 "Topological data pointer is null");
983#endif // NDEBUG
984
985 const int nb_dofs = data.getIndices().size();
986 if (!nb_dofs)
988
989 const int nb_integration_pts = data.getN().size1();
990
991 auto t_w = getFTensor0IntegrationWeight();
992 const int nb_base_functions = data.getN().size2();
993 auto t_row_base_fun = data.getFTensor0N();
994 auto t_obj_du_gamma =
995 topoData->getFTensorObjDDisplacement(nb_integration_pts);
996
998
999 auto get_ftensor1 = [](auto &v) {
1001 &v[0], &v[1], &v[2]);
1002 };
1003
1004 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1005 const double a = t_w * getMeasure();
1006 auto t_nf = get_ftensor1(nF);
1007
1008 int bb = 0;
1009 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1010 t_nf(i) += a * t_row_base_fun * t_obj_du_gamma(i);
1011 ++t_nf;
1012 ++t_row_base_fun;
1013 }
1014 for (; bb != nb_base_functions; ++bb)
1015 ++t_row_base_fun;
1016
1017 ++t_w;
1018 ++t_obj_du_gamma;
1019 }
1020
1022}
1023
1026
1027#ifndef NDEBUG
1028 if (!topoData)
1029 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1030 "Topological data pointer is null");
1031#endif // NDEBUG
1032
1033 const int nb_dofs = data.getIndices().size();
1034 if (!nb_dofs)
1036
1037 const int nb_integration_pts = OP::getGaussPts().size2();
1038
1039 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1040 auto t_w = OP::getFTensor0IntegrationWeight();
1041 const int nb_base_functions = data.getN().size2() / SPACE_DIM;
1042 auto t_row_base_fun = data.getFTensor1N<SPACE_DIM>();
1043 auto t_obj_dtraction =
1044 topoData->getFTensorObjDDisplacement(nb_integration_pts);
1045
1048
1049 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1050 auto t_nf = getFTensor1FromPtr<SPACE_DIM>(&*OP::locF.begin());
1051 int bb = 0;
1052 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1053 t_nf(i) +=
1054 t_w * (t_row_base_fun(j) * t_normal(j)) * t_obj_dtraction(i) * 0.5;
1055 ++t_nf;
1056 ++t_row_base_fun;
1057 }
1058 for (; bb != nb_base_functions; ++bb)
1059 ++t_row_base_fun;
1060
1061 ++t_w;
1062 ++t_normal;
1063 ++t_obj_dtraction;
1064 }
1065
1067}
1068
1069MoFEMErrorCode OpTauStabilisation_dX::integrate(int, EntityType,
1070 EntData &data) {
1072 locJ = 0;
1073
1074#ifndef NDEBUG
1075 if (!topoData)
1076 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1077 "Topological data pointer is null");
1078 if (!brokenDispDataPtr)
1079 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1080 "Broken displacement data pointer is null");
1081 if (!hybridDispPtr)
1082 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1083 "Hybrid displacement pointer is null");
1084 if (!varHybridDispPtr)
1085 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1086 "Adjoint hybrid displacement pointer is null");
1087#endif // NDEBUG
1088
1089 const int nb_dofs = data.getIndices().size();
1090 if (!nb_dofs)
1092
1093 const int nb_integration_pts = getGaussPts().size2();
1094 const int nb_base_functions = data.getN().size2();
1095
1096#ifndef NDEBUG
1097 if (this->nF.size() != nb_dofs)
1098 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1099 "Size of nF %ld != nb_dofs %d", this->nF.size(), nb_dofs);
1100 if (data.getDiffN().size1() != nb_integration_pts)
1101 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1102 "Differential of base functions should have the same number of "
1103 "integration points as the data");
1104 if (data.getDiffN().size2() != nb_base_functions * 2)
1105 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1106 "Differential of base functions should have the same number of "
1107 "base functions as the data");
1108#endif // NDEBUG
1109
1113
1114 auto &coords = getCoords();
1115 // Tau scale is based on the mesh triangle coordinates, not on the perturbed
1116 // material-position field. Treat h as constant with respect to X.
1117 const double h = std::get<2>(Tools::getTricircumcenter3d(coords.data().data()));
1118
1119 auto t_w = getFTensor0IntegrationWeight();
1120 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1121 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1122 auto t_u_hybrid = getFTensor1FromMat<SPACE_DIM, -1, DL>(*hybridDispPtr);
1123 auto t_var_u_hybrid =
1124 getFTensor1FromMat<SPACE_DIM, -1, DL>(*varHybridDispPtr);
1125 auto t_diff_base = data.getFTensor1DiffN<2>();
1126
1127 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1129 t_normal(j) =
1130 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1131
1132 double area = std::sqrt(t_normal(i) * t_normal(i));
1134 t_da(i) = t_normal(i) / area;
1135 area /= 2.;
1136 t_da(i) /= 2.;
1137
1138 double tau_density = 0;
1139 for (auto &bd : *brokenDispDataPtr) {
1140 auto t_u_broken =
1141 getFTensor1FromMat<SPACE_DIM, -1, DL>(bd.getFlux(), nb_integration_pts);
1142 auto t_var_u_broken = getFTensor1FromMat<SPACE_DIM, -1, DL>(
1143 bd.getVarFlux(), nb_integration_pts);
1144 for (int ss = 0; ss != gg; ++ss) {
1145 ++t_u_broken;
1146 ++t_var_u_broken;
1147 }
1148
1149 // This is the adjoint-weighted material derivative of the four tau
1150 // stabilisation residual blocks:
1151 // u_gamma-u_gamma, L2-L2, u_gamma-L2, and L2-u_gamma.
1152 const double hybrid_hybrid = t_var_u_hybrid(i) * t_u_hybrid(i);
1153 const double broken_broken = t_var_u_broken(i) * t_u_broken(i);
1154 const double hybrid_broken = -t_var_u_hybrid(i) * t_u_broken(i);
1155 const double broken_hybrid = -t_var_u_broken(i) * t_u_hybrid(i);
1156 tau_density +=
1157 hybrid_hybrid + broken_broken + hybrid_broken + broken_hybrid;
1158 }
1159
1160 const double tau = alphaTau / h;
1161 locJ += t_w * tau * area * tau_density;
1162
1163 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1164 int rr = 0;
1165 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1167 t_normal_dX(j, I) =
1168 (FTensor::levi_civita(i, j, I) * t_tangent2(i)) * t_diff_base(N0) +
1169 (FTensor::levi_civita(I, j, k) * t_tangent1(k)) * t_diff_base(N1);
1170
1171 t_nf(I) +=
1172 t_w * alphaTau * tau_density * (t_da(i) * t_normal_dX(i, I)) / h;
1173 ++t_diff_base;
1174 ++t_nf;
1175 }
1176 for (; rr != nb_base_functions; ++rr)
1177 ++t_diff_base;
1178
1179 ++t_w;
1180 ++t_tangent1;
1181 ++t_tangent2;
1182 ++t_u_hybrid;
1183 ++t_var_u_hybrid;
1184 }
1185
1187}
1188
1189MoFEMErrorCode OpDispBc_dX::integrate(int, EntityType type, EntData &data) {
1191 locJ = 0;
1192
1193#ifndef NDEBUG
1194 if (!brokenSideDataPtr)
1195 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1196 "Broken side data pointer is null");
1197#endif // NDEBUG
1198
1199
1200 const int nb_dofs = data.getIndices().size();
1201 if (!nb_dofs)
1203
1204 const int nb_integration_pts = getGaussPts().size2();
1205 const int nb_base_functions = data.getN().size2();
1206
1207 if (data.getDiffN().size1() != nb_integration_pts)
1208 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1209 "Differential of base functions should have the same number of "
1210 "integration points as the data");
1211 if (data.getDiffN().size2() != nb_base_functions * 2)
1212 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1213 "Differential of base functions should have the same number of "
1214 "base functions as the data");
1215
1216 double time = getFEMethod()->ts_t;
1219
1221
1224
1225 const EntityHandle fe_ent = getFEEntityHandle();
1226 for (auto &bc : *bcDispPtr) {
1227 if (bc.faces.find(fe_ent) == bc.faces.end())
1228 continue;
1229
1230 double scale = 1;
1231 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1232 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1233 } else {
1234 MOFEM_LOG("SELF", Sev::warning)
1235 << "No scaling method found for " << bc.blockName;
1236 }
1237
1238 FTensor::Tensor1<double, SPACE_DIM> t_bc_disp(bc.vals[0], bc.vals[1],
1239 bc.vals[2]);
1240 t_bc_disp(i) *= scale;
1241
1242 for (auto &bd : *brokenSideDataPtr) {
1243 auto t_w = getFTensor0IntegrationWeight();
1244 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1245 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1246 auto t_var_flux =
1247 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(bd.getVarFlux());
1248 auto t_diff_base = data.getFTensor1DiffN<2>();
1249
1250 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1251 const double a = 0.5 * bd.getSense() * t_w;
1252
1254 t_normal(j) =
1255 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1256
1257 locJ += a * t_bc_disp(i) * (t_var_flux(i, j) * t_normal(j));
1258
1259 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1260 int bb = 0;
1261 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1262 // The H(div) contravariant Piola trace P . n dA is invariant with
1263 // respect to material-position perturbations. The normal variation is
1264 // cancelled by the Piola variation of the flux, so this BC contributes
1265 // to locJ but not to the exact dX vector.
1266 ++t_nf;
1267 ++t_diff_base;
1268 }
1269 for (; bb != nb_base_functions; ++bb)
1270 ++t_diff_base;
1271
1272 ++t_w;
1273 ++t_tangent1;
1274 ++t_tangent2;
1275 ++t_var_flux;
1276 }
1277 }
1278
1279 }
1280
1281
1283}
1284
1285MoFEMErrorCode OpAnalyticalDispBc_dX::integrate(int, EntityType type,
1286 EntData &data) {
1288 locJ = 0;
1289
1290#ifndef NDEBUG
1291 if (!brokenSideDataPtr)
1292 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1293 "Broken side data pointer is null");
1294#endif // NDEBUG
1295
1296 const int nb_dofs = data.getIndices().size();
1297 if (!nb_dofs)
1299
1300 const int nb_integration_pts = getGaussPts().size2();
1301 const int nb_base_functions = data.getN().size2();
1302
1303 if (data.getDiffN().size1() != nb_integration_pts)
1304 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1305 "Differential of base functions should have the same number of "
1306 "integration points as the data");
1307 if (data.getDiffN().size2() != nb_base_functions * 2)
1308 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1309 "Differential of base functions should have the same number of "
1310 "base functions as the data");
1311
1315
1316 const EntityHandle fe_ent = getFEEntityHandle();
1317 for (auto &bc : *bcDispPtr) {
1318 if (bc.faces.find(fe_ent) == bc.faces.end())
1319 continue;
1320
1321 auto v_analytical_expr =
1322 getTopologicalAnalyticalExpr(this, bc.blockName);
1323
1324 for (auto &bd : *brokenSideDataPtr) {
1325 auto t_w = getFTensor0IntegrationWeight();
1326 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1327 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1328 auto t_var_flux =
1329 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(bd.getVarFlux());
1330 auto t_diff_base = data.getFTensor1DiffN<2>();
1331 auto t_bc_disp =
1332 getFTensor1FromMat<SPACE_DIM, -1, DL>(v_analytical_expr);
1333
1334 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1335 const double a = 0.5 * bd.getSense() * t_w;
1336
1338 t_normal(j) =
1339 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1340
1341 locJ += a * t_bc_disp(i) * (t_var_flux(i, j) * t_normal(j));
1342
1343 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1344 int bb = 0;
1345 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1346 // The H(div) contravariant Piola trace P . n dA is invariant with
1347 // respect to material-position perturbations. The normal variation is
1348 // cancelled by the Piola variation of the flux, so this BC contributes
1349 // to locJ but not to the exact dX vector.
1350 ++t_nf;
1351 ++t_diff_base;
1352 }
1353 for (; bb != nb_base_functions; ++bb)
1354 ++t_diff_base;
1355
1356 ++t_w;
1357 ++t_tangent1;
1358 ++t_tangent2;
1359 ++t_var_flux;
1360 ++t_bc_disp;
1361 }
1362 }
1363 }
1364
1366}
1367
1368MoFEMErrorCode OpBrokenTractionBc_dX::integrate(int side, EntityType type,
1369 EntData &data) {
1371 locJ = 0;
1372
1376
1377 int nb_dofs = data.getFieldData().size();
1378 int nb_integration_pts = getGaussPts().size2();
1379 int nb_base_functions = data.getN().size2();
1380
1381 double time = getFEMethod()->ts_t;
1384 }
1385
1386#ifndef NDEBUG
1387 if (this->nF.size() != nb_dofs)
1388 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1389 "Size of nF %ld != nb_dofs %d", this->nF.size(), nb_dofs);
1390#endif // NDEBUG
1391
1392 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
1394
1395 auto t_val = getFTensor1FromPtr<3>(&*bc.vals.begin());
1396 auto t_diff_base = data.getFTensor1DiffN<2>();
1397 auto t_w = getFTensor0IntegrationWeight();
1398 auto t_coords = getFTensor1CoordsAtGaussPts();
1399
1400 auto t_var_u_gamma = getFTensor1FromMat<SPACE_DIM>(lambdaHybridPtr);
1401 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1402 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1403
1404 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1405
1407 t_normal(j) =
1408 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1409
1410 double a = sqrt(t_normal(i) * t_normal(i));
1412 t_da(i) = t_normal(i) / a;
1413 a /= 2.;
1414 t_da(i) /= 2.;
1415
1416 const auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
1417 locJ -= (time_scale * t_w * a * tau) * (t_val(i) * t_var_u_gamma(i));
1418
1419 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1420 int rr = 0;
1421 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1423 t_normal_dX(j, I) =
1424 (FTensor::levi_civita(i, j, I) * t_tangent2(i)) * t_diff_base(N0) +
1425 (FTensor::levi_civita(I, j, k) * t_tangent1(k)) * t_diff_base(N1);
1426 t_nf(I) -= (time_scale * t_w * tau) * (t_val(i) * t_var_u_gamma(i)) *
1427 (t_da(i) * t_normal_dX(i, I));
1428 ++t_diff_base;
1429 ++t_nf;
1430 }
1431 for (; rr != nb_base_functions; ++rr)
1432 ++t_diff_base;
1433
1434 ++t_w;
1435 ++t_coords;
1436 ++t_var_u_gamma;
1437 ++t_tangent1;
1438 ++t_tangent2;
1439 }
1440
1442 };
1443
1444 // get entity of face
1445 EntityHandle fe_ent = getFEEntityHandle();
1446 for (auto &bc : *(bcData)) {
1447 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1448
1449 double time_scale = 1;
1450 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1451 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1452 }
1453
1454 if (nb_dofs) {
1455 if (std::regex_match(bc.blockName, std::regex(".*COOK.*"))) {
1456 auto calc_tau = [](double, double y, double) {
1457 y -= 44;
1458 y /= (60 - 44);
1459 return -y * (y - 1) / 0.25;
1460 };
1461 CHKERR integrate_rhs(bc, calc_tau, time_scale);
1462 } else {
1463 CHKERR integrate_rhs(
1464 bc, [](double, double, double) { return 1; }, time_scale);
1465 }
1466 }
1467 }
1468 }
1470}
1471
1473 EntityType type,
1474 EntData &data) {
1476 locJ = 0;
1477
1484
1485 int nb_dofs = data.getFieldData().size();
1486 int nb_integration_pts = getGaussPts().size2();
1487 int nb_base_functions = data.getN().size2();
1488
1489#ifndef NDEBUG
1490 if (this->nF.size() != nb_dofs)
1491 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1492 "Size of nF %ld != nb_dofs %d", this->nF.size(), nb_dofs);
1493#endif // NDEBUG
1494
1495 auto integrate_rhs = [&](auto &bc) {
1497
1498 auto v_analytical_expr =
1499 getTopologicalAnalyticalExpr(this, bc.blockName);
1500
1501 auto t_val = getFTensor1FromMat<SPACE_DIM, -1, DL>(v_analytical_expr);
1502 auto t_diff_base = data.getFTensor1DiffN<2>();
1503 auto t_w = getFTensor0IntegrationWeight();
1504
1505 auto t_var_u_gamma = getFTensor1FromMat<SPACE_DIM>(lambdaHybridPtr);
1506 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1507 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1508
1509 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1510
1512 t_normal(j) =
1513 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1514
1515 double a = sqrt(t_normal(i) * t_normal(i));
1517 t_da(i) = t_normal(i) / a;
1518 a /= 2.;
1519 t_da(i) /= 2.;
1520
1521 locJ -= (t_w * a) * (t_val(i) * t_var_u_gamma(i));
1522
1523 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1524 int rr = 0;
1525 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1527 t_normal_dX(j, I) =
1528 (FTensor::levi_civita(i, j, I) * t_tangent2(i)) * t_diff_base(N0) +
1529 (FTensor::levi_civita(I, j, k) * t_tangent1(k)) * t_diff_base(N1);
1530 t_nf(I) -= t_w * (t_val(i) * t_var_u_gamma(i)) *
1531 (t_da(i) * t_normal_dX(i, I));
1532 ++t_diff_base;
1533 ++t_nf;
1534 }
1535 for (; rr != nb_base_functions; ++rr)
1536 ++t_diff_base;
1537
1538 ++t_w;
1539 ++t_val;
1540 ++t_var_u_gamma;
1541 ++t_tangent1;
1542 ++t_tangent2;
1543 }
1544
1546 };
1547
1548 EntityHandle fe_ent = getFEEntityHandle();
1549 for (auto &bc : *(bcData)) {
1550 if (bc.faces.find(fe_ent) != bc.faces.end() && nb_dofs) {
1551 CHKERR integrate_rhs(bc);
1552 }
1553 }
1554
1556}
1557
1558MoFEMErrorCode OpJ_dUImpl::integrate(EntData &data) {
1560
1561#ifndef NDEBUG
1562 if (!topoData)
1563 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1564 "Topological data pointer is null");
1565#endif // NDEBUG
1566
1567 const int nb_dofs = data.getIndices().size();
1568 if (!nb_dofs)
1570
1571 const int nb_integration_pts = data.getN().size1();
1572
1573 const auto v = getVolume();
1574 auto t_w = getFTensor0IntegrationWeight();
1575 const int nb_base_functions = data.getN().size2();
1576 auto t_row_base_fun = data.getFTensor0N();
1577
1578 auto t_obj_dlog_stretch = topoData->getFTensorObjDStrain(nb_integration_pts);
1579
1582 FTensor::Index<'L', size_symm> L;
1583 auto t_L = symm_L_tensor();
1584
1585 auto get_ftensor1 = [](auto &v) {
1587 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1588 };
1589
1590 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1591 const double a = v * t_w;
1592 auto t_nf = get_ftensor1(OP::nF);
1593
1595 t_obj_dU(L) = t_obj_dlog_stretch(i, j) * t_L(i, j, L);
1596
1597 int bb = 0;
1598 for (; bb != nb_dofs / size_symm; ++bb) {
1599 t_nf(L) += a * t_row_base_fun * t_obj_dU(L);
1600 ++t_nf;
1601 ++t_row_base_fun;
1602 }
1603 for (; bb != nb_base_functions; ++bb)
1604 ++t_row_base_fun;
1605
1606 ++t_w;
1607 ++t_obj_dlog_stretch;
1608 }
1609
1611}
1612
1616 const std::string field_name,
1617 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1618 boost::shared_ptr<TopologicalData> topo_ptr,
1619 SmartPetscObj<Vec> assemble_vec, const double alpha, const double rho,
1620 const double alpha_omega = 0, boost::shared_ptr<double> J_ptr = nullptr)
1622 field_name, data_ptr, topo_ptr, J_ptr, assemble_vec, Tag()),
1623 alphaW(alpha), alphaRho(rho), alphaOmega(alpha_omega) {}
1624
1625 MoFEMErrorCode integrate(EntData &data) {
1627#ifndef NDEBUG
1629 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1630 "L2 user base scale is set to %d, current inplementation only "
1631 "hanlde case for false",
1633 }
1634#endif // NDEBUG
1635
1636#ifndef NDEBUG
1637 if (!dataAtPts)
1638 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1639 "DataAtIntegrationPts pointer is null");
1640#endif // NDEBUG
1641
1642 const int nb_dofs = data.getIndices().size();
1643 if (!nb_dofs)
1645
1646 const int nb_integration_pts = getGaussPts().size2();
1647
1648 const auto v = getVolume();
1649 auto t_w = getFTensor0IntegrationWeight();
1650 // OpSpatialEquilibrium
1651 auto t_div_P = dataAtPts->getFTensorDivP(nb_integration_pts);
1652 auto t_var_w = dataAtPts->getFTensorVarWL2(nb_integration_pts);
1653 // OpSpatialRotation
1654 auto t_approx_P = dataAtPts->getFTensorApproxP(nb_integration_pts);
1655 auto t_omega = dataAtPts->getFTensorRotAxis(nb_integration_pts);
1656 auto t_u_h1 = dataAtPts->getFTensorStretchH1(nb_integration_pts);
1657 auto t_var_omega = dataAtPts->getFTensorVarRotAxis(nb_integration_pts);
1658 // OpSpatialConsistencyP
1659 auto t_h = dataAtPts->getFTensorSmallH(nb_integration_pts);
1660 auto t_var_P = dataAtPts->getFTensorVarPiola(nb_integration_pts);
1661 auto t_w_l2 = dataAtPts->getFTensorSmallWL2(nb_integration_pts);
1662 auto t_var_div_P = dataAtPts->getFTensorDivVarPiola(nb_integration_pts);
1663
1664 auto t_jac = topoData->getFTensorJacobian(nb_integration_pts);
1665
1666 auto get_ftensor1 = [](auto &v) {
1668 &v[0], &v[1], &v[2]);
1669 };
1670
1671 auto next = [&]() {
1672 ++t_w;
1673 ++t_div_P;
1674 ++t_var_w;
1675 ++t_approx_P;
1676 ++t_omega;
1677 ++t_u_h1;
1678 ++t_var_omega;
1679 ++t_h;
1680 ++t_var_P;
1681 ++t_w_l2;
1682 ++t_var_div_P;
1683 ++t_jac;
1684 };
1685
1692
1695
1696 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1697
1698 locJ = 0;
1699 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1700 double a = v * t_w;
1701
1703 // rotation
1705 case SMALL_ROT:
1706 t_diff_R(i, j, k) = levi_civita(i, j, k);
1707 break;
1708 case LARGE_ROT:
1709 t_diff_R(i, j, k) =
1710 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, j, k);
1711 break;
1712 default:
1713 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1714 "rotationSelector not handled");
1715 }
1716
1718 t_diff;
1719 t_diff(i, j, l, k) = t_kd(i, l) * t_kd(j, k);
1720
1721 // OpSpatialEqulibrium
1722 {
1723 const auto beta = a * (t_div_P(i) * t_var_w(i));
1724 locJ -= beta;
1725 }
1726 // OpSpatialEquilibrium
1727 {
1728 double beta;
1732 case LARGE_ROT:
1733 case MODERATE_ROT:
1734 beta =
1735
1736 ((t_diff_R(j, k, m) * t_var_omega(m)) * t_u_h1(k, l))
1737
1738 * (t_approx_P(j, n) * t_jac(l, n));
1739
1740 t_beta_dX(I, J) =
1741
1742 ((t_diff_R(j, k, m) * t_var_omega(m)) * t_u_h1(k, l))
1743
1744 * (t_approx_P(j, n) * t_diff(l, n, I, J));
1745
1746 break;
1747 case SMALL_ROT:
1748 beta =
1749
1750 (levi_civita(i, j, k) * t_var_omega(k))
1751
1752 * (t_approx_P(i, n) * t_jac(j, n));
1753
1754 t_beta_dX(I, J) =
1755
1756 (t_diff_R(i, j, k) * t_var_omega(k))
1757
1758 * (t_approx_P(i, n) * t_diff(j, n, I, J));
1759
1760 break;
1761 default:
1762 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1763 "gradApproximator not handled");
1764 break;
1765 };
1766
1767 locJ -= a * beta;
1768 auto t_nf = get_ftensor1(nF);
1769 auto t_base_diff = data.getFTensor1DiffN<3>(gg, 0);
1770 for (int bb = 0; bb != nb_dofs / SPACE_DIM; ++bb) {
1771 t_nf(i) -= a * (t_beta_dX(i, j) * t_base_diff(j));
1772 ++t_nf;
1773 ++t_base_diff;
1774 }
1775 }
1776 // OpSpatialConsistency
1777 {
1778 const auto beta =
1779 (t_h(i, j) - t_kd(i, j)) * (t_var_P(i, n) * t_jac(j, n));
1781 t_beta_dX(I, J) =
1782 (t_h(i, j) - t_kd(i, j)) * (t_var_P(i, n) * t_diff(j, n, I, J));
1783 locJ -= a * beta;
1784 auto t_nf = get_ftensor1(nF);
1785 auto t_base_diff = data.getFTensor1DiffN<3>(gg, 0);
1786 for (int bb = 0; bb != nb_dofs / SPACE_DIM; ++bb) {
1787 t_nf(i) -= a * (t_beta_dX(i, j) * t_base_diff(j));
1788 ++t_nf;
1789 ++t_base_diff;
1790 }
1791 }
1792 // OpSpatialConsistency, cont
1793 {
1794 const auto beta = t_w_l2(i) * t_var_div_P(i);
1795 locJ -= a * beta;
1796 }
1797
1798
1799 next();
1800 }
1801
1803 }
1804
1805private:
1806 const double alphaW;
1807 const double alphaRho;
1808 const double alphaOmega;
1809};
1810
1811
1815 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1816 SmartPetscObj<Vec> assemble_vec,
1817 boost::shared_ptr<TopologicalData> topo_ptr,
1818 const double alpha, const double rho,
1819 const double alpha_omega = 0)
1821 field_name, data_ptr, topo_ptr, nullptr, assemble_vec, Tag()),
1822 alphaW(alpha), alphaRho(rho), alphaOmega(alpha_omega) {}
1823
1824 MoFEMErrorCode integrate(EntData &data) {
1826
1827#ifndef NDEBUG
1828 if (!dataAtPts)
1829 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1830 "DataAtIntegrationPts pointer is null");
1831#endif // NDEBUG
1832
1833 const int nb_dofs = data.getIndices().size();
1834 if (!nb_dofs)
1836
1837 const int nb_integration_pts = getGaussPts().size2();
1838
1839 const auto v = getVolume();
1840 auto t_w = getFTensor0IntegrationWeight();
1841 auto t_div_P = dataAtPts->getFTensorDivP(nb_integration_pts);
1842 auto t_w_l2 = dataAtPts->getFTensorSmallWL2(nb_integration_pts);
1843 auto t_s_dot_w = dataAtPts->getFTensorSmallWL2Dot(nb_integration_pts);
1844 auto t_s_dot_dot_w =
1845 dataAtPts->getFTensorSmallWL2DotDot(nb_integration_pts);
1846 auto t_h = dataAtPts->getFTensorSmallH(nb_integration_pts);
1847 auto t_levi_kirchhoff =
1848 dataAtPts->getFTensorLeviKirchhoff(nb_integration_pts);
1849 auto t_omega_grad_dot =
1850 dataAtPts->getFTensorRotAxisGradDot(nb_integration_pts);
1851 auto t_R = dataAtPts->getFTensorRotMat(nb_integration_pts);
1852 auto t_u = dataAtPts->getFTensorStretch(nb_integration_pts);
1853
1854 auto t_var_w = dataAtPts->getFTensorVarWL2(nb_integration_pts);
1855 auto t_var_omega = dataAtPts->getFTensorVarRotAxis(nb_integration_pts);
1856 auto t_var_grad_omega =
1857 dataAtPts->getFTensorVarGradRotAxis(nb_integration_pts);
1858 auto t_var_P = dataAtPts->getFTensorVarPiola(nb_integration_pts);
1859 auto t_var_div_P = dataAtPts->getFTensorDivVarPiola(nb_integration_pts);
1860 auto t_det = topoData->getFTensorDetJacobian(nb_integration_pts);
1861 auto t_inv_jac = topoData->getFTensorInvJacobian(nb_integration_pts);
1862
1863 auto w_l2_dot_dot_at_pts = dataAtPts->getSmallWL2DotDotAtPts();
1864 if (w_l2_dot_dot_at_pts->size1() != nb_integration_pts ||
1865 w_l2_dot_dot_at_pts->size2() != SPACE_DIM) {
1866 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
1867 *w_l2_dot_dot_at_pts, nb_integration_pts);
1868 w_l2_dot_dot_at_pts->clear();
1869 }
1870
1871 const auto piola_scale = dataAtPts->piolaScale;
1872 const auto alpha_w = alphaW / piola_scale;
1873 const auto alpha_rho = alphaRho / piola_scale;
1874
1875 const int nb_base_functions = data.getN().size2();
1876 auto t_base_diff = data.getFTensor1DiffN<3>();
1877
1878 auto get_ftensor1 = [](auto &v) {
1880 &v[0], &v[1], &v[2]);
1881 };
1882
1883 auto next = [&]() {
1884 ++t_w;
1885 ++t_div_P;
1886 ++t_w_l2;
1887 ++t_s_dot_w;
1888 ++t_s_dot_dot_w;
1889 ++t_h;
1890 ++t_levi_kirchhoff;
1891 ++t_omega_grad_dot;
1892 ++t_R;
1893 ++t_u;
1894
1895 ++t_var_w;
1896 ++t_var_omega;
1897 ++t_var_grad_omega;
1898 ++t_var_P;
1899 ++t_var_div_P;
1900
1901 ++t_det;
1902 ++t_inv_jac;
1903 };
1904
1910 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1911
1912 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1913
1914 // Calculate the variation of the gradient due to geometry change
1916 t_cof(i, j) = t_det * t_inv_jac(j, i);
1917
1918 auto t_nf = get_ftensor1(nF);
1919 int bb = 0;
1920 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1921
1923 t_div_base(i) = -(1 / t_det) * (t_inv_jac(j, i) * t_base_diff(j));
1924
1925 // OpSpatialEquilibrium
1926 t_nf(i) += (t_w * v) *
1927 (t_var_w(k) * (-t_div_P(k) + alpha_w * t_s_dot_w(k) +
1928 alpha_rho * t_s_dot_dot_w(k))) *
1929 t_cof(i, j) * t_base_diff(j);
1930 t_nf(i) += (t_w * v) * (-(t_var_w(k) * t_div_P(k))) * t_div_base(i);
1931
1932 // OpSpatialRotation
1933 t_nf(i) += (t_w * v) * (t_var_omega(k) * (-t_levi_kirchhoff(k))) *
1934 t_cof(i, j) * t_base_diff(j);
1935 #ifndef NDEBUG
1936 // need to add implementaion of omege terms
1937 if (alphaOmega) {
1938 SETERRQ(
1939 PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
1940 "OpSensitivity_dX with alpha_omega != 0 is not implemented yet");
1941 }
1942 #endif
1943
1944 // OpSpatialConsistencyP
1946 t_nf(i) -= (t_w * v) * (t_var_P(i, k) * (t_R(i, l) * t_u(l, k)) / 2) *
1947 t_cof(i, j) * t_base_diff(j);
1948 t_nf(i) -= (t_w * v) * (t_var_P(i, l) * (t_R(i, k) * t_u(l, k)) / 2) *
1949 t_cof(i, j) * t_base_diff(j);
1950 t_nf(i) += (t_w * v) * (t_var_P(i, j) * t_kd(i, j)) * t_cof(i, j) *
1951 t_base_diff(j);
1952 } else {
1954 t_residuum_P(k, m) = t_h(k, m) - t_kd(k, m);
1955 t_nf(i) += (t_w * v) * (t_var_P(k, m) * (-t_residuum_P(k, m))) *
1956 t_cof(i, j) * t_base_diff(j);
1957 }
1958
1959 // OpSpatialConsistencyDivTerm
1960 t_nf(i) += (t_w * v) * (t_var_div_P(k) * (-t_w_l2(k))) * t_cof(i, j) *
1961 t_base_diff(j);
1962 t_nf(i) += (t_w * v) * (t_var_div_P(k) * (-t_w_l2(k))) * t_div_base(i);
1963
1964 ++t_nf;
1965 ++t_base_diff;
1966 }
1967 for (; bb != nb_base_functions; ++bb)
1968 ++t_base_diff;
1969
1970 next();
1971 }
1972
1974 }
1975
1976private:
1977 const double alphaW;
1978 const double alphaRho;
1979 const double alphaOmega;
1980};
1981
1985 const std::string &field_name,
1986 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1987 SmartPetscObj<Vec> assemble_vec,
1988 boost::shared_ptr<TopologicalData> topo_ptr,
1989 std::vector<boost::shared_ptr<ScalingMethod>> smv,
1990 boost::shared_ptr<double> J_ptr = nullptr)
1992 field_name, data_ptr, topo_ptr, J_ptr, assemble_vec, Tag()),
1993 scalingMethods(smv) {
1994 CHK_THROW_MESSAGE(getMeshsetData(m_field, ms_id), "Get meshset data");
1995 }
1996
1997 MoFEMErrorCode integrate(EntData &data) {
1999
2000 locJ = 0;
2001
2002 if (entsPtr) {
2003 if (entsPtr->find(this->getFEEntityHandle()) == entsPtr->end())
2005 }
2006
2007#ifndef NDEBUG
2008 if (!dataAtPts)
2009 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2010 "DataAtIntegrationPts pointer is null");
2011#endif // NDEBUG
2012
2013 const int nb_dofs = data.getIndices().size();
2014 if (!nb_dofs)
2016
2017 const int nb_integration_pts = getGaussPts().size2();
2018
2019 const auto v = getVolume();
2020 auto t_w = getFTensor0IntegrationWeight();
2021 auto t_var_w_l2 = dataAtPts->getFTensorVarWL2(nb_integration_pts);
2022 auto t_det = topoData->getFTensorDetJacobian(nb_integration_pts);
2023 auto t_inv_jac = topoData->getFTensorInvJacobian(nb_integration_pts);
2024
2025 const int nb_base_functions = data.getN().size2();
2026 auto t_base_diff = data.getFTensor1DiffN<3>();
2027
2028 auto get_ftensor1 = [](auto &v) {
2030 &v[0], &v[1], &v[2]);
2031 };
2032
2033 auto next = [&]() {
2034 ++t_w;
2035 ++t_var_w_l2;
2036 ++t_inv_jac;
2037 ++t_det;
2038 };
2039
2041
2042 auto get_scale = [&](const double t) {
2043 double s = 1;
2044 for (auto &o : scalingMethods) {
2045
2046
2047 s *= o->getScale(t);
2048 }
2049 return s;
2050 };
2051
2052 auto scale = get_scale(getFEMethod()->ts_t);
2053
2054 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2055 const double alpha = scale * t_w * v;
2056
2057 double adjount = t_var_w_l2(i) * tForce(i);
2058 locJ += (alpha * t_det) * adjount;
2059
2061 t_cof(i, j) = t_det * t_inv_jac(j, i);
2062
2063 auto t_nf = get_ftensor1(nF);
2064 int bb = 0;
2065 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
2066 t_nf(i) += (alpha * adjount) * t_cof(i, J) * t_base_diff(J);
2067
2068 ++t_nf;
2069 ++t_base_diff;
2070 }
2071 for (; bb != nb_base_functions; ++bb)
2072 ++t_base_diff;
2073
2074 next();
2075 }
2076
2078 }
2079
2080protected:
2081
2082 MoFEMErrorCode getMeshsetData(MoFEM::Interface &m_field, int ms_id) {
2084
2085 auto cubit_meshset_ptr =
2086 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(ms_id,
2087 BLOCKSET);
2088
2089 std::vector<double> block_data;
2090 CHKERR cubit_meshset_ptr->getAttributes(block_data);
2091
2092 if (block_data.size() != SPACE_DIM) {
2093 MOFEM_LOG("SELF", Sev::warning)
2094 << "BLOCKSET is expected to have " << SPACE_DIM
2095 << " attributes but has size " << block_data.size();
2096 if (block_data.size() < SPACE_DIM) {
2097 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2098 "Size of attribute in BLOCKSET is too small");
2099 }
2100 }
2101
2102 for (unsigned int ii = 0; ii != SPACE_DIM; ++ii) {
2103 tForce(ii) = block_data[ii];
2104 }
2105
2106 MOFEM_LOG("WORLD", Sev::noisy)
2107 << "Flux blockset " << cubit_meshset_ptr->getName();
2108 MOFEM_LOG("WORLD", Sev::noisy)
2109 << "Number of attributes " << block_data.size();
2110
2111 this->entsPtr = boost::make_shared<Range>();
2112 CHKERR m_field.get_moab().get_entities_by_handle(cubit_meshset_ptr->meshset,
2113 *(entsPtr), true);
2114
2115 MOFEM_LOG("WORLD", Sev::noisy) << "tForce vector initialised: " << tForce;
2116 MOFEM_LOG("WORLD", Sev::noisy) << "Number of elements " << entsPtr->size();
2117
2118
2119
2121 }
2122
2124 boost::shared_ptr<Range> entsPtr;
2125 std::vector<boost::shared_ptr<ScalingMethod>> scalingMethods;
2126};
2127
2128} // namespace EshelbianPlasticity
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.
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 StretchHandling stretchHandling
static enum RotSelector rotSelector
static enum RotSelector gradApproximator
static double physicalDt
static PetscBool physicalTimeFlg
static double currentPhysicalTime
static bool hasNonHomogeneousMaterialBlock
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_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_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)
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
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
data at integration pts
double rho
Definition plastic.cpp:145
double scale
Definition plastic.cpp:124