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
518 eval_evergy(
519 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(dataAtPts->matInvD));
520 } else {
521 eval_evergy(
522 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->matInvD));
523 }
525 };
526
527 auto conversion_of_biot_stress = [&]() {
529 // Python differentiates the objective with respect to Biot stress. The
530 // material equations need the corresponding Piola and rotation derivatives.
531 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
532 *topoData->getObjDRotationAtPts(), nb_gauss_pts);
533 topoData->getObjDRotationAtPts()->clear();
534
535 auto t_obj_dbiot = topoData->getFTensorObjDStress(nb_gauss_pts);
536 auto t_obj_domega = topoData->getFTensorObjDRotation(nb_gauss_pts);
537 auto t_R = dataAtPts->getFTensorRotMat(nb_gauss_pts);
538 auto t_P = dataAtPts->getFTensorApproxP(nb_gauss_pts);
539 auto t_grad_h1 = dataAtPts->getFTensorSmallWGradH1(nb_gauss_pts);
540 auto t_omega = dataAtPts->getFTensorRotAxis(nb_gauss_pts);
541
547 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
548
549 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
551 t_dJ_dbiot(l, o) = t_obj_dbiot(l, o);
552
554 case SMALL_ROT:
555 // In the linear/small formulation Python sees the Piola field itself:
556 // B = P. There is no rotation or H1-gradient pullback to apply.
557 t_obj_dbiot(i, k) = t_dJ_dbiot(i, k);
558 t_obj_domega(m) = 0;
559 break;
560 case NO_H1_CONFIGURATION: {
563 case LARGE_ROT:
564 t_diff_R(i, l, m) =
565 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, l, m);
566 break;
567 default:
568 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
569 "rotationSelector not handled");
570 }
571
572 // Python sees B = R^T P.
573 t_obj_dbiot(i, k) = t_R(i, l) * t_dJ_dbiot(l, k);
574 t_obj_domega(m) = t_dJ_dbiot(l, k) * t_diff_R(i, l, m) * t_P(i, k);
575 } break;
576 case LARGE_ROT:
577 case MODERATE_ROT: {
579 t_h1(o, k) = t_kd(o, k) + t_grad_h1(o, k);
580
583 case SMALL_ROT:
584 t_diff_R(i, l, m) = levi_civita(i, l, m);
585 break;
586 case LARGE_ROT:
587 t_diff_R(i, l, m) =
588 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, l, m);
589 break;
590 default:
591 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
592 "rotationSelector not handled");
593 }
594
595 // Python sees B = R^T P H1^T.
596 t_obj_dbiot(i, k) = t_R(i, l) * (t_dJ_dbiot(l, o) * t_h1(o, k));
597 t_obj_domega(m) =
598 t_dJ_dbiot(l, o) * (t_diff_R(i, l, m) * t_P(i, k)) * t_h1(o, k);
599 } break;
600 default:
601 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
602 "gradApproximator not handled");
603 }
604
605 ++t_obj_dbiot;
606 ++t_obj_domega;
607 ++t_R;
608 ++t_P;
609 ++t_grad_h1;
610 ++t_omega;
611 }
612
614 };
615
616 auto conversion_of_stretch = [&]() {
618 // Python sees the physical stretch tensor. The stretch field stores log
619 // stretch, so convert dJ/dU to dJ/dlogU once here.
620 auto t_obj_dstretch = topoData->getFTensorObjDStrain(nb_gauss_pts);
621 auto t_diff_stretch = dataAtPts->getFTensorDiffStretch(nb_gauss_pts);
622
627
628 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
630 t_dJ_dstretch(i, j) = t_obj_dstretch(i, j);
631
632 t_obj_dstretch(k, l) = t_dJ_dstretch(i, j) * t_diff_stretch(i, j, k, l);
633
634 ++t_obj_dstretch;
635 ++t_diff_stretch;
636 }
637
639 };
640
641 auto conversion_of_stretch_to_stress_for_no_stretch = [&](auto t_inv_D) {
643 // In no-stretch mode, log stretch is computed from the stress field. Fold
644 // the objective stretch derivative into the stress derivative buffer.
645 auto t_obj_dstress = topoData->getFTensorObjDStress(nb_gauss_pts);
646 auto t_obj_dstretch = topoData->getFTensorObjDStrain(nb_gauss_pts);
647
652
653 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
655 t_dstretch_dstress(i, j) =
656 ((t_obj_dstretch(k, l) || t_obj_dstretch(l, k)) / 2.) *
657 t_inv_D(k, l, i, j);
658
659 t_obj_dstress(i, j) += t_dstretch_dstress(i, j);
660
661 ++t_obj_dstress;
662 ++t_obj_dstretch;
663 ++t_inv_D;
664 }
665
667 };
668
669 switch (evalEnergyModel) {
670 case PYTHON_MODEL:
671 CHKERR evaluate_python_objective();
672 CHKERR conversion_of_biot_stress();
677 CHKERR conversion_of_stretch_to_stress_for_no_stretch(
678 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(dataAtPts->matInvD));
679 } else {
680 CHKERR conversion_of_stretch_to_stress_for_no_stretch(
681 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->matInvD));
682 }
683 } else {
684 CHKERR conversion_of_stretch();
685 }
686 break;
687 case HENCKY_MODEL:
689 CHKERR evaluate_energy_of_hencky_model_nostreach();
690 CHKERR conversion_of_biot_stress();
691 } else {
692 CHKERR evaluate_energy_of_hencky_model();
693 }
694 break;
695 default:
696 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
697 "Objective model type not handled");
698 }
699
701}
702
703MoFEMErrorCode OpInteriorJImpl::integrate(EntData &data) {
705 locJ = 0;
706
707#ifndef NDEBUG
708 if (!topoData)
709 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
710 "Topological data pointer is null");
711#endif // NDEBUG
712
713 const int nb_dofs = data.getIndices().size();
714 if (!nb_dofs)
716
717 const int nb_integration_pts = getGaussPts().size2();
718
719 const auto v = getVolume();
720 auto t_w = getFTensor0IntegrationWeight();
721 auto t_obj = topoData->getFTensorObj(nb_integration_pts);
722 auto t_obj_dP = topoData->getFTensorObjDStress(nb_integration_pts);
723 auto t_obj_dStrain = topoData->getFTensorObjDStrain(nb_integration_pts);
724 auto t_obj_dU = topoData->getFTensorObjDDisplacement(nb_integration_pts);
725 auto t_P = dataAtPts->getFTensorApproxP(nb_integration_pts);
726 auto t_det = topoData->getFTensorDetJacobian(nb_integration_pts);
727 auto t_inv_jac = topoData->getFTensorInvJacobian(nb_integration_pts);
728 auto t_jac = topoData->getFTensorJacobian(nb_integration_pts);
729
730 auto next = [&]() {
731 ++t_w;
732 ++t_obj;
733 ++t_obj_dP;
734 ++t_obj_dStrain;
735 ++t_obj_dU;
736 ++t_P;
737 ++t_det;
738 ++t_inv_jac;
739 ++t_jac;
740 };
741
743 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
744
745 auto get_ftensor1 = [](auto &v) {
747 &v[0], &v[1], &v[2]);
748 };
749
750 nF.clear();
751
752 const int nb_base_functions = data.getN().size2();
753 auto t_base_diff = data.getFTensor1DiffN<SPACE_DIM>();
754 for (int gg = 0; gg != nb_integration_pts; ++gg) {
755 locJ += (t_w * v * t_det) * t_obj;
756
758 t_cof(i, j) = t_det * t_inv_jac(j, i);
759
761 t_dJ_dX(I, J) =
762
763 t_obj * t_cof(I, J)
764
765 +
766
767 t_obj_dP(i, j) * (t_kd(j, I) * (t_kd(k, J) * t_P(i, k)) -
768 t_inv_jac(I, J) * t_jac(j, k) * t_P(i, k));
769
770 auto t_nf = get_ftensor1(nF);
771 int bb = 0;
772 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
773 t_nf(i) += (t_w * v) * t_dJ_dX(i, j) * t_base_diff(j);
774 ++t_nf;
775 ++t_base_diff;
776 }
777 for (; bb != nb_base_functions; ++bb)
778 ++t_base_diff;
779
780 next();
781 }
782
784}
785
786MoFEMErrorCode OpJ_dPImpl::integrate(EntData &data) {
788
789#ifndef NDEBUG
790 if (!topoData)
791 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
792 "Topological data pointer is null");
793#endif // NDEBUG
794
795 const int nb_dofs = data.getIndices().size();
796 if (!nb_dofs)
798
799 const int nb_integration_pts = data.getN().size1();
800
801 const auto v = getVolume();
802 auto t_w = getFTensor0IntegrationWeight();
803 const int nb_base_functions = data.getN().size2() / SPACE_DIM;
804 auto t_row_base_fun = data.getFTensor1N<SPACE_DIM>();
805
808
809 auto get_ftensor1 = [](auto &v) {
811 &v[0], &v[1], &v[2]);
812 };
813
814 auto t_obj_dP = topoData->getFTensorObjDStress(nb_integration_pts);
815
816 for (int gg = 0; gg != nb_integration_pts; ++gg) {
817 const double a = v * t_w;
818 auto t_nf = get_ftensor1(nF);
819
820 int bb = 0;
821 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
822 t_nf(i) += a * t_row_base_fun(j) * t_obj_dP(i, j);
823 ++t_nf;
824 ++t_row_base_fun;
825 }
826 for (; bb != nb_base_functions; ++bb)
827 ++t_row_base_fun;
828
829 ++t_w;
830 ++t_obj_dP;
831 }
832
834}
835
836MoFEMErrorCode OpJ_dBubbleImpl::integrate(EntData &data) {
838
839#ifndef NDEBUG
840 if (!topoData)
841 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
842 "Topological data pointer is null");
843#endif // NDEBUG
844
845 const int nb_dofs = data.getIndices().size();
846 if (!nb_dofs)
848
849 const int nb_integration_pts = data.getN().size1();
850
851 const auto v = getVolume();
852 auto t_w = getFTensor0IntegrationWeight();
853 const int nb_base_functions = data.getN().size2() / (SPACE_DIM * SPACE_DIM);
854 auto t_row_base_fun = data.getFTensor2N<SPACE_DIM, SPACE_DIM>();
855 auto t_obj_dP = topoData->getFTensorObjDStress(nb_integration_pts);
856
859
860 auto get_ftensor0 = [](auto &v) {
862 };
863
864 for (int gg = 0; gg != nb_integration_pts; ++gg) {
865 const double a = v * t_w;
866 auto t_nf = get_ftensor0(nF);
867
868 int bb = 0;
869 for (; bb != nb_dofs; ++bb) {
870 t_nf += a * t_row_base_fun(i, j) * t_obj_dP(i, j);
871 ++t_nf;
872 ++t_row_base_fun;
873 }
874 for (; bb != nb_base_functions; ++bb)
875 ++t_row_base_fun;
876
877 ++t_w;
878 ++t_obj_dP;
879 }
880
882}
883
884MoFEMErrorCode OpJ_dwImpl::integrate(EntData &data) {
886
887#ifndef NDEBUG
888 if (!topoData)
889 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
890 "Topological data pointer is null");
891#endif // NDEBUG
892
893 const int nb_dofs = data.getIndices().size();
894 if (!nb_dofs)
896
897 const int nb_integration_pts = data.getN().size1();
898
899 const auto v = getVolume();
900 auto t_w = getFTensor0IntegrationWeight();
901 const int nb_base_functions = data.getN().size2();
902 auto t_row_base_fun = data.getFTensor0N();
903 auto t_obj_dw = topoData->getFTensorObjDDisplacement(nb_integration_pts);
904
906
907 auto get_ftensor1 = [](auto &v) {
909 &v[0], &v[1], &v[2]);
910 };
911
912 for (int gg = 0; gg != nb_integration_pts; ++gg) {
913 const double a = v * t_w;
914 auto t_nf = get_ftensor1(nF);
915
916 int bb = 0;
917 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
918 t_nf(i) += a * t_row_base_fun * t_obj_dw(i);
919 ++t_nf;
920 ++t_row_base_fun;
921 }
922 for (; bb != nb_base_functions; ++bb)
923 ++t_row_base_fun;
924
925 ++t_w;
926 ++t_obj_dw;
927 }
928
930}
931
932MoFEMErrorCode OpJ_dOmegaImpl::integrate(EntData &data) {
934
935#ifndef NDEBUG
936 if (!topoData)
937 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
938 "Topological data pointer is null");
939#endif // NDEBUG
940
941 const int nb_dofs = data.getIndices().size();
942 if (!nb_dofs)
944
945 const int nb_integration_pts = data.getN().size1();
946
947 const auto v = getVolume();
948 auto t_w = getFTensor0IntegrationWeight();
949 const int nb_base_functions = data.getN().size2();
950 auto t_row_base_fun = data.getFTensor0N();
951 auto t_obj_domega = topoData->getFTensorObjDRotation(nb_integration_pts);
952
954
955 auto get_ftensor1 = [](auto &v) {
957 &v[0], &v[1], &v[2]);
958 };
959
960 for (int gg = 0; gg != nb_integration_pts; ++gg) {
961 const double a = v * t_w;
962 auto t_nf = get_ftensor1(nF);
963
964 int bb = 0;
965 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
966 t_nf(i) += a * t_row_base_fun * t_obj_domega(i);
967 ++t_nf;
968 ++t_row_base_fun;
969 }
970 for (; bb != nb_base_functions; ++bb)
971 ++t_row_base_fun;
972
973 ++t_w;
974 ++t_obj_domega;
975 }
976
978}
979
980MoFEMErrorCode dJ_duGammaImpl::integrate(EntData &data) {
982
983#ifndef NDEBUG
984 if (!topoData)
985 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
986 "Topological data pointer is null");
987#endif // NDEBUG
988
989 const int nb_dofs = data.getIndices().size();
990 if (!nb_dofs)
992
993 const int nb_integration_pts = data.getN().size1();
994
995 auto t_w = getFTensor0IntegrationWeight();
996 const int nb_base_functions = data.getN().size2();
997 auto t_row_base_fun = data.getFTensor0N();
998 auto t_obj_du_gamma =
999 topoData->getFTensorObjDDisplacement(nb_integration_pts);
1000
1002
1003 auto get_ftensor1 = [](auto &v) {
1005 &v[0], &v[1], &v[2]);
1006 };
1007
1008 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1009 const double a = t_w * getMeasure();
1010 auto t_nf = get_ftensor1(nF);
1011
1012 int bb = 0;
1013 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1014 t_nf(i) += a * t_row_base_fun * t_obj_du_gamma(i);
1015 ++t_nf;
1016 ++t_row_base_fun;
1017 }
1018 for (; bb != nb_base_functions; ++bb)
1019 ++t_row_base_fun;
1020
1021 ++t_w;
1022 ++t_obj_du_gamma;
1023 }
1024
1026}
1027
1030
1031#ifndef NDEBUG
1032 if (!topoData)
1033 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1034 "Topological data pointer is null");
1035#endif // NDEBUG
1036
1037 const int nb_dofs = data.getIndices().size();
1038 if (!nb_dofs)
1040
1041 const int nb_integration_pts = OP::getGaussPts().size2();
1042
1043 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1044 auto t_w = OP::getFTensor0IntegrationWeight();
1045 const int nb_base_functions = data.getN().size2() / SPACE_DIM;
1046 auto t_row_base_fun = data.getFTensor1N<SPACE_DIM>();
1047 auto t_obj_dtraction =
1048 topoData->getFTensorObjDDisplacement(nb_integration_pts);
1049
1052
1053 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1054 auto t_nf = getFTensor1FromPtr<SPACE_DIM>(&*OP::locF.begin());
1055 int bb = 0;
1056 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1057 t_nf(i) +=
1058 t_w * (t_row_base_fun(j) * t_normal(j)) * t_obj_dtraction(i) * 0.5;
1059 ++t_nf;
1060 ++t_row_base_fun;
1061 }
1062 for (; bb != nb_base_functions; ++bb)
1063 ++t_row_base_fun;
1064
1065 ++t_w;
1066 ++t_normal;
1067 ++t_obj_dtraction;
1068 }
1069
1071}
1072
1073MoFEMErrorCode OpTauStabilisation_dX::integrate(int, EntityType,
1074 EntData &data) {
1076 locJ = 0;
1077
1078#ifndef NDEBUG
1079 if (!topoData)
1080 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1081 "Topological data pointer is null");
1082 if (!brokenDispDataPtr)
1083 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1084 "Broken displacement data pointer is null");
1085 if (!hybridDispPtr)
1086 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1087 "Hybrid displacement pointer is null");
1088 if (!varHybridDispPtr)
1089 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1090 "Adjoint hybrid displacement pointer is null");
1091#endif // NDEBUG
1092
1093 const int nb_dofs = data.getIndices().size();
1094 if (!nb_dofs)
1096
1097 const int nb_integration_pts = getGaussPts().size2();
1098 const int nb_base_functions = data.getN().size2();
1099
1100#ifndef NDEBUG
1101 if (this->nF.size() != nb_dofs)
1102 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1103 "Size of nF %ld != nb_dofs %d", this->nF.size(), nb_dofs);
1104 if (data.getDiffN().size1() != nb_integration_pts)
1105 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1106 "Differential of base functions should have the same number of "
1107 "integration points as the data");
1108 if (data.getDiffN().size2() != nb_base_functions * 2)
1109 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1110 "Differential of base functions should have the same number of "
1111 "base functions as the data");
1112#endif // NDEBUG
1113
1117
1118 auto &coords = getCoords();
1119 // Tau scale is based on the mesh triangle coordinates, not on the perturbed
1120 // material-position field. Treat h as constant with respect to X.
1121 const double h = std::get<2>(Tools::getTricircumcenter3d(coords.data().data()));
1122
1123 auto t_w = getFTensor0IntegrationWeight();
1124 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1125 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1126 auto t_u_hybrid = getFTensor1FromMat<SPACE_DIM, -1, DL>(*hybridDispPtr);
1127 auto t_var_u_hybrid =
1128 getFTensor1FromMat<SPACE_DIM, -1, DL>(*varHybridDispPtr);
1129 auto t_diff_base = data.getFTensor1DiffN<2>();
1130
1131 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1133 t_normal(j) =
1134 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1135
1136 double area = std::sqrt(t_normal(i) * t_normal(i));
1138 t_da(i) = t_normal(i) / area;
1139 area /= 2.;
1140 t_da(i) /= 2.;
1141
1142 double tau_density = 0;
1143 for (auto &bd : *brokenDispDataPtr) {
1144 auto t_u_broken =
1145 getFTensor1FromMat<SPACE_DIM, -1, DL>(bd.getFlux(), nb_integration_pts);
1146 auto t_var_u_broken = getFTensor1FromMat<SPACE_DIM, -1, DL>(
1147 bd.getVarFlux(), nb_integration_pts);
1148 for (int ss = 0; ss != gg; ++ss) {
1149 ++t_u_broken;
1150 ++t_var_u_broken;
1151 }
1152
1153 // This is the adjoint-weighted material derivative of the four tau
1154 // stabilisation residual blocks:
1155 // u_gamma-u_gamma, L2-L2, u_gamma-L2, and L2-u_gamma.
1156 const double hybrid_hybrid = t_var_u_hybrid(i) * t_u_hybrid(i);
1157 const double broken_broken = t_var_u_broken(i) * t_u_broken(i);
1158 const double hybrid_broken = -t_var_u_hybrid(i) * t_u_broken(i);
1159 const double broken_hybrid = -t_var_u_broken(i) * t_u_hybrid(i);
1160 tau_density +=
1161 hybrid_hybrid + broken_broken + hybrid_broken + broken_hybrid;
1162 }
1163
1164 const double tau = alphaTau / h;
1165 locJ += t_w * tau * area * tau_density;
1166
1167 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1168 int rr = 0;
1169 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1171 t_normal_dX(j, I) =
1172 (FTensor::levi_civita(i, j, I) * t_tangent2(i)) * t_diff_base(N0) +
1173 (FTensor::levi_civita(I, j, k) * t_tangent1(k)) * t_diff_base(N1);
1174
1175 t_nf(I) +=
1176 t_w * alphaTau * tau_density * (t_da(i) * t_normal_dX(i, I)) / h;
1177 ++t_diff_base;
1178 ++t_nf;
1179 }
1180 for (; rr != nb_base_functions; ++rr)
1181 ++t_diff_base;
1182
1183 ++t_w;
1184 ++t_tangent1;
1185 ++t_tangent2;
1186 ++t_u_hybrid;
1187 ++t_var_u_hybrid;
1188 }
1189
1191}
1192
1193MoFEMErrorCode OpDispBc_dX::integrate(int, EntityType type, EntData &data) {
1195 locJ = 0;
1196
1197#ifndef NDEBUG
1198 if (!brokenSideDataPtr)
1199 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1200 "Broken side data pointer is null");
1201#endif // NDEBUG
1202
1203
1204 const int nb_dofs = data.getIndices().size();
1205 if (!nb_dofs)
1207
1208 const int nb_integration_pts = getGaussPts().size2();
1209 const int nb_base_functions = data.getN().size2();
1210
1211 if (data.getDiffN().size1() != nb_integration_pts)
1212 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1213 "Differential of base functions should have the same number of "
1214 "integration points as the data");
1215 if (data.getDiffN().size2() != nb_base_functions * 2)
1216 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1217 "Differential of base functions should have the same number of "
1218 "base functions as the data");
1219
1220 double time = getFEMethod()->ts_t;
1223
1225
1228
1229 const EntityHandle fe_ent = getFEEntityHandle();
1230 for (auto &bc : *bcDispPtr) {
1231 if (bc.faces.find(fe_ent) == bc.faces.end())
1232 continue;
1233
1234 double scale = 1;
1235 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1236 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1237 } else {
1238 MOFEM_LOG("SELF", Sev::warning)
1239 << "No scaling method found for " << bc.blockName;
1240 }
1241
1242 FTensor::Tensor1<double, SPACE_DIM> t_bc_disp(bc.vals[0], bc.vals[1],
1243 bc.vals[2]);
1244 t_bc_disp(i) *= scale;
1245
1246 for (auto &bd : *brokenSideDataPtr) {
1247 auto t_w = getFTensor0IntegrationWeight();
1248 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1249 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1250 auto t_var_flux =
1251 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(bd.getVarFlux());
1252 auto t_diff_base = data.getFTensor1DiffN<2>();
1253
1254 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1255 const double a = 0.5 * bd.getSense() * t_w;
1256
1258 t_normal(j) =
1259 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1260
1261 locJ += a * t_bc_disp(i) * (t_var_flux(i, j) * t_normal(j));
1262
1263 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1264 int bb = 0;
1265 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1266 // The H(div) contravariant Piola trace P . n dA is invariant with
1267 // respect to material-position perturbations. The normal variation is
1268 // cancelled by the Piola variation of the flux, so this BC contributes
1269 // to locJ but not to the exact dX vector.
1270 ++t_nf;
1271 ++t_diff_base;
1272 }
1273 for (; bb != nb_base_functions; ++bb)
1274 ++t_diff_base;
1275
1276 ++t_w;
1277 ++t_tangent1;
1278 ++t_tangent2;
1279 ++t_var_flux;
1280 }
1281 }
1282
1283 }
1284
1285
1287}
1288
1289MoFEMErrorCode OpAnalyticalDispBc_dX::integrate(int, EntityType type,
1290 EntData &data) {
1292 locJ = 0;
1293
1294#ifndef NDEBUG
1295 if (!brokenSideDataPtr)
1296 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1297 "Broken side data pointer is null");
1298#endif // NDEBUG
1299
1300 const int nb_dofs = data.getIndices().size();
1301 if (!nb_dofs)
1303
1304 const int nb_integration_pts = getGaussPts().size2();
1305 const int nb_base_functions = data.getN().size2();
1306
1307 if (data.getDiffN().size1() != nb_integration_pts)
1308 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1309 "Differential of base functions should have the same number of "
1310 "integration points as the data");
1311 if (data.getDiffN().size2() != nb_base_functions * 2)
1312 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1313 "Differential of base functions should have the same number of "
1314 "base functions as the data");
1315
1319
1320 const EntityHandle fe_ent = getFEEntityHandle();
1321 for (auto &bc : *bcDispPtr) {
1322 if (bc.faces.find(fe_ent) == bc.faces.end())
1323 continue;
1324
1325 auto v_analytical_expr =
1326 getTopologicalAnalyticalExpr(this, bc.blockName);
1327
1328 for (auto &bd : *brokenSideDataPtr) {
1329 auto t_w = getFTensor0IntegrationWeight();
1330 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1331 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1332 auto t_var_flux =
1333 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(bd.getVarFlux());
1334 auto t_diff_base = data.getFTensor1DiffN<2>();
1335 auto t_bc_disp =
1336 getFTensor1FromMat<SPACE_DIM, -1, DL>(v_analytical_expr);
1337
1338 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1339 const double a = 0.5 * bd.getSense() * t_w;
1340
1342 t_normal(j) =
1343 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1344
1345 locJ += a * t_bc_disp(i) * (t_var_flux(i, j) * t_normal(j));
1346
1347 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1348 int bb = 0;
1349 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1350 // The H(div) contravariant Piola trace P . n dA is invariant with
1351 // respect to material-position perturbations. The normal variation is
1352 // cancelled by the Piola variation of the flux, so this BC contributes
1353 // to locJ but not to the exact dX vector.
1354 ++t_nf;
1355 ++t_diff_base;
1356 }
1357 for (; bb != nb_base_functions; ++bb)
1358 ++t_diff_base;
1359
1360 ++t_w;
1361 ++t_tangent1;
1362 ++t_tangent2;
1363 ++t_var_flux;
1364 ++t_bc_disp;
1365 }
1366 }
1367 }
1368
1370}
1371
1372MoFEMErrorCode OpBrokenTractionBc_dX::integrate(int side, EntityType type,
1373 EntData &data) {
1375 locJ = 0;
1376
1380
1381 int nb_dofs = data.getFieldData().size();
1382 int nb_integration_pts = getGaussPts().size2();
1383 int nb_base_functions = data.getN().size2();
1384
1385 double time = getFEMethod()->ts_t;
1388 }
1389
1390#ifndef NDEBUG
1391 if (this->nF.size() != nb_dofs)
1392 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1393 "Size of nF %ld != nb_dofs %d", this->nF.size(), nb_dofs);
1394#endif // NDEBUG
1395
1396 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
1398
1399 auto t_val = getFTensor1FromPtr<3>(&*bc.vals.begin());
1400 auto t_diff_base = data.getFTensor1DiffN<2>();
1401 auto t_w = getFTensor0IntegrationWeight();
1402 auto t_coords = getFTensor1CoordsAtGaussPts();
1403
1404 auto t_var_u_gamma = getFTensor1FromMat<SPACE_DIM>(lambdaHybridPtr);
1405 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1406 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1407
1408 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1409
1411 t_normal(j) =
1412 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1413
1414 double a = sqrt(t_normal(i) * t_normal(i));
1416 t_da(i) = t_normal(i) / a;
1417 a /= 2.;
1418 t_da(i) /= 2.;
1419
1420 const auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
1421 locJ -= (time_scale * t_w * a * tau) * (t_val(i) * t_var_u_gamma(i));
1422
1423 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1424 int rr = 0;
1425 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1427 t_normal_dX(j, I) =
1428 (FTensor::levi_civita(i, j, I) * t_tangent2(i)) * t_diff_base(N0) +
1429 (FTensor::levi_civita(I, j, k) * t_tangent1(k)) * t_diff_base(N1);
1430 t_nf(I) -= (time_scale * t_w * tau) * (t_val(i) * t_var_u_gamma(i)) *
1431 (t_da(i) * t_normal_dX(i, I));
1432 ++t_diff_base;
1433 ++t_nf;
1434 }
1435 for (; rr != nb_base_functions; ++rr)
1436 ++t_diff_base;
1437
1438 ++t_w;
1439 ++t_coords;
1440 ++t_var_u_gamma;
1441 ++t_tangent1;
1442 ++t_tangent2;
1443 }
1444
1446 };
1447
1448 // get entity of face
1449 EntityHandle fe_ent = getFEEntityHandle();
1450 for (auto &bc : *(bcData)) {
1451 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1452
1453 double time_scale = 1;
1454 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1455 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1456 }
1457
1458 if (nb_dofs) {
1459 if (std::regex_match(bc.blockName, std::regex(".*COOK.*"))) {
1460 auto calc_tau = [](double, double y, double) {
1461 y -= 44;
1462 y /= (60 - 44);
1463 return -y * (y - 1) / 0.25;
1464 };
1465 CHKERR integrate_rhs(bc, calc_tau, time_scale);
1466 } else {
1467 CHKERR integrate_rhs(
1468 bc, [](double, double, double) { return 1; }, time_scale);
1469 }
1470 }
1471 }
1472 }
1474}
1475
1477 EntityType type,
1478 EntData &data) {
1480 locJ = 0;
1481
1488
1489 int nb_dofs = data.getFieldData().size();
1490 int nb_integration_pts = getGaussPts().size2();
1491 int nb_base_functions = data.getN().size2();
1492
1493#ifndef NDEBUG
1494 if (this->nF.size() != nb_dofs)
1495 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1496 "Size of nF %ld != nb_dofs %d", this->nF.size(), nb_dofs);
1497#endif // NDEBUG
1498
1499 auto integrate_rhs = [&](auto &bc) {
1501
1502 auto v_analytical_expr =
1503 getTopologicalAnalyticalExpr(this, bc.blockName);
1504
1505 auto t_val = getFTensor1FromMat<SPACE_DIM, -1, DL>(v_analytical_expr);
1506 auto t_diff_base = data.getFTensor1DiffN<2>();
1507 auto t_w = getFTensor0IntegrationWeight();
1508
1509 auto t_var_u_gamma = getFTensor1FromMat<SPACE_DIM>(lambdaHybridPtr);
1510 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1511 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1512
1513 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1514
1516 t_normal(j) =
1517 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1518
1519 double a = sqrt(t_normal(i) * t_normal(i));
1521 t_da(i) = t_normal(i) / a;
1522 a /= 2.;
1523 t_da(i) /= 2.;
1524
1525 locJ -= (t_w * a) * (t_val(i) * t_var_u_gamma(i));
1526
1527 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1528 int rr = 0;
1529 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1531 t_normal_dX(j, I) =
1532 (FTensor::levi_civita(i, j, I) * t_tangent2(i)) * t_diff_base(N0) +
1533 (FTensor::levi_civita(I, j, k) * t_tangent1(k)) * t_diff_base(N1);
1534 t_nf(I) -= t_w * (t_val(i) * t_var_u_gamma(i)) *
1535 (t_da(i) * t_normal_dX(i, I));
1536 ++t_diff_base;
1537 ++t_nf;
1538 }
1539 for (; rr != nb_base_functions; ++rr)
1540 ++t_diff_base;
1541
1542 ++t_w;
1543 ++t_val;
1544 ++t_var_u_gamma;
1545 ++t_tangent1;
1546 ++t_tangent2;
1547 }
1548
1550 };
1551
1552 EntityHandle fe_ent = getFEEntityHandle();
1553 for (auto &bc : *(bcData)) {
1554 if (bc.faces.find(fe_ent) != bc.faces.end() && nb_dofs) {
1555 CHKERR integrate_rhs(bc);
1556 }
1557 }
1558
1560}
1561
1562MoFEMErrorCode OpJ_dUImpl::integrate(EntData &data) {
1564
1565#ifndef NDEBUG
1566 if (!topoData)
1567 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1568 "Topological data pointer is null");
1569#endif // NDEBUG
1570
1571 const int nb_dofs = data.getIndices().size();
1572 if (!nb_dofs)
1574
1575 const int nb_integration_pts = data.getN().size1();
1576
1577 const auto v = getVolume();
1578 auto t_w = getFTensor0IntegrationWeight();
1579 const int nb_base_functions = data.getN().size2();
1580 auto t_row_base_fun = data.getFTensor0N();
1581
1582 auto t_obj_dlog_stretch = topoData->getFTensorObjDStrain(nb_integration_pts);
1583
1586 FTensor::Index<'L', size_symm> L;
1588
1589 auto get_ftensor1 = [](auto &v) {
1591 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1592 };
1593
1594 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1595 const double a = v * t_w;
1596 auto t_nf = get_ftensor1(OP::nF);
1597
1599 t_obj_dU(L) = t_obj_dlog_stretch(i, j) * t_L(i, j, L);
1600
1601 int bb = 0;
1602 for (; bb != nb_dofs / size_symm; ++bb) {
1603 t_nf(L) += a * t_row_base_fun * t_obj_dU(L);
1604 ++t_nf;
1605 ++t_row_base_fun;
1606 }
1607 for (; bb != nb_base_functions; ++bb)
1608 ++t_row_base_fun;
1609
1610 ++t_w;
1611 ++t_obj_dlog_stretch;
1612 }
1613
1615}
1616
1620 const std::string field_name,
1621 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1622 boost::shared_ptr<TopologicalData> topo_ptr,
1623 SmartPetscObj<Vec> assemble_vec, const double alpha, const double rho,
1624 const double alpha_viscous_omega = 0,
1625 boost::shared_ptr<double> J_ptr = nullptr)
1627 field_name, data_ptr, topo_ptr, J_ptr, assemble_vec, Tag()),
1628 alphaW(alpha), alphaRho(rho),
1629 alphaViscousOmega(alpha_viscous_omega) {}
1630
1631 MoFEMErrorCode integrate(EntData &data) {
1633#ifndef NDEBUG
1635 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1636 "L2 user base scale is set to %d, current inplementation only "
1637 "hanlde case for false",
1639 }
1640#endif // NDEBUG
1641
1642#ifndef NDEBUG
1643 if (!dataAtPts)
1644 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1645 "DataAtIntegrationPts pointer is null");
1646#endif // NDEBUG
1647
1648 const int nb_dofs = data.getIndices().size();
1649 if (!nb_dofs)
1651
1652 const int nb_integration_pts = getGaussPts().size2();
1653
1654 const auto v = getVolume();
1655 auto t_w = getFTensor0IntegrationWeight();
1656 // OpSpatialEquilibrium
1657 auto t_div_P = dataAtPts->getFTensorDivP(nb_integration_pts);
1658 auto t_var_w = dataAtPts->getFTensorVarWL2(nb_integration_pts);
1659 // OpSpatialRotation
1660 auto t_approx_P = dataAtPts->getFTensorApproxP(nb_integration_pts);
1661 auto t_omega = dataAtPts->getFTensorRotAxis(nb_integration_pts);
1662 auto t_u_h1 = dataAtPts->getFTensorStretchH1(nb_integration_pts);
1663 auto t_var_omega = dataAtPts->getFTensorVarRotAxis(nb_integration_pts);
1664 // OpSpatialConsistencyP
1665 auto t_h = dataAtPts->getFTensorSmallH(nb_integration_pts);
1666 auto t_var_P = dataAtPts->getFTensorVarPiola(nb_integration_pts);
1667 auto t_w_l2 = dataAtPts->getFTensorSmallWL2(nb_integration_pts);
1668 auto t_var_div_P = dataAtPts->getFTensorDivVarPiola(nb_integration_pts);
1669
1670 auto t_jac = topoData->getFTensorJacobian(nb_integration_pts);
1671
1672 auto get_ftensor1 = [](auto &v) {
1674 &v[0], &v[1], &v[2]);
1675 };
1676
1677 auto next = [&]() {
1678 ++t_w;
1679 ++t_div_P;
1680 ++t_var_w;
1681 ++t_approx_P;
1682 ++t_omega;
1683 ++t_u_h1;
1684 ++t_var_omega;
1685 ++t_h;
1686 ++t_var_P;
1687 ++t_w_l2;
1688 ++t_var_div_P;
1689 ++t_jac;
1690 };
1691
1698
1701
1702 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1703
1704 locJ = 0;
1705 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1706 double a = v * t_w;
1707
1709 // rotation
1711 case SMALL_ROT:
1712 t_diff_R(i, j, k) = levi_civita(i, j, k);
1713 break;
1714 case LARGE_ROT:
1715 t_diff_R(i, j, k) =
1716 LieGroups::SO3::diffExp(t_omega, t_omega.l2())(i, j, k);
1717 break;
1718 default:
1719 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1720 "rotationSelector not handled");
1721 }
1722
1724 t_diff;
1725 t_diff(i, j, l, k) = t_kd(i, l) * t_kd(j, k);
1726
1727 // OpSpatialEqulibrium
1728 {
1729 const auto beta = a * (t_div_P(i) * t_var_w(i));
1730 locJ -= beta;
1731 }
1732 // OpSpatialEquilibrium
1733 {
1734 double beta;
1738 case LARGE_ROT:
1739 case MODERATE_ROT:
1740 beta =
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_jac(l, n));
1745
1746 t_beta_dX(I, J) =
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_diff(l, n, I, J));
1751
1752 break;
1753 case SMALL_ROT:
1754 beta =
1755
1756 (levi_civita(i, j, k) * t_var_omega(k))
1757
1758 * (t_approx_P(i, n) * t_jac(j, n));
1759
1760 t_beta_dX(I, J) =
1761
1762 (t_diff_R(i, j, k) * t_var_omega(k))
1763
1764 * (t_approx_P(i, n) * t_diff(j, n, I, J));
1765
1766 break;
1767 default:
1768 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1769 "gradApproximator not handled");
1770 break;
1771 };
1772
1773 locJ -= a * beta;
1774 auto t_nf = get_ftensor1(nF);
1775 auto t_base_diff = data.getFTensor1DiffN<3>(gg, 0);
1776 for (int bb = 0; bb != nb_dofs / SPACE_DIM; ++bb) {
1777 t_nf(i) -= a * (t_beta_dX(i, j) * t_base_diff(j));
1778 ++t_nf;
1779 ++t_base_diff;
1780 }
1781 }
1782 // OpSpatialConsistency
1783 {
1784 const auto beta =
1785 (t_h(i, j) - t_kd(i, j)) * (t_var_P(i, n) * t_jac(j, n));
1787 t_beta_dX(I, J) =
1788 (t_h(i, j) - t_kd(i, j)) * (t_var_P(i, n) * t_diff(j, n, I, J));
1789 locJ -= a * beta;
1790 auto t_nf = get_ftensor1(nF);
1791 auto t_base_diff = data.getFTensor1DiffN<3>(gg, 0);
1792 for (int bb = 0; bb != nb_dofs / SPACE_DIM; ++bb) {
1793 t_nf(i) -= a * (t_beta_dX(i, j) * t_base_diff(j));
1794 ++t_nf;
1795 ++t_base_diff;
1796 }
1797 }
1798 // OpSpatialConsistency, cont
1799 {
1800 const auto beta = t_w_l2(i) * t_var_div_P(i);
1801 locJ -= a * beta;
1802 }
1803
1804
1805 next();
1806 }
1807
1809 }
1810
1811private:
1812 const double alphaW;
1813 const double alphaRho;
1814 const double alphaViscousOmega;
1815};
1816
1817
1821 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1822 SmartPetscObj<Vec> assemble_vec,
1823 boost::shared_ptr<TopologicalData> topo_ptr,
1824 const double alpha, const double rho,
1825 const double alpha_viscous_omega = 0)
1827 field_name, data_ptr, topo_ptr, nullptr, assemble_vec, Tag()),
1828 alphaW(alpha), alphaRho(rho),
1829 alphaViscousOmega(alpha_viscous_omega) {}
1830
1831 MoFEMErrorCode integrate(EntData &data) {
1833
1834#ifndef NDEBUG
1835 if (!dataAtPts)
1836 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1837 "DataAtIntegrationPts pointer is null");
1838#endif // NDEBUG
1839
1840 const int nb_dofs = data.getIndices().size();
1841 if (!nb_dofs)
1843
1844#ifndef NDEBUG
1845 if (alphaViscousOmega) {
1846 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
1847 "OpSensitivity_dX with alpha_viscous_omega != 0 is not "
1848 "implemented yet");
1849 }
1850#endif // NDEBUG
1851
1852 const int nb_integration_pts = getGaussPts().size2();
1853
1854 const auto v = getVolume();
1855 auto t_w = getFTensor0IntegrationWeight();
1856 auto t_div_P = dataAtPts->getFTensorDivP(nb_integration_pts);
1857 auto t_w_l2 = dataAtPts->getFTensorSmallWL2(nb_integration_pts);
1858 auto t_s_dot_w = dataAtPts->getFTensorSmallWL2Dot(nb_integration_pts);
1859 auto t_s_dot_dot_w =
1860 dataAtPts->getFTensorSmallWL2DotDot(nb_integration_pts);
1861 auto t_h = dataAtPts->getFTensorSmallH(nb_integration_pts);
1862 auto t_levi_kirchhoff =
1863 dataAtPts->getFTensorLeviKirchhoff(nb_integration_pts);
1864 auto t_omega_grad_dot =
1865 dataAtPts->getFTensorRotAxisGradDot(nb_integration_pts);
1866 auto t_R = dataAtPts->getFTensorRotMat(nb_integration_pts);
1867 auto t_u = dataAtPts->getFTensorStretch(nb_integration_pts);
1868
1869 auto t_var_w = dataAtPts->getFTensorVarWL2(nb_integration_pts);
1870 auto t_var_omega = dataAtPts->getFTensorVarRotAxis(nb_integration_pts);
1871 auto t_var_grad_omega =
1872 dataAtPts->getFTensorVarGradRotAxis(nb_integration_pts);
1873 auto t_var_P = dataAtPts->getFTensorVarPiola(nb_integration_pts);
1874 auto t_var_div_P = dataAtPts->getFTensorDivVarPiola(nb_integration_pts);
1875 auto t_det = topoData->getFTensorDetJacobian(nb_integration_pts);
1876 auto t_inv_jac = topoData->getFTensorInvJacobian(nb_integration_pts);
1877
1878 auto w_l2_dot_dot_at_pts = dataAtPts->getSmallWL2DotDotAtPts();
1879 if (w_l2_dot_dot_at_pts->size1() != nb_integration_pts ||
1880 w_l2_dot_dot_at_pts->size2() != SPACE_DIM) {
1881 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
1882 *w_l2_dot_dot_at_pts, nb_integration_pts);
1883 w_l2_dot_dot_at_pts->clear();
1884 }
1885
1886 const auto piola_scale = dataAtPts->piolaScale;
1887 const auto alpha_w = alphaW / piola_scale;
1888 const auto alpha_rho = alphaRho / piola_scale;
1889
1890 const int nb_base_functions = data.getN().size2();
1891 auto t_base_diff = data.getFTensor1DiffN<3>();
1892
1893 auto get_ftensor1 = [](auto &v) {
1895 &v[0], &v[1], &v[2]);
1896 };
1897
1898 auto next = [&]() {
1899 ++t_w;
1900 ++t_div_P;
1901 ++t_w_l2;
1902 ++t_s_dot_w;
1903 ++t_s_dot_dot_w;
1904 ++t_h;
1905 ++t_levi_kirchhoff;
1906 ++t_omega_grad_dot;
1907 ++t_R;
1908 ++t_u;
1909
1910 ++t_var_w;
1911 ++t_var_omega;
1912 ++t_var_grad_omega;
1913 ++t_var_P;
1914 ++t_var_div_P;
1915
1916 ++t_det;
1917 ++t_inv_jac;
1918 };
1919
1925 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1926
1927 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1928
1929 // Calculate the variation of the gradient due to geometry change
1931 t_cof(i, j) = t_det * t_inv_jac(j, i);
1932
1933 double consistency_residual = 0;
1935 consistency_residual =
1936 -0.5 * t_var_P(k, m) * (t_R(k, l) * t_u(l, m)) -
1937 0.5 * t_var_P(k, l) * (t_R(k, m) * t_u(l, m)) +
1938 t_var_P(k, l) * t_kd(k, l);
1939 } else {
1941 t_residuum_P(k, m) = t_h(k, m) - t_kd(k, m);
1942 consistency_residual =
1943 t_var_P(k, m) * (-t_residuum_P(k, m));
1944 }
1945
1946 auto t_nf = get_ftensor1(nF);
1947 int bb = 0;
1948 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1949
1951 t_div_base(i) = -(1 / t_det) * (t_inv_jac(j, i) * t_base_diff(j));
1952
1953 // OpSpatialEquilibrium
1954 t_nf(i) += (t_w * v) *
1955 (t_var_w(k) * (-t_div_P(k) + alpha_w * t_s_dot_w(k) +
1956 alpha_rho * t_s_dot_dot_w(k))) *
1957 t_cof(i, j) * t_base_diff(j);
1958 t_nf(i) += (t_w * v) * (-(t_var_w(k) * t_div_P(k))) * t_div_base(i);
1959
1960 // OpSpatialRotation
1961 t_nf(i) += (t_w * v) * (t_var_omega(k) * (-t_levi_kirchhoff(k))) *
1962 t_cof(i, j) * t_base_diff(j);
1963
1964 // OpSpatialConsistencyP
1965 t_nf(i) += (t_w * v * consistency_residual) * t_cof(i, j) *
1966 t_base_diff(j);
1967
1968 // OpSpatialConsistencyDivTerm
1969 t_nf(i) += (t_w * v) * (t_var_div_P(k) * (-t_w_l2(k))) * t_cof(i, j) *
1970 t_base_diff(j);
1971 t_nf(i) += (t_w * v) * (t_var_div_P(k) * (-t_w_l2(k))) * t_div_base(i);
1972
1973 ++t_nf;
1974 ++t_base_diff;
1975 }
1976 for (; bb != nb_base_functions; ++bb)
1977 ++t_base_diff;
1978
1979 next();
1980 }
1981
1983 }
1984
1985private:
1986 const double alphaW;
1987 const double alphaRho;
1988 const double alphaViscousOmega;
1989};
1990
1994 const std::string &field_name,
1995 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1996 SmartPetscObj<Vec> assemble_vec,
1997 boost::shared_ptr<TopologicalData> topo_ptr,
1998 std::vector<boost::shared_ptr<ScalingMethod>> smv,
1999 boost::shared_ptr<double> J_ptr = nullptr)
2001 field_name, data_ptr, topo_ptr, J_ptr, assemble_vec, Tag()),
2002 scalingMethods(smv) {
2003 CHK_THROW_MESSAGE(getMeshsetData(m_field, ms_id), "Get meshset data");
2004 }
2005
2006 MoFEMErrorCode integrate(EntData &data) {
2008
2009 locJ = 0;
2010
2011 if (entsPtr) {
2012 if (entsPtr->find(this->getFEEntityHandle()) == entsPtr->end())
2014 }
2015
2016#ifndef NDEBUG
2017 if (!dataAtPts)
2018 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2019 "DataAtIntegrationPts pointer is null");
2020#endif // NDEBUG
2021
2022 const int nb_dofs = data.getIndices().size();
2023 if (!nb_dofs)
2025
2026 const int nb_integration_pts = getGaussPts().size2();
2027
2028 const auto v = getVolume();
2029 auto t_w = getFTensor0IntegrationWeight();
2030 auto t_var_w_l2 = dataAtPts->getFTensorVarWL2(nb_integration_pts);
2031 auto t_det = topoData->getFTensorDetJacobian(nb_integration_pts);
2032 auto t_inv_jac = topoData->getFTensorInvJacobian(nb_integration_pts);
2033
2034 const int nb_base_functions = data.getN().size2();
2035 auto t_base_diff = data.getFTensor1DiffN<3>();
2036
2037 auto get_ftensor1 = [](auto &v) {
2039 &v[0], &v[1], &v[2]);
2040 };
2041
2042 auto next = [&]() {
2043 ++t_w;
2044 ++t_var_w_l2;
2045 ++t_inv_jac;
2046 ++t_det;
2047 };
2048
2050
2051 auto get_scale = [&](const double t) {
2052 double s = 1;
2053 for (auto &o : scalingMethods) {
2054
2055
2056 s *= o->getScale(t);
2057 }
2058 return s;
2059 };
2060
2061 auto scale = get_scale(getFEMethod()->ts_t);
2062
2063 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2064 const double alpha = scale * t_w * v;
2065
2066 double adjount = t_var_w_l2(i) * tForce(i);
2067 locJ += (alpha * t_det) * adjount;
2068
2070 t_cof(i, j) = t_det * t_inv_jac(j, i);
2071
2072 auto t_nf = get_ftensor1(nF);
2073 int bb = 0;
2074 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
2075 t_nf(i) += (alpha * adjount) * t_cof(i, J) * t_base_diff(J);
2076
2077 ++t_nf;
2078 ++t_base_diff;
2079 }
2080 for (; bb != nb_base_functions; ++bb)
2081 ++t_base_diff;
2082
2083 next();
2084 }
2085
2087 }
2088
2089protected:
2090
2091 MoFEMErrorCode getMeshsetData(MoFEM::Interface &m_field, int ms_id) {
2093
2094 auto cubit_meshset_ptr =
2095 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(ms_id,
2096 BLOCKSET);
2097
2098 std::vector<double> block_data;
2099 CHKERR cubit_meshset_ptr->getAttributes(block_data);
2100
2101 if (block_data.size() != SPACE_DIM) {
2102 MOFEM_LOG("SELF", Sev::warning)
2103 << "BLOCKSET is expected to have " << SPACE_DIM
2104 << " attributes but has size " << block_data.size();
2105 if (block_data.size() < SPACE_DIM) {
2106 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2107 "Size of attribute in BLOCKSET is too small");
2108 }
2109 }
2110
2111 for (unsigned int ii = 0; ii != SPACE_DIM; ++ii) {
2112 tForce(ii) = block_data[ii];
2113 }
2114
2115 MOFEM_LOG("WORLD", Sev::noisy)
2116 << "Flux blockset " << cubit_meshset_ptr->getName();
2117 MOFEM_LOG("WORLD", Sev::noisy)
2118 << "Number of attributes " << block_data.size();
2119
2120 this->entsPtr = boost::make_shared<Range>();
2121 CHKERR m_field.get_moab().get_entities_by_handle(cubit_meshset_ptr->meshset,
2122 *(entsPtr), true);
2123
2124 MOFEM_LOG("WORLD", Sev::noisy) << "tForce vector initialised: " << tForce;
2125 MOFEM_LOG("WORLD", Sev::noisy) << "Number of elements " << entsPtr->size();
2126
2127
2128
2130 }
2131
2133 boost::shared_ptr<Range> entsPtr;
2134 std::vector<boost::shared_ptr<ScalingMethod>> scalingMethods;
2135};
2136
2137} // namespace EshelbianPlasticity
std::string type
#define FTENSOR_INDEXES(DIM,...)
#define FTENSOR_INDEX(DIM, I)
constexpr double a
constexpr int SPACE_DIM
Kronecker Delta class.
Mapping from symmetric tensor indices to packed storage index.
#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
static bool isNoStretch()
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)
static auto diffExp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:105
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