v0.16.3
Loading...
Searching...
No Matches
EshelbianTopologicalDerivativeOperators.cpp
Go to the documentation of this file.
1/**
2 * @file EshelbianTopologicalDerivative.cpp
3 * @brief
4 * @version 0.1
5 * @date 2026-02-11
6 *
7 * @copyright Copyright (c) 2026
8 *
9 */
10
11using namespace EshelbianPlasticity;
12using namespace ShapeOptimization;
13
14namespace EshelbianPlasticity {
15
16// dr/dX topological derivative for Eshelbian plasticity model
17
18template <typename AssembleOp>
20 using OP = AssembleOp;
21
23 const std::string &field_name,
24 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
25 boost::shared_ptr<TopologicalData> topo_ptr,
26 boost::shared_ptr<double> J_ptr, SmartPetscObj<Vec> assemble_vec,
27 Tag topo_tag)
28 : OP(field_name, data_ptr, OP::OPROW), JPtr(J_ptr),
29 assembleVec(assemble_vec), topoTag(topo_tag), topoData(topo_ptr) {}
30
31 MoFEMErrorCode assemble(int side, EntityType type, EntData &data) override {
33 if (type == MBVERTEX) {
34 // Note it is iterated over vertices, since geometry is now in H1.
35 if (JPtr) {
36 *JPtr += locJ;
37 }
38 }
39 if (assembleVec) {
40 double *vec_ptr = OP::nF.data().data();
41 const int nb_dofs = data.getIndices().size();
42 int *ind_ptr = data.getIndices().data().data();
43 CHKERR VecSetValues(assembleVec, nb_dofs, ind_ptr, vec_ptr, ADD_VALUES);
44 }
45 if (topoTag) {
46 const auto field_ents = data.getFieldEntities();
47 std::vector<EntityHandle> ents(field_ents.size());
48 std::transform(field_ents.begin(), field_ents.end(), ents.begin(),
49 [](const auto *fe) { return fe->getEnt(); });
50 if (field_ents.empty())
52 if (type_from_handle(ents[0]) != MBVERTEX)
54 auto &moab = OP::getMoab();
55 VectorDouble topo_values(OP::nF.size());
56 CHKERR moab.tag_set_data(topoTag, ents.data(), ents.size(),
57 topo_values.data().data());
58 noalias(topo_values) += OP::nF;
59 CHKERR moab.tag_set_data(topoTag, ents.data(), ents.size(),
60 OP::nF.data().data());
61 }
63 }
64
65protected:
66 double locJ;
67 boost::shared_ptr<double> JPtr;
68 SmartPetscObj<Vec> assembleVec;
70 boost::shared_ptr<TopologicalData> topoData;
71};
72
79
85
87 : public FormsIntegrators<FaceUserDataOperator>::Assembly<A>::OpBrokenBase {
88
89 using OP = typename FormsIntegrators<FaceUserDataOperator>::Assembly<
91
93 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_base_side_data,
94 boost::shared_ptr<TopologicalData> topo_ptr,
95 boost::shared_ptr<double> J_ptr, SmartPetscObj<Vec> assemble_vec,
96 Tag topo_tag, boost::shared_ptr<Range> ents_ptr = nullptr)
97 : OP(broken_base_side_data, ents_ptr), JPtr(J_ptr),
98 assembleVec(assemble_vec), topoTag(topo_tag), topoData(topo_ptr) {}
99
100 MoFEMErrorCode aSsemble(EntData &data) override {
102 if (assembleVec) {
103 double *vec_ptr = OP::locF.data().data();
104 const int nb_dofs = data.getIndices().size();
105 int *ind_ptr = data.getIndices().data().data();
106 CHKERR VecSetValues(assembleVec, nb_dofs, ind_ptr, vec_ptr, ADD_VALUES);
107 }
108 if (topoTag) {
109 const auto field_ents = data.getFieldEntities();
110 std::vector<EntityHandle> ents(field_ents.size());
111 std::transform(field_ents.begin(), field_ents.end(), ents.begin(),
112 [](const auto *fe) { return fe->getEnt(); });
113 if (field_ents.empty())
115 if (type_from_handle(ents[0]) != MBVERTEX)
117 auto &moab = getMoab();
118 VectorDouble topo_values(OP::locF.size());
119 CHKERR moab.tag_set_data(topoTag, ents.data(), ents.size(),
120 topo_values.data().data());
121 topo_values += OP::locF;
122 CHKERR moab.tag_set_data(topoTag, ents.data(), ents.size(),
123 OP::locF.data().data());
124 }
126 }
127
128protected:
129 boost::shared_ptr<double> JPtr;
130 SmartPetscObj<Vec> assembleVec;
132 boost::shared_ptr<TopologicalData> topoData;
133};
134
137 OpAssembleVolumeTopologicalDerivativeImpl;
138
139 MoFEMErrorCode integrate(EntData &data);
140};
141
144 OpAssembleVolumeTopologicalDerivativeImpl;
145
146 MoFEMErrorCode integrate(EntData &data);
147};
148
151 OpAssembleVolumeTopologicalDerivativeImpl;
152
153 MoFEMErrorCode integrate(EntData &data);
154};
155
158 OpAssembleVolumeTopologicalDerivativeImpl;
159
160 MoFEMErrorCode integrate(EntData &data);
161};
162
165 OpAssembleFaceTopologicalDerivativeImpl;
166
167 MoFEMErrorCode integrate(EntData &data);
168};
169
173 OpAssembleBrokenFaceTopologicalDerivativeImplBase;
174
175 MoFEMErrorCode iNtegrate(EntData &data);
176};
177
180 const std::string &field_name,
181 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_disp_data_ptr,
182 boost::shared_ptr<MatrixDouble> hybrid_disp_ptr,
183 boost::shared_ptr<MatrixDouble> var_hybrid_disp_ptr,
184 boost::shared_ptr<TopologicalData> topo_ptr, const double alpha_tau,
185 SmartPetscObj<Vec> vec, boost::shared_ptr<double> J_ptr = nullptr,
186 Tag tag = Tag())
188 J_ptr, vec, tag),
189 brokenDispDataPtr(broken_disp_data_ptr), hybridDispPtr(hybrid_disp_ptr),
190 varHybridDispPtr(var_hybrid_disp_ptr), alphaTau(alpha_tau) {}
191
192 MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override;
193
194private:
195 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenDispDataPtr;
196 boost::shared_ptr<MatrixDouble> hybridDispPtr;
197 boost::shared_ptr<MatrixDouble> varHybridDispPtr;
198 double alphaTau;
199};
200
203 const std::string &field_name,
204 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
205 boost::shared_ptr<BcDispVec> bc_disp_ptr,
206 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv,
207 boost::shared_ptr<TopologicalData> topo_ptr, SmartPetscObj<Vec> vec,
208 boost::shared_ptr<double> J_ptr = nullptr, Tag tag = Tag())
210 J_ptr, vec, tag),
211 brokenSideDataPtr(broken_side_data_ptr), bcDispPtr(bc_disp_ptr),
212 scalingMethodsMap(smv) {}
213
214 MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override;
215
216private:
217 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
218 boost::shared_ptr<BcDispVec> bcDispPtr;
219 std::map<std::string, boost::shared_ptr<ScalingMethod>> scalingMethodsMap;
220};
221
222template <typename OP_PTR>
223static MatrixDouble
224getTopologicalAnalyticalExpr(OP_PTR op_ptr, const std::string &block_name) {
225
226 auto nb_gauss_pts = op_ptr->getGaussPts().size2();
227
228 auto ts_time = op_ptr->getTStime();
229 auto ts_time_step = op_ptr->getTStimeStep();
230
233 ts_time_step = EshelbianCore::physicalDt;
234 }
235
236 MatrixDouble m_ref_coords = op_ptr->getCoordsAtGaussPts();
237 MatrixDouble m_ref_normals = op_ptr->getNormalsAtGaussPts();
238
239 auto v_analytical_expr =
240 analytical_expr_function(ts_time_step, ts_time, nb_gauss_pts,
241 m_ref_coords, m_ref_normals, block_name);
242
243 if (PetscUnlikely(!v_analytical_expr.size2())) {
245 "Analytical expression is empty or does not exist, "
246 "check python file");
247 }
248
249 return v_analytical_expr;
250}
251
254 const std::string &field_name,
255 boost::shared_ptr<std::vector<BrokenBaseSideData>> broken_side_data_ptr,
256 boost::shared_ptr<AnalyticalDisplacementBcVec> bc_disp_ptr,
257 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv,
258 boost::shared_ptr<TopologicalData> topo_ptr, SmartPetscObj<Vec> vec,
259 boost::shared_ptr<double> J_ptr = nullptr, Tag tag = Tag())
261 J_ptr, vec, tag),
262 brokenSideDataPtr(broken_side_data_ptr), bcDispPtr(bc_disp_ptr),
263 scalingMethodsMap(smv) {}
264
265 MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override;
266
267private:
268 boost::shared_ptr<std::vector<BrokenBaseSideData>> brokenSideDataPtr;
269 boost::shared_ptr<AnalyticalDisplacementBcVec> bcDispPtr;
270 std::map<std::string, boost::shared_ptr<ScalingMethod>> scalingMethodsMap;
271};
272
275 std::string field_name, boost::shared_ptr<TractionBcVec> bc_data,
276 boost::shared_ptr<MatrixDouble> lambda_hybrid_ptr,
277 boost::shared_ptr<TopologicalData> topo_ptr,
278 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv,
279 SmartPetscObj<Vec> vec, boost::shared_ptr<double> J_ptr = nullptr,
280 Tag tag = Tag())
282 J_ptr, vec, tag),
283 bcData(bc_data), lambdaHybridPtr(lambda_hybrid_ptr), topoData(topo_ptr),
284 scalingMethodsMap(smv) {}
285
286 MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override;
287
288protected:
289 boost::shared_ptr<TractionBcVec> bcData;
290 boost::shared_ptr<MatrixDouble> lambdaHybridPtr;
291 boost::shared_ptr<TopologicalData> topoData;
292 std::map<std::string, boost::shared_ptr<ScalingMethod>> scalingMethodsMap;
293};
294
298 std::string field_name,
299 boost::shared_ptr<AnalyticalTractionBcVec> bc_data,
300 boost::shared_ptr<MatrixDouble> lambda_hybrid_ptr,
301 boost::shared_ptr<TopologicalData> topo_ptr,
302 std::map<std::string, boost::shared_ptr<ScalingMethod>> smv,
303 SmartPetscObj<Vec> vec, boost::shared_ptr<double> J_ptr = nullptr,
304 Tag tag = Tag())
306 J_ptr, vec, tag),
307 bcData(bc_data), lambdaHybridPtr(lambda_hybrid_ptr), topoData(topo_ptr),
308 scalingMethodsMap(smv) {}
309
310 MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override;
311
312protected:
313 boost::shared_ptr<AnalyticalTractionBcVec> bcData;
314 boost::shared_ptr<MatrixDouble> lambdaHybridPtr;
315 boost::shared_ptr<TopologicalData> topoData;
316 std::map<std::string, boost::shared_ptr<ScalingMethod>> scalingMethodsMap;
317};
318
321 OpAssembleVolumeTopologicalDerivativeImpl;
322
323 MoFEMErrorCode integrate(EntData &data);
324};
325
328 OpAssembleVolumeTopologicalDerivativeImpl;
329
330 MoFEMErrorCode integrate(EntData &data);
331};
332
334 : public ForcesAndSourcesCore::UserDataOperator {
335 using OP = ForcesAndSourcesCore::UserDataOperator;
336
338 boost::shared_ptr<DataAtIntegrationPts> data_at_pts_ptr,
339 boost::shared_ptr<TopologicalData> topo_p,
340 boost::shared_ptr<ObjectiveFunctionData> python_ptr,
341 const ObjectiveModelType eval_energy_model = PYTHON_MODEL)
342 : OP(NOSPACE, OP::OPSPACE), dataAtPts(data_at_pts_ptr), topoData(topo_p),
343 pythonPtr(python_ptr), evalEnergyModel(eval_energy_model) {}
344
345 MoFEMErrorCode doWork(int side, EntityType type, EntData &data);
346
347private:
349 boost::shared_ptr<DataAtIntegrationPts> dataAtPts;
350 boost::shared_ptr<TopologicalData> topoData;
351 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
352};
353
355 EntityType type,
356 EntData &data) {
358
359#ifndef NDEBUG
360 if (!dataAtPts)
361 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
362 "DataAtIntegrationPts pointer is null");
363 if (!topoData)
364 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
365 "Topological data pointer is null");
366#endif // NDEBUG
367
368 const int nb_gauss_pts = getGaussPts().size2();
369 if (!nb_gauss_pts)
371
372 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::size(
373 *topoData->objConstantRotation, nb_gauss_pts);
374 topoData->objConstantRotation->clear();
375 const auto &features = dataAtPts->physicsPtr->getFeatures();
376 const auto variable_compliance_mask =
380
381 auto stress_full_ptr = boost::make_shared<MatrixDouble>();
382 auto get_stress_full =
383 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
384 DL>::size(*stress_full_ptr, nb_gauss_pts);
385 stress_full_ptr->clear();
386 auto strain_full_ptr = boost::make_shared<MatrixDouble>();
387 auto get_strain_full =
388 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
389 DL>::size(*strain_full_ptr, nb_gauss_pts);
390 strain_full_ptr->clear();
391
392 auto t_stress = get_stress_full();
393 auto t_strain = get_strain_full();
394
395 auto t_biot = dataAtPts->getFTensorAdjointPdstretch(nb_gauss_pts);
396 auto t_u = dataAtPts->getFTensorStretch(nb_gauss_pts);
397
398 auto next = [&]() {
399 ++t_stress;
400 ++t_strain;
401 ++t_biot;
402 ++t_u;
403 };
404
406
407 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
408 // we have to handle all variants, that will render how the Jacobian
409 // gradient is evaluated.
410 t_stress(i, j) = t_biot(i, j);
411 t_strain(i, j) = t_u(i, j);
412 next();
413 }
414
415 auto evaluate_python_objective = [&]() {
417 if (!pythonPtr)
418 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
419 "ObjectiveFunctionData pointer is null");
420
421 auto &coords = OP::getCoordsAtGaussPts();
422 CHKERR pythonPtr->evalInteriorObjectiveFunction(
423 coords, dataAtPts->getSmallWL2AtPts(), stress_full_ptr, strain_full_ptr,
424 topoData->getObjAtPts(), false);
425 CHKERR pythonPtr->evalInteriorObjectiveGradientStrain(
426 coords, dataAtPts->getSmallWL2AtPts(), stress_full_ptr, strain_full_ptr,
427 topoData->getObjDStrainAtPts(), false);
428 CHKERR pythonPtr->evalInteriorObjectiveGradientU(
429 coords, dataAtPts->getSmallWL2AtPts(), stress_full_ptr, strain_full_ptr,
430 topoData->getObjDDisplacementAtPts(), false);
431 CHKERR pythonPtr->evalInteriorObjectiveGradientStress(
432 coords, dataAtPts->getSmallWL2AtPts(), stress_full_ptr, strain_full_ptr,
433 topoData->getObjDStressAtPts(), false);
435 };
436
437 auto evaluate_energy_of_hencky_model = [&]() {
439
440 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
441 *topoData->getObjDDisplacementAtPts(), nb_gauss_pts);
442 topoData->getObjDDisplacementAtPts()->clear();
443 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
444 DL>::size(*topoData->getObjDStressAtPts(), nb_gauss_pts);
445 topoData->getObjDStressAtPts()->clear();
446 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
447 *topoData->getObjDRotationAtPts(), nb_gauss_pts);
448
449 auto eval_evergy = [&](auto &&t_D) {
450 auto get_obj =
451 MatrixSizeHelper<GetFTensor1FromMatType<1, -1, DL>, DL>::size(
452 *topoData->getObjAtPts(), nb_gauss_pts);
453 auto get_dstrain_obj =
454 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
455 DL>::size(*topoData->getObjDStrainAtPts(),
456 nb_gauss_pts);
457 auto t_obj = get_obj();
458 auto t_dstrain_obj = get_dstrain_obj();
459 auto t_log_u = dataAtPts->getFTensorLogStretchTotal(nb_gauss_pts);
460 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
461 t_obj(0) = 0.5 * (t_log_u(i, j) * t_D(i, j, k, l) * t_log_u(k, l));
462 t_dstrain_obj(i, j) = t_D(i, j, k, l) * t_log_u(k, l);
463 ++t_log_u;
464 ++t_obj;
465 ++t_dstrain_obj;
466 ++t_D;
467 }
468 };
469
471 eval_evergy(
472 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(dataAtPts->matD));
473 } else {
474 eval_evergy(getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->matD));
475 }
476
477 topoData->getObjDRotationAtPts()->clear();
479 };
480
481 auto evaluate_energy_of_hencky_model_nostreach = [&]() {
483
484 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
485 *topoData->getObjDDisplacementAtPts(), nb_gauss_pts);
486 topoData->getObjDDisplacementAtPts()->clear();
487 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
488 DL>::size(*topoData->getObjDStrainAtPts(), nb_gauss_pts);
489 topoData->getObjDStrainAtPts()->clear();
490 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
491 *topoData->getObjDRotationAtPts(), nb_gauss_pts);
492 topoData->getObjDRotationAtPts()->clear();
493
494 auto eval_evergy = [&](auto &&t_inv_D) {
495 auto get_obj =
496 MatrixSizeHelper<GetFTensor1FromMatType<1, -1, DL>, DL>::size(
497 *topoData->getObjAtPts(), nb_gauss_pts);
498 auto get_dstress_obj =
499 MatrixSizeHelper<GetFTensor2FromMatType<SPACE_DIM, SPACE_DIM, -1, DL>,
500 DL>::size(*topoData->getObjDStressAtPts(),
501 nb_gauss_pts);
502 auto t_obj = get_obj();
503 auto t_dstress_obj = get_dstress_obj();
504 auto t_stress = dataAtPts->getFTensorAdjointPdstretch(nb_gauss_pts);
505 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
506 t_obj(0) =
507 0.5 * (t_stress(i, j) * t_inv_D(i, j, k, l) * t_stress(k, l));
508 t_dstress_obj(i, j) = t_inv_D(i, j, k, l) * t_stress(k, l);
509 ++t_stress;
510 ++t_obj;
511 ++t_dstress_obj;
512 ++t_inv_D;
513 }
514 };
515
516 if ((features & variable_compliance_mask).none()) {
517 eval_evergy(
518 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(dataAtPts->matInvD));
519 } else {
520 eval_evergy(
521 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->matInvD));
522 }
524 };
525
526 auto conversion_of_biot_stress = [&]() {
528 // Pull Python's Biot-stress covector back to Piola and both rotation
529 // factors.
530 MatrixSizeHelper<GetFTensor1FromMatType<3, -1, DL>, DL>::size(
531 *topoData->getObjDRotationAtPts(), nb_gauss_pts);
532 topoData->getObjDRotationAtPts()->clear();
533 auto objective = topoData->getFTensorObjDStress(nb_gauss_pts);
534 auto R = dataAtPts->getFTensorRotMat(nb_gauss_pts);
535 auto P = dataAtPts->getFTensorApproxP(nb_gauss_pts);
536 auto gradient = dataAtPts->getFTensorSmallWGradH1(nb_gauss_pts);
537 FTENSOR_INDEXES(3, i, k, l, m, o);
538 constexpr auto identity = FTensor::Kronecker_Delta<double>();
539 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
541 covector(l, o) = objective(l, o);
542 h1(o, k) = identity(o, k);
545 h1(o, k) += gradient(o, k);
546 objective(i, k) = R(i, l) * (covector(l, o) * h1(o, k));
547 for (int mode = 0; mode != 2; ++mode) {
550 using namespace LogarithmicDirectionalDerivatives;
551 const auto read = [&](MatrixPtr values) {
552 Vector result;
553 auto view = GetFTensor1FromMatImpl<3, -1, DL, MatrixDouble>::get(
554 *values, gg, 0);
555 result(i) = view(i);
556 return result;
557 };
558 const SplitRotation rotation(read(dataAtPts->constantRotation),
559 read(dataAtPts->higherRotation));
560 derivative(i, l, m) = rotation.firstTensor(mode)(i, l, m);
561 } else {
562 derivative(i, l, m) = levi_civita(i, l, m);
563 }
564 auto rotation_covector =
565 topoData->getFTensorObjDRotation(nb_gauss_pts, mode, gg);
566 rotation_covector(m) =
567 covector(l, o) * (derivative(i, l, m) * P(i, k)) * h1(o, k);
568 }
569 }
570 ++objective;
571 ++R;
572 ++P;
573 ++gradient;
574 }
576 };
577
578 auto conversion_of_stretch = [&]() {
580 // Python sees the physical stretch tensor. The stretch field stores log
581 // stretch, so convert dJ/dU to dJ/dlogU once here.
582 auto t_obj_dstretch = topoData->getFTensorObjDStrain(nb_gauss_pts);
583 auto t_diff_stretch = dataAtPts->getFTensorDiffStretch(nb_gauss_pts);
584
589
590 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
592 t_dJ_dstretch(i, j) = t_obj_dstretch(i, j);
593
594 t_obj_dstretch(k, l) = t_dJ_dstretch(i, j) * t_diff_stretch(i, j, k, l);
595
596 ++t_obj_dstretch;
597 ++t_diff_stretch;
598 }
599
601 };
602
603 auto conversion_of_stretch_to_stress_for_no_stretch = [&](auto t_inv_D) {
605 // In no-stretch mode, log stretch is computed from the stress field. Fold
606 // the objective stretch derivative into the stress derivative buffer.
607 auto t_obj_dstress = topoData->getFTensorObjDStress(nb_gauss_pts);
608 auto t_obj_dstretch = topoData->getFTensorObjDStrain(nb_gauss_pts);
609
614
615 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
617 t_dstretch_dstress(i, j) =
618 ((t_obj_dstretch(k, l) || t_obj_dstretch(l, k)) / 2.) *
619 t_inv_D(k, l, i, j);
620
621 t_obj_dstress(i, j) += t_dstretch_dstress(i, j);
622
623 ++t_obj_dstress;
624 ++t_obj_dstretch;
625 ++t_inv_D;
626 }
627
629 };
630
631 switch (evalEnergyModel) {
632 case PYTHON_MODEL:
633 CHKERR evaluate_python_objective();
634 CHKERR conversion_of_biot_stress();
636 if ((features & variable_compliance_mask).none()) {
637 CHKERR conversion_of_stretch_to_stress_for_no_stretch(
638 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM, 0>(dataAtPts->matInvD));
639 } else {
640 CHKERR conversion_of_stretch_to_stress_for_no_stretch(
641 getFTensor4DdgFromMat<SPACE_DIM, SPACE_DIM>(dataAtPts->matInvD));
642 }
643 } else {
644 CHKERR conversion_of_stretch();
645 }
646 break;
647 case HENCKY_MODEL:
649 CHKERR evaluate_energy_of_hencky_model_nostreach();
650 CHKERR conversion_of_biot_stress();
651 } else {
652 CHKERR evaluate_energy_of_hencky_model();
653 }
654 break;
655 default:
656 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
657 "Objective model type not handled");
658 }
659
661}
662
665 locJ = 0;
666
667#ifndef NDEBUG
668 if (!topoData)
669 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
670 "Topological data pointer is null");
671#endif // NDEBUG
672
673 const int nb_dofs = data.getIndices().size();
674 if (!nb_dofs)
676
677 const int nb_integration_pts = getGaussPts().size2();
678
679 const auto v = getVolume();
680 auto t_w = getFTensor0IntegrationWeight();
681 auto t_obj = topoData->getFTensorObj(nb_integration_pts);
682 auto t_obj_dP = topoData->getFTensorObjDStress(nb_integration_pts);
683 auto t_obj_dStrain = topoData->getFTensorObjDStrain(nb_integration_pts);
684 auto t_obj_dU = topoData->getFTensorObjDDisplacement(nb_integration_pts);
685 auto t_P = dataAtPts->getFTensorApproxP(nb_integration_pts);
686 auto t_det = topoData->getFTensorDetJacobian(nb_integration_pts);
687 auto t_inv_jac = topoData->getFTensorInvJacobian(nb_integration_pts);
688 auto t_jac = topoData->getFTensorJacobian(nb_integration_pts);
689
690 auto next = [&]() {
691 ++t_w;
692 ++t_obj;
693 ++t_obj_dP;
694 ++t_obj_dStrain;
695 ++t_obj_dU;
696 ++t_P;
697 ++t_det;
698 ++t_inv_jac;
699 ++t_jac;
700 };
701
703 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
704
705 auto get_ftensor1 = [](auto &v) {
707 &v[0], &v[1], &v[2]);
708 };
709
710 nF.clear();
711
712 const int nb_base_functions = data.getN().size2();
713 auto t_base_diff = data.getFTensor1DiffN<SPACE_DIM>();
714 for (int gg = 0; gg != nb_integration_pts; ++gg) {
715 locJ += (t_w * v * t_det) * t_obj;
716
718 t_cof(i, j) = t_det * t_inv_jac(j, i);
719
721 t_dJ_dX(I, J) =
722
723 t_obj * t_cof(I, J)
724
725 +
726
727 t_obj_dP(i, j) * (t_kd(j, I) * (t_kd(k, J) * t_P(i, k)) -
728 t_inv_jac(I, J) * t_jac(j, k) * t_P(i, k));
729
730 auto t_nf = get_ftensor1(nF);
731 int bb = 0;
732 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
733 t_nf(i) += (t_w * v) * t_dJ_dX(i, j) * t_base_diff(j);
734 ++t_nf;
735 ++t_base_diff;
736 }
737 for (; bb != nb_base_functions; ++bb)
738 ++t_base_diff;
739
740 next();
741 }
742
744}
745
748
749#ifndef NDEBUG
750 if (!topoData)
751 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
752 "Topological data pointer is null");
753#endif // NDEBUG
754
755 const int nb_dofs = data.getIndices().size();
756 if (!nb_dofs)
758
759 const int nb_integration_pts = data.getN().size1();
760
761 const auto v = getVolume();
762 auto t_w = getFTensor0IntegrationWeight();
763 const int nb_base_functions = data.getN().size2() / SPACE_DIM;
764 auto t_row_base_fun = data.getFTensor1N<SPACE_DIM>();
765
768
769 auto get_ftensor1 = [](auto &v) {
771 &v[0], &v[1], &v[2]);
772 };
773
774 auto t_obj_dP = topoData->getFTensorObjDStress(nb_integration_pts);
775
776 for (int gg = 0; gg != nb_integration_pts; ++gg) {
777 const double a = v * t_w;
778 auto t_nf = get_ftensor1(nF);
779
780 int bb = 0;
781 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
782 t_nf(i) += a * t_row_base_fun(j) * t_obj_dP(i, j);
783 ++t_nf;
784 ++t_row_base_fun;
785 }
786 for (; bb != nb_base_functions; ++bb)
787 ++t_row_base_fun;
788
789 ++t_w;
790 ++t_obj_dP;
791 }
792
794}
795
798
799#ifndef NDEBUG
800 if (!topoData)
801 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
802 "Topological data pointer is null");
803#endif // NDEBUG
804
805 const int nb_dofs = data.getIndices().size();
806 if (!nb_dofs)
808
809 const int nb_integration_pts = data.getN().size1();
810
811 const auto v = getVolume();
812 auto t_w = getFTensor0IntegrationWeight();
813 const int nb_base_functions = data.getN().size2() / (SPACE_DIM * SPACE_DIM);
814 auto t_row_base_fun = data.getFTensor2N<SPACE_DIM, SPACE_DIM>();
815 auto t_obj_dP = topoData->getFTensorObjDStress(nb_integration_pts);
816
819
820 auto get_ftensor0 = [](auto &v) {
822 };
823
824 for (int gg = 0; gg != nb_integration_pts; ++gg) {
825 const double a = v * t_w;
826 auto t_nf = get_ftensor0(nF);
827
828 int bb = 0;
829 for (; bb != nb_dofs; ++bb) {
830 t_nf += a * t_row_base_fun(i, j) * t_obj_dP(i, j);
831 ++t_nf;
832 ++t_row_base_fun;
833 }
834 for (; bb != nb_base_functions; ++bb)
835 ++t_row_base_fun;
836
837 ++t_w;
838 ++t_obj_dP;
839 }
840
842}
843
846
847#ifndef NDEBUG
848 if (!topoData)
849 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
850 "Topological data pointer is null");
851#endif // NDEBUG
852
853 const int nb_dofs = data.getIndices().size();
854 if (!nb_dofs)
856
857 const int nb_integration_pts = data.getN().size1();
858
859 const auto v = getVolume();
860 auto t_w = getFTensor0IntegrationWeight();
861 const int nb_base_functions = data.getN().size2();
862 auto t_row_base_fun = data.getFTensor0N();
863 auto t_obj_dw = topoData->getFTensorObjDDisplacement(nb_integration_pts);
864
866
867 auto get_ftensor1 = [](auto &v) {
869 &v[0], &v[1], &v[2]);
870 };
871
872 for (int gg = 0; gg != nb_integration_pts; ++gg) {
873 const double a = v * t_w;
874 auto t_nf = get_ftensor1(nF);
875
876 int bb = 0;
877 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
878 t_nf(i) += a * t_row_base_fun * t_obj_dw(i);
879 ++t_nf;
880 ++t_row_base_fun;
881 }
882 for (; bb != nb_base_functions; ++bb)
883 ++t_row_base_fun;
884
885 ++t_w;
886 ++t_obj_dw;
887 }
888
890}
891
894
895#ifndef NDEBUG
896 if (!topoData)
897 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
898 "Topological data pointer is null");
899#endif // NDEBUG
900
901 const int nb_dofs = data.getIndices().size();
902 if (!nb_dofs)
904
905 const int nb_integration_pts = data.getN().size1();
906
907 const auto v = getVolume();
908 auto t_w = getFTensor0IntegrationWeight();
909 const int nb_base_functions = data.getN().size2();
910 auto t_row_base_fun = data.getFTensor0N();
911
913
914 auto get_ftensor1 = [](auto &v) {
916 &v[0], &v[1], &v[2]);
917 };
918
919 for (int gg = 0; gg != nb_integration_pts; ++gg) {
920 const double a = v * t_w;
921 auto t_nf = get_ftensor1(nF);
922
923 int bb = 0;
924 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
925 auto objective = topoData->getFTensorObjDRotation(nb_integration_pts,
926 bb == 0 ? 0 : 1, gg);
927 t_nf(i) += a * t_row_base_fun * objective(i);
928 ++t_nf;
929 ++t_row_base_fun;
930 }
931 for (; bb != nb_base_functions; ++bb)
932 ++t_row_base_fun;
933
934 ++t_w;
935 }
936
938}
939
942
943#ifndef NDEBUG
944 if (!topoData)
945 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
946 "Topological data pointer is null");
947#endif // NDEBUG
948
949 const int nb_dofs = data.getIndices().size();
950 if (!nb_dofs)
952
953 const int nb_integration_pts = data.getN().size1();
954
955 auto t_w = getFTensor0IntegrationWeight();
956 const int nb_base_functions = data.getN().size2();
957 auto t_row_base_fun = data.getFTensor0N();
958 auto t_obj_du_gamma =
959 topoData->getFTensorObjDDisplacement(nb_integration_pts);
960
962
963 auto get_ftensor1 = [](auto &v) {
965 &v[0], &v[1], &v[2]);
966 };
967
968 for (int gg = 0; gg != nb_integration_pts; ++gg) {
969 const double a = t_w * getMeasure();
970 auto t_nf = get_ftensor1(nF);
971
972 int bb = 0;
973 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
974 t_nf(i) += a * t_row_base_fun * t_obj_du_gamma(i);
975 ++t_nf;
976 ++t_row_base_fun;
977 }
978 for (; bb != nb_base_functions; ++bb)
979 ++t_row_base_fun;
980
981 ++t_w;
982 ++t_obj_du_gamma;
983 }
984
986}
987
990
991#ifndef NDEBUG
992 if (!topoData)
993 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
994 "Topological data pointer is null");
995#endif // NDEBUG
996
997 const int nb_dofs = data.getIndices().size();
998 if (!nb_dofs)
1000
1001 const int nb_integration_pts = OP::getGaussPts().size2();
1002
1003 auto t_normal = OP::getFTensor1NormalsAtGaussPts();
1004 auto t_w = OP::getFTensor0IntegrationWeight();
1005 const int nb_base_functions = data.getN().size2() / SPACE_DIM;
1006 auto t_row_base_fun = data.getFTensor1N<SPACE_DIM>();
1007 auto t_obj_dtraction =
1008 topoData->getFTensorObjDDisplacement(nb_integration_pts);
1009
1012
1013 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1014 auto t_nf = getFTensor1FromPtr<SPACE_DIM>(&*OP::locF.begin());
1015 int bb = 0;
1016 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1017 t_nf(i) +=
1018 t_w * (t_row_base_fun(j) * t_normal(j)) * t_obj_dtraction(i) * 0.5;
1019 ++t_nf;
1020 ++t_row_base_fun;
1021 }
1022 for (; bb != nb_base_functions; ++bb)
1023 ++t_row_base_fun;
1024
1025 ++t_w;
1026 ++t_normal;
1027 ++t_obj_dtraction;
1028 }
1029
1031}
1032
1033MoFEMErrorCode OpTauStabilisation_dX::integrate(int, EntityType,
1034 EntData &data) {
1036 locJ = 0;
1037
1038#ifndef NDEBUG
1039 if (!topoData)
1040 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1041 "Topological data pointer is null");
1042 if (!brokenDispDataPtr)
1043 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1044 "Broken displacement data pointer is null");
1045 if (!hybridDispPtr)
1046 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1047 "Hybrid displacement pointer is null");
1048 if (!varHybridDispPtr)
1049 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1050 "Adjoint hybrid displacement pointer is null");
1051#endif // NDEBUG
1052
1053 const int nb_dofs = data.getIndices().size();
1054 if (!nb_dofs)
1056
1057 const int nb_integration_pts = getGaussPts().size2();
1058 const int nb_base_functions = data.getN().size2();
1059
1060#ifndef NDEBUG
1061 if (this->nF.size() != nb_dofs)
1062 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1063 "Size of nF %ld != nb_dofs %d", this->nF.size(), nb_dofs);
1064 if (data.getDiffN().size1() != nb_integration_pts)
1065 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1066 "Differential of base functions should have the same number of "
1067 "integration points as the data");
1068 if (data.getDiffN().size2() != nb_base_functions * 2)
1069 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1070 "Differential of base functions should have the same number of "
1071 "base functions as the data");
1072#endif // NDEBUG
1073
1077
1078 auto &coords = getCoords();
1079 // Tau scale is based on the mesh triangle coordinates, not on the perturbed
1080 // material-position field. Treat h as constant with respect to X.
1081 const double h =
1082 std::get<2>(Tools::getTricircumcenter3d(coords.data().data()));
1083
1084 auto t_w = getFTensor0IntegrationWeight();
1085 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1086 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1087 auto t_u_hybrid = getFTensor1FromMat<SPACE_DIM, -1, DL>(*hybridDispPtr);
1088 auto t_var_u_hybrid =
1089 getFTensor1FromMat<SPACE_DIM, -1, DL>(*varHybridDispPtr);
1090 auto t_diff_base = data.getFTensor1DiffN<2>();
1091
1092 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1094 t_normal(j) =
1095 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1096
1097 double area = std::sqrt(t_normal(i) * t_normal(i));
1099 t_da(i) = t_normal(i) / area;
1100 area /= 2.;
1101 t_da(i) /= 2.;
1102
1103 double tau_density = 0;
1104 for (auto &bd : *brokenDispDataPtr) {
1105 auto t_u_broken = getFTensor1FromMat<SPACE_DIM, -1, DL>(
1106 bd.getFlux(), nb_integration_pts);
1107 auto t_var_u_broken = getFTensor1FromMat<SPACE_DIM, -1, DL>(
1108 bd.getVarFlux(), nb_integration_pts);
1109 for (int ss = 0; ss != gg; ++ss) {
1110 ++t_u_broken;
1111 ++t_var_u_broken;
1112 }
1113
1114 // This is the adjoint-weighted material derivative of the four tau
1115 // stabilisation residual blocks:
1116 // u_gamma-u_gamma, L2-L2, u_gamma-L2, and L2-u_gamma.
1117 const double hybrid_hybrid = t_var_u_hybrid(i) * t_u_hybrid(i);
1118 const double broken_broken = t_var_u_broken(i) * t_u_broken(i);
1119 const double hybrid_broken = -t_var_u_hybrid(i) * t_u_broken(i);
1120 const double broken_hybrid = -t_var_u_broken(i) * t_u_hybrid(i);
1121 tau_density +=
1122 hybrid_hybrid + broken_broken + hybrid_broken + broken_hybrid;
1123 }
1124
1125 const double tau = alphaTau / h;
1126 locJ += t_w * tau * area * tau_density;
1127
1128 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1129 int rr = 0;
1130 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1132 t_normal_dX(j, I) =
1133 (FTensor::levi_civita(i, j, I) * t_tangent2(i)) * t_diff_base(N0) +
1134 (FTensor::levi_civita(I, j, k) * t_tangent1(k)) * t_diff_base(N1);
1135
1136 t_nf(I) +=
1137 t_w * alphaTau * tau_density * (t_da(i) * t_normal_dX(i, I)) / h;
1138 ++t_diff_base;
1139 ++t_nf;
1140 }
1141 for (; rr != nb_base_functions; ++rr)
1142 ++t_diff_base;
1143
1144 ++t_w;
1145 ++t_tangent1;
1146 ++t_tangent2;
1147 ++t_u_hybrid;
1148 ++t_var_u_hybrid;
1149 }
1150
1152}
1153
1154MoFEMErrorCode OpDispBc_dX::integrate(int, EntityType type, EntData &data) {
1156 locJ = 0;
1157
1158#ifndef NDEBUG
1159 if (!brokenSideDataPtr)
1160 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1161 "Broken side data pointer is null");
1162#endif // NDEBUG
1163
1164 const int nb_dofs = data.getIndices().size();
1165 if (!nb_dofs)
1167
1168 const int nb_integration_pts = getGaussPts().size2();
1169 const int nb_base_functions = data.getN().size2();
1170
1171#ifndef NDEBUG
1172 if (data.getDiffN().size1() != nb_integration_pts)
1173 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1174 "Differential of base functions should have the same number of "
1175 "integration points as the data");
1176 if (data.getDiffN().size2() != nb_base_functions * 2)
1177 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1178 "Differential of base functions should have the same number of "
1179 "base functions as the data");
1180#endif // NDEBUG
1181
1182 double time = getFEMethod()->ts_t;
1185
1187
1190
1191 const EntityHandle fe_ent = getFEEntityHandle();
1192 for (auto &bc : *bcDispPtr) {
1193 if (bc.faces.find(fe_ent) == bc.faces.end())
1194 continue;
1195
1196 double scale = 1;
1197 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1198 scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1199 } else {
1200 MOFEM_LOG("SELF", Sev::warning)
1201 << "No scaling method found for " << bc.blockName;
1202 }
1203
1204 FTensor::Tensor1<double, SPACE_DIM> t_bc_disp(bc.vals[0], bc.vals[1],
1205 bc.vals[2]);
1206 t_bc_disp(i) *= scale;
1207
1208 for (auto &bd : *brokenSideDataPtr) {
1209 auto t_w = getFTensor0IntegrationWeight();
1210 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1211 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1212 auto t_var_flux =
1213 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(bd.getVarFlux());
1214 auto t_diff_base = data.getFTensor1DiffN<2>();
1215
1216 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1217 const double a = 0.5 * bd.getSense() * t_w;
1218
1220 t_normal(j) =
1221 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1222
1223 locJ += a * t_bc_disp(i) * (t_var_flux(i, j) * t_normal(j));
1224
1225 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1226 int bb = 0;
1227 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1228 // The H(div) contravariant Piola trace P . n dA is invariant with
1229 // respect to material-position perturbations. The normal variation is
1230 // cancelled by the Piola variation of the flux, so this BC
1231 // contributes to locJ but not to the exact dX vector.
1232 ++t_nf;
1233 ++t_diff_base;
1234 }
1235 for (; bb != nb_base_functions; ++bb)
1236 ++t_diff_base;
1237
1238 ++t_w;
1239 ++t_tangent1;
1240 ++t_tangent2;
1241 ++t_var_flux;
1242 }
1243 }
1244 }
1245
1247}
1248
1249MoFEMErrorCode OpAnalyticalDispBc_dX::integrate(int, EntityType type,
1250 EntData &data) {
1252 locJ = 0;
1253
1254#ifndef NDEBUG
1255 if (!brokenSideDataPtr)
1256 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1257 "Broken side data pointer is null");
1258#endif // NDEBUG
1259
1260 const int nb_dofs = data.getIndices().size();
1261 if (!nb_dofs)
1263
1264 const int nb_integration_pts = getGaussPts().size2();
1265 const int nb_base_functions = data.getN().size2();
1266
1267#ifndef NDEBUG
1268 if (data.getDiffN().size1() != nb_integration_pts)
1269 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1270 "Differential of base functions should have the same number of "
1271 "integration points as the data");
1272 if (data.getDiffN().size2() != nb_base_functions * 2)
1273 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1274 "Differential of base functions should have the same number of "
1275 "base functions as the data");
1276#endif // NDEBUG
1277
1281
1282 const EntityHandle fe_ent = getFEEntityHandle();
1283 for (auto &bc : *bcDispPtr) {
1284 if (bc.faces.find(fe_ent) == bc.faces.end())
1285 continue;
1286
1287 auto v_analytical_expr = getTopologicalAnalyticalExpr(this, bc.blockName);
1288
1289 for (auto &bd : *brokenSideDataPtr) {
1290 auto t_w = getFTensor0IntegrationWeight();
1291 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1292 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1293 auto t_var_flux =
1294 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(bd.getVarFlux());
1295 auto t_diff_base = data.getFTensor1DiffN<2>();
1296 auto t_bc_disp = getFTensor1FromMat<SPACE_DIM, -1, DL>(v_analytical_expr);
1297
1298 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1299 const double a = 0.5 * bd.getSense() * t_w;
1300
1302 t_normal(j) =
1303 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1304
1305 locJ += a * t_bc_disp(i) * (t_var_flux(i, j) * t_normal(j));
1306
1307 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1308 int bb = 0;
1309 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1310 // The H(div) contravariant Piola trace P . n dA is invariant with
1311 // respect to material-position perturbations. The normal variation is
1312 // cancelled by the Piola variation of the flux, so this BC
1313 // contributes to locJ but not to the exact dX vector.
1314 ++t_nf;
1315 ++t_diff_base;
1316 }
1317 for (; bb != nb_base_functions; ++bb)
1318 ++t_diff_base;
1319
1320 ++t_w;
1321 ++t_tangent1;
1322 ++t_tangent2;
1323 ++t_var_flux;
1324 ++t_bc_disp;
1325 }
1326 }
1327 }
1328
1330}
1331
1332MoFEMErrorCode OpBrokenTractionBc_dX::integrate(int side, EntityType type,
1333 EntData &data) {
1335 locJ = 0;
1336
1340
1341 int nb_dofs = data.getFieldData().size();
1342 int nb_integration_pts = getGaussPts().size2();
1343 int nb_base_functions = data.getN().size2();
1344
1345 double time = getFEMethod()->ts_t;
1348 }
1349
1350#ifndef NDEBUG
1351 if (this->nF.size() != nb_dofs)
1352 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1353 "Size of nF %ld != nb_dofs %d", this->nF.size(), nb_dofs);
1354#endif // NDEBUG
1355
1356 auto integrate_rhs = [&](auto &bc, auto calc_tau, double time_scale) {
1358
1359 auto t_val = getFTensor1FromPtr<3>(&*bc.vals.begin());
1360 auto t_diff_base = data.getFTensor1DiffN<2>();
1361 auto t_w = getFTensor0IntegrationWeight();
1362 auto t_coords = getFTensor1CoordsAtGaussPts();
1363
1364 auto t_var_u_gamma = getFTensor1FromMat<SPACE_DIM>(lambdaHybridPtr);
1365 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1366 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1367
1368 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1369
1371 t_normal(j) =
1372 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1373
1374 double a = sqrt(t_normal(i) * t_normal(i));
1376 t_da(i) = t_normal(i) / a;
1377 a /= 2.;
1378 t_da(i) /= 2.;
1379
1380 const auto tau = calc_tau(t_coords(0), t_coords(1), t_coords(2));
1381 locJ -= (time_scale * t_w * a * tau) * (t_val(i) * t_var_u_gamma(i));
1382
1383 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1384 int rr = 0;
1385 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1387 t_normal_dX(j, I) =
1388 (FTensor::levi_civita(i, j, I) * t_tangent2(i)) * t_diff_base(N0) +
1389 (FTensor::levi_civita(I, j, k) * t_tangent1(k)) * t_diff_base(N1);
1390 t_nf(I) -= (time_scale * t_w * tau) * (t_val(i) * t_var_u_gamma(i)) *
1391 (t_da(i) * t_normal_dX(i, I));
1392 ++t_diff_base;
1393 ++t_nf;
1394 }
1395 for (; rr != nb_base_functions; ++rr)
1396 ++t_diff_base;
1397
1398 ++t_w;
1399 ++t_coords;
1400 ++t_var_u_gamma;
1401 ++t_tangent1;
1402 ++t_tangent2;
1403 }
1404
1406 };
1407
1408 // get entity of face
1409 EntityHandle fe_ent = getFEEntityHandle();
1410 for (auto &bc : *(bcData)) {
1411 if (bc.faces.find(fe_ent) != bc.faces.end()) {
1412
1413 double time_scale = 1;
1414 if (scalingMethodsMap.find(bc.blockName) != scalingMethodsMap.end()) {
1415 time_scale *= scalingMethodsMap.at(bc.blockName)->getScale(time);
1416 }
1417
1418 if (nb_dofs) {
1419 if (std::regex_match(bc.blockName, std::regex(".*COOK.*"))) {
1420 auto calc_tau = [](double, double y, double) {
1421 y -= 44;
1422 y /= (60 - 44);
1423 return -y * (y - 1) / 0.25;
1424 };
1425 CHKERR integrate_rhs(bc, calc_tau, time_scale);
1426 } else {
1427 CHKERR integrate_rhs(
1428 bc, [](double, double, double) { return 1; }, time_scale);
1429 }
1430 }
1431 }
1432 }
1434}
1435
1437 EntityType type,
1438 EntData &data) {
1440 locJ = 0;
1441
1448
1449 int nb_dofs = data.getFieldData().size();
1450 int nb_integration_pts = getGaussPts().size2();
1451 int nb_base_functions = data.getN().size2();
1452
1453#ifndef NDEBUG
1454 if (this->nF.size() != nb_dofs)
1455 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1456 "Size of nF %ld != nb_dofs %d", this->nF.size(), nb_dofs);
1457#endif // NDEBUG
1458
1459 auto integrate_rhs = [&](auto &bc) {
1461
1462 auto v_analytical_expr = getTopologicalAnalyticalExpr(this, bc.blockName);
1463
1464 auto t_val = getFTensor1FromMat<SPACE_DIM, -1, DL>(v_analytical_expr);
1465 auto t_diff_base = data.getFTensor1DiffN<2>();
1466 auto t_w = getFTensor0IntegrationWeight();
1467
1468 auto t_var_u_gamma = getFTensor1FromMat<SPACE_DIM>(lambdaHybridPtr);
1469 auto t_tangent1 = getFTensor1Tangent1AtGaussPts();
1470 auto t_tangent2 = getFTensor1Tangent2AtGaussPts();
1471
1472 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1473
1475 t_normal(j) =
1476 (FTensor::levi_civita(i, j, k) * t_tangent1(k)) * t_tangent2(i);
1477
1478 double a = sqrt(t_normal(i) * t_normal(i));
1480 t_da(i) = t_normal(i) / a;
1481 a /= 2.;
1482 t_da(i) /= 2.;
1483
1484 locJ -= (t_w * a) * (t_val(i) * t_var_u_gamma(i));
1485
1486 auto t_nf = getFTensor1FromArray<SPACE_DIM, SPACE_DIM>(nF);
1487 int rr = 0;
1488 for (; rr != nb_dofs / SPACE_DIM; ++rr) {
1490 t_normal_dX(j, I) =
1491 (FTensor::levi_civita(i, j, I) * t_tangent2(i)) * t_diff_base(N0) +
1492 (FTensor::levi_civita(I, j, k) * t_tangent1(k)) * t_diff_base(N1);
1493 t_nf(I) -=
1494 t_w * (t_val(i) * t_var_u_gamma(i)) * (t_da(i) * t_normal_dX(i, I));
1495 ++t_diff_base;
1496 ++t_nf;
1497 }
1498 for (; rr != nb_base_functions; ++rr)
1499 ++t_diff_base;
1500
1501 ++t_w;
1502 ++t_val;
1503 ++t_var_u_gamma;
1504 ++t_tangent1;
1505 ++t_tangent2;
1506 }
1507
1509 };
1510
1511 EntityHandle fe_ent = getFEEntityHandle();
1512 for (auto &bc : *(bcData)) {
1513 if (bc.faces.find(fe_ent) != bc.faces.end() && nb_dofs) {
1514 CHKERR integrate_rhs(bc);
1515 }
1516 }
1517
1519}
1520
1523
1524#ifndef NDEBUG
1525 if (!topoData)
1526 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1527 "Topological data pointer is null");
1528#endif // NDEBUG
1529
1530 const int nb_dofs = data.getIndices().size();
1531 if (!nb_dofs)
1533
1534 const int nb_integration_pts = data.getN().size1();
1535
1536 const auto v = getVolume();
1537 auto t_w = getFTensor0IntegrationWeight();
1538 const int nb_base_functions = data.getN().size2();
1539 auto t_row_base_fun = data.getFTensor0N();
1540
1541 auto t_obj_dlog_stretch = topoData->getFTensorObjDStrain(nb_integration_pts);
1542
1545 FTensor::Index<'L', size_symm> L;
1547
1548 auto get_ftensor1 = [](auto &v) {
1550 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5]);
1551 };
1552
1553 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1554 const double a = v * t_w;
1555 auto t_nf = get_ftensor1(OP::nF);
1556
1558 t_obj_dU(L) = t_obj_dlog_stretch(i, j) * t_L(i, j, L);
1559
1560 int bb = 0;
1561 for (; bb != nb_dofs / size_symm; ++bb) {
1562 t_nf(L) += a * t_row_base_fun * t_obj_dU(L);
1563 ++t_nf;
1564 ++t_row_base_fun;
1565 }
1566 for (; bb != nb_base_functions; ++bb)
1567 ++t_row_base_fun;
1568
1569 ++t_w;
1570 ++t_obj_dlog_stretch;
1571 }
1572
1574}
1575
1579 const std::string field_name,
1580 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1581 boost::shared_ptr<TopologicalData> topo_ptr,
1582 SmartPetscObj<Vec> assemble_vec, const double alpha, const double rho,
1583 const double alpha_viscous_omega = 0,
1584 boost::shared_ptr<double> J_ptr = nullptr)
1586 field_name, data_ptr, topo_ptr, J_ptr, assemble_vec, Tag()),
1587 alphaW(alpha), alphaRho(rho), alphaViscousOmega(alpha_viscous_omega) {}
1588
1589 MoFEMErrorCode integrate(EntData &data) {
1591#ifndef NDEBUG
1593 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1594 "L2 user base scale is set to %d, current inplementation only "
1595 "hanlde case for false",
1597 }
1598#endif // NDEBUG
1599
1600#ifndef NDEBUG
1601 if (!dataAtPts)
1602 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1603 "DataAtIntegrationPts pointer is null");
1604#endif // NDEBUG
1605
1606 const int nb_dofs = data.getIndices().size();
1607 if (!nb_dofs)
1609
1610 const int nb_integration_pts = getGaussPts().size2();
1611
1612 const auto v = getVolume();
1613 auto t_w = getFTensor0IntegrationWeight();
1614 // OpSpatialEquilibrium
1615 auto t_div_P = dataAtPts->getFTensorDivP(nb_integration_pts);
1616 auto t_var_w = dataAtPts->getFTensorVarWL2(nb_integration_pts);
1617 // OpSpatialRotation
1618 auto t_approx_P = dataAtPts->getFTensorApproxP(nb_integration_pts);
1619 auto t_u_h1 = dataAtPts->getFTensorStretchH1(nb_integration_pts);
1620 auto t_var_omega = dataAtPts->getFTensorVarRotAxis(nb_integration_pts);
1621 // OpSpatialConsistencyP
1622 auto t_h = dataAtPts->getFTensorSmallH(nb_integration_pts);
1623 auto t_var_P = dataAtPts->getFTensorVarPiola(nb_integration_pts);
1624 auto t_w_l2 = dataAtPts->getFTensorSmallWL2(nb_integration_pts);
1625 auto t_var_div_P = dataAtPts->getFTensorDivVarPiola(nb_integration_pts);
1626
1627 auto t_jac = topoData->getFTensorJacobian(nb_integration_pts);
1628
1629 auto get_ftensor1 = [](auto &v) {
1631 &v[0], &v[1], &v[2]);
1632 };
1633
1634 auto next = [&]() {
1635 ++t_w;
1636 ++t_div_P;
1637 ++t_var_w;
1638 ++t_approx_P;
1639 ++t_u_h1;
1640 ++t_var_omega;
1641 ++t_h;
1642 ++t_var_P;
1643 ++t_w_l2;
1644 ++t_var_div_P;
1645 ++t_jac;
1646 };
1647
1654
1657
1658 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1659
1660 locJ = 0;
1661 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1662 double a = v * t_w;
1663
1664 // The adjoint direction varies both element-constant and higher modes.
1667 using namespace LogarithmicDirectionalDerivatives;
1668 const auto read = [&](MatrixPtr values) {
1669 Vector result;
1670 auto view = GetFTensor1FromMatImpl<3, -1, DL, MatrixDouble>::get(
1671 *values, gg, 0);
1672 result(i) = view(i);
1673 return result;
1674 };
1675 const SplitRotation rotation(read(dataAtPts->constantRotation),
1676 read(dataAtPts->higherRotation));
1677 variation_R(i, j) =
1678 rotation.first(read(dataAtPts->varConstantRotation),
1679 read(dataAtPts->varHigherRotation))(i, j);
1680 } else {
1681 variation_R(i, j) = levi_civita(i, j, k) * t_var_omega(k);
1682 }
1683
1685 t_diff;
1686 t_diff(i, j, l, k) = t_kd(i, l) * t_kd(j, k);
1687
1688 // OpSpatialEqulibrium
1689 {
1690 const auto beta = a * (t_div_P(i) * t_var_w(i));
1691 locJ -= beta;
1692 }
1693 // OpSpatialEquilibrium
1694 {
1695 double beta;
1699 case LARGE_ROT:
1700 case MODERATE_ROT:
1701 beta =
1702
1703 (variation_R(j, k) * t_u_h1(k, l))
1704
1705 * (t_approx_P(j, n) * t_jac(l, n));
1706
1707 t_beta_dX(I, J) =
1708
1709 (variation_R(j, k) * t_u_h1(k, l))
1710
1711 * (t_approx_P(j, n) * t_diff(l, n, I, J));
1712
1713 break;
1714 case SMALL_ROT:
1715 beta =
1716
1717 variation_R(i, j)
1718
1719 * (t_approx_P(i, n) * t_jac(j, n));
1720
1721 t_beta_dX(I, J) =
1722
1723 variation_R(i, j)
1724
1725 * (t_approx_P(i, n) * t_diff(j, n, I, J));
1726
1727 break;
1728 default:
1729 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1730 "gradApproximator not handled");
1731 break;
1732 };
1733
1734 locJ -= a * beta;
1735 auto t_nf = get_ftensor1(nF);
1736 auto t_base_diff = data.getFTensor1DiffN<3>(gg, 0);
1737 for (int bb = 0; bb != nb_dofs / SPACE_DIM; ++bb) {
1738 t_nf(i) -= a * (t_beta_dX(i, j) * t_base_diff(j));
1739 ++t_nf;
1740 ++t_base_diff;
1741 }
1742 }
1743 // OpSpatialConsistency
1744 {
1745 const auto beta =
1746 (t_h(i, j) - t_kd(i, j)) * (t_var_P(i, n) * t_jac(j, n));
1748 t_beta_dX(I, J) =
1749 (t_h(i, j) - t_kd(i, j)) * (t_var_P(i, n) * t_diff(j, n, I, J));
1750 locJ -= a * beta;
1751 auto t_nf = get_ftensor1(nF);
1752 auto t_base_diff = data.getFTensor1DiffN<3>(gg, 0);
1753 for (int bb = 0; bb != nb_dofs / SPACE_DIM; ++bb) {
1754 t_nf(i) -= a * (t_beta_dX(i, j) * t_base_diff(j));
1755 ++t_nf;
1756 ++t_base_diff;
1757 }
1758 }
1759 // OpSpatialConsistency, cont
1760 {
1761 const auto beta = t_w_l2(i) * t_var_div_P(i);
1762 locJ -= a * beta;
1763 }
1764
1765 next();
1766 }
1767
1769 }
1770
1771private:
1772 const double alphaW;
1773 const double alphaRho;
1774 const double alphaViscousOmega;
1775};
1776
1780 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1781 SmartPetscObj<Vec> assemble_vec,
1782 boost::shared_ptr<TopologicalData> topo_ptr,
1783 const double alpha, const double rho,
1784 const double alpha_viscous_omega = 0)
1786 field_name, data_ptr, topo_ptr, nullptr, assemble_vec, Tag()),
1787 alphaW(alpha), alphaRho(rho) {
1788 if (alpha_viscous_omega)
1791 "OpSensitivityInterior_dX with alpha_viscous_omega != 0 is not "
1792 "implemented yet");
1793 }
1794
1795 MoFEMErrorCode integrate(EntData &data) {
1797
1798#ifndef NDEBUG
1799 if (!dataAtPts)
1800 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1801 "DataAtIntegrationPts pointer is null");
1802#endif // NDEBUG
1803
1804 const int nb_dofs = data.getIndices().size();
1805 if (!nb_dofs)
1807
1808 const int nb_integration_pts = getGaussPts().size2();
1809
1810 const auto v = getVolume();
1811 auto t_w = getFTensor0IntegrationWeight();
1812 auto t_div_P = dataAtPts->getFTensorDivP(nb_integration_pts);
1813 auto t_w_l2 = dataAtPts->getFTensorSmallWL2(nb_integration_pts);
1814 auto t_s_dot_w = dataAtPts->getFTensorSmallWL2Dot(nb_integration_pts);
1815 auto t_s_dot_dot_w =
1816 dataAtPts->getFTensorSmallWL2DotDot(nb_integration_pts);
1817 auto t_h = dataAtPts->getFTensorSmallH(nb_integration_pts);
1818 auto t_levi_kirchhoff =
1819 dataAtPts->getFTensorLeviKirchhoff(nb_integration_pts);
1820 auto t_omega_grad_dot =
1821 dataAtPts->getFTensorRotAxisGradDot(nb_integration_pts);
1822 auto t_R = dataAtPts->getFTensorRotMat(nb_integration_pts);
1823 auto t_u = dataAtPts->getFTensorStretch(nb_integration_pts);
1824
1825 auto t_var_w = dataAtPts->getFTensorVarWL2(nb_integration_pts);
1826 auto t_var_grad_omega =
1827 dataAtPts->getFTensorVarGradRotAxis(nb_integration_pts);
1828 auto t_var_P = dataAtPts->getFTensorVarPiola(nb_integration_pts);
1829 auto t_var_div_P = dataAtPts->getFTensorDivVarPiola(nb_integration_pts);
1830 auto t_det = topoData->getFTensorDetJacobian(nb_integration_pts);
1831 auto t_inv_jac = topoData->getFTensorInvJacobian(nb_integration_pts);
1832
1833 auto w_l2_dot_dot_at_pts = dataAtPts->getSmallWL2DotDotAtPts();
1834 if (w_l2_dot_dot_at_pts->size1() != nb_integration_pts ||
1835 w_l2_dot_dot_at_pts->size2() != SPACE_DIM) {
1836 MatrixSizeHelper<GetFTensor1FromMatType<SPACE_DIM, -1, DL>, DL>::size(
1837 *w_l2_dot_dot_at_pts, nb_integration_pts);
1838 w_l2_dot_dot_at_pts->clear();
1839 }
1840
1841 const auto piola_scale = dataAtPts->piolaScale;
1842 const auto alpha_w = alphaW / piola_scale;
1843 const auto alpha_rho = alphaRho / piola_scale;
1844
1845 const int nb_base_functions = data.getN().size2();
1846 auto t_base_diff = data.getFTensor1DiffN<3>();
1847
1848 auto get_ftensor1 = [](auto &v) {
1850 &v[0], &v[1], &v[2]);
1851 };
1852
1853 auto next = [&]() {
1854 ++t_w;
1855 ++t_div_P;
1856 ++t_w_l2;
1857 ++t_s_dot_w;
1858 ++t_s_dot_dot_w;
1859 ++t_h;
1860 ++t_levi_kirchhoff;
1861 ++t_omega_grad_dot;
1862 ++t_R;
1863 ++t_u;
1864
1865 ++t_var_w;
1866 ++t_var_grad_omega;
1867 ++t_var_P;
1868 ++t_var_div_P;
1869
1870 ++t_det;
1871 ++t_inv_jac;
1872 };
1873
1879 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
1880
1881 for (int gg = 0; gg != nb_integration_pts; ++gg) {
1882
1883 // Calculate the variation of the gradient due to geometry change
1885 t_cof(i, j) = t_det * t_inv_jac(j, i);
1886
1887 double consistency_residual = 0;
1889 consistency_residual = -0.5 * t_var_P(k, m) * (t_R(k, l) * t_u(l, m)) -
1890 0.5 * t_var_P(k, l) * (t_R(k, m) * t_u(l, m)) +
1891 t_var_P(k, l) * t_kd(k, l);
1892 } else {
1894 t_residuum_P(k, m) = t_h(k, m) - t_kd(k, m);
1895 consistency_residual = t_var_P(k, m) * (-t_residuum_P(k, m));
1896 }
1897
1898 auto t_nf = get_ftensor1(nF);
1899 int bb = 0;
1900 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
1901
1903 t_div_base(i) = -(1 / t_det) * (t_inv_jac(j, i) * t_base_diff(j));
1904
1905 // OpSpatialEquilibrium
1906 t_nf(i) += (t_w * v) *
1907 (t_var_w(k) * (-t_div_P(k) + alpha_w * t_s_dot_w(k) +
1908 alpha_rho * t_s_dot_dot_w(k))) *
1909 t_cof(i, j) * t_base_diff(j);
1910 t_nf(i) += (t_w * v) * (-(t_var_w(k) * t_div_P(k))) * t_div_base(i);
1911
1912 // OpSpatialRotation
1913 auto constant_work =
1914 dataAtPts->getFTensorLeviKirchhoff(nb_integration_pts, 0, gg);
1915 auto constant_variation =
1916 GetFTensor1FromMatImpl<3, -1, DL, MatrixDouble>::get(
1917 *dataAtPts->varConstantRotation, gg, 0);
1918 auto higher_variation =
1919 GetFTensor1FromMatImpl<3, -1, DL, MatrixDouble>::get(
1920 *dataAtPts->varHigherRotation, gg, 0);
1921 const double rotation_work = constant_variation(k) * constant_work(k) +
1922 higher_variation(k) * t_levi_kirchhoff(k);
1923 t_nf(i) -= (t_w * v * rotation_work) * t_cof(i, j) * t_base_diff(j);
1924
1925 // OpSpatialConsistencyP
1926 t_nf(i) +=
1927 (t_w * v * consistency_residual) * t_cof(i, j) * t_base_diff(j);
1928
1929 // OpSpatialConsistencyDivTerm
1930 t_nf(i) += (t_w * v) * (t_var_div_P(k) * (-t_w_l2(k))) * t_cof(i, j) *
1931 t_base_diff(j);
1932 t_nf(i) += (t_w * v) * (t_var_div_P(k) * (-t_w_l2(k))) * t_div_base(i);
1933
1934 ++t_nf;
1935 ++t_base_diff;
1936 }
1937 for (; bb != nb_base_functions; ++bb)
1938 ++t_base_diff;
1939
1940 next();
1941 }
1942
1944 }
1945
1946private:
1947 const double alphaW;
1948 const double alphaRho;
1949};
1950
1953 const std::string &field_name,
1954 boost::shared_ptr<DataAtIntegrationPts> data_ptr,
1955 SmartPetscObj<Vec> assemble_vec,
1956 boost::shared_ptr<TopologicalData> topo_ptr,
1957 std::vector<boost::shared_ptr<ScalingMethod>> smv,
1958 boost::shared_ptr<double> J_ptr = nullptr)
1960 field_name, data_ptr, topo_ptr, J_ptr, assemble_vec, Tag()),
1961 scalingMethods(smv) {
1962 CHK_THROW_MESSAGE(getMeshsetData(m_field, ms_id), "Get meshset data");
1963 }
1964
1965 MoFEMErrorCode integrate(EntData &data) {
1967
1968 locJ = 0;
1969
1970 if (entsPtr) {
1971 if (entsPtr->find(this->getFEEntityHandle()) == entsPtr->end())
1973 }
1974
1975#ifndef NDEBUG
1976 if (!dataAtPts)
1977 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1978 "DataAtIntegrationPts pointer is null");
1979#endif // NDEBUG
1980
1981 const int nb_dofs = data.getIndices().size();
1982 if (!nb_dofs)
1984
1985 const int nb_integration_pts = getGaussPts().size2();
1986
1987 const auto v = getVolume();
1988 auto t_w = getFTensor0IntegrationWeight();
1989 auto t_var_w_l2 = dataAtPts->getFTensorVarWL2(nb_integration_pts);
1990 auto t_det = topoData->getFTensorDetJacobian(nb_integration_pts);
1991 auto t_inv_jac = topoData->getFTensorInvJacobian(nb_integration_pts);
1992
1993 const int nb_base_functions = data.getN().size2();
1994 auto t_base_diff = data.getFTensor1DiffN<3>();
1995
1996 auto get_ftensor1 = [](auto &v) {
1998 &v[0], &v[1], &v[2]);
1999 };
2000
2001 auto next = [&]() {
2002 ++t_w;
2003 ++t_var_w_l2;
2004 ++t_inv_jac;
2005 ++t_det;
2006 };
2007
2009
2010 auto get_scale = [&](const double t) {
2011 double s = 1;
2012 for (auto &o : scalingMethods) {
2013
2014 s *= o->getScale(t);
2015 }
2016 return s;
2017 };
2018
2019 auto scale = get_scale(getFEMethod()->ts_t);
2020
2021 for (int gg = 0; gg != nb_integration_pts; ++gg) {
2022 const double alpha = scale * t_w * v;
2023
2024 double adjount = t_var_w_l2(i) * tForce(i);
2025 locJ += (alpha * t_det) * adjount;
2026
2028 t_cof(i, j) = t_det * t_inv_jac(j, i);
2029
2030 auto t_nf = get_ftensor1(nF);
2031 int bb = 0;
2032 for (; bb != nb_dofs / SPACE_DIM; ++bb) {
2033 t_nf(i) += (alpha * adjount) * t_cof(i, J) * t_base_diff(J);
2034
2035 ++t_nf;
2036 ++t_base_diff;
2037 }
2038 for (; bb != nb_base_functions; ++bb)
2039 ++t_base_diff;
2040
2041 next();
2042 }
2043
2045 }
2046
2047protected:
2048 MoFEMErrorCode getMeshsetData(MoFEM::Interface &m_field, int ms_id) {
2050
2051 auto cubit_meshset_ptr =
2052 m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(ms_id,
2053 BLOCKSET);
2054
2055 std::vector<double> block_data;
2056 CHKERR cubit_meshset_ptr->getAttributes(block_data);
2057
2058 if (block_data.size() != SPACE_DIM) {
2059 MOFEM_LOG("SELF", Sev::warning)
2060 << "BLOCKSET is expected to have " << SPACE_DIM
2061 << " attributes but has size " << block_data.size();
2062 if (block_data.size() < SPACE_DIM) {
2063 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2064 "Size of attribute in BLOCKSET is too small");
2065 }
2066 }
2067
2068 for (unsigned int ii = 0; ii != SPACE_DIM; ++ii) {
2069 tForce(ii) = block_data[ii];
2070 }
2071
2072 MOFEM_LOG("WORLD", Sev::noisy)
2073 << "Flux blockset " << cubit_meshset_ptr->getName();
2074 MOFEM_LOG("WORLD", Sev::noisy)
2075 << "Number of attributes " << block_data.size();
2076
2077 this->entsPtr = boost::make_shared<Range>();
2078 CHKERR m_field.get_moab().get_entities_by_handle(cubit_meshset_ptr->meshset,
2079 *(entsPtr), true);
2080
2081 MOFEM_LOG("WORLD", Sev::noisy) << "tForce vector initialised: " << tForce;
2082 MOFEM_LOG("WORLD", Sev::noisy) << "Number of elements " << entsPtr->size();
2083
2085 }
2086
2088 boost::shared_ptr<Range> entsPtr;
2089 std::vector<boost::shared_ptr<ScalingMethod>> scalingMethods;
2090};
2091
2092} // namespace EshelbianPlasticity
boost::shared_ptr< DataAtIntegrationPts > dataAtPts
std::string type
boost::shared_ptr< DataAtIntegrationPts > data
SmartPetscObj< Vec > gradient
SmartPetscObj< Vec > values
PetscInt size
#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.
const char features[]
@ R
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
boost::shared_ptr< MatrixDouble > MatrixPtr
EntitiesFieldData::EntData EntData
static MatrixDouble getTopologicalAnalyticalExpr(OP_PTR op_ptr, const std::string &block_name)
static constexpr auto size_symm
MatrixDouble analytical_expr_function(double delta_t, double t, int nb_gauss_pts, MatrixDouble &m_ref_coords, MatrixDouble &m_ref_normals, const std::string block_name)
constexpr std::enable_if<(Dim0<=2 &&Dim1<=2), Tensor2_Expr< Levi_Civita< T >, T, Dim0, Dim1, i, j > >::type levi_civita(const Index< i, Dim0 > &, const Index< j, Dim1 > &)
levi_civita functions to make for easy adhoc use
constexpr IntegrationType I
constexpr AssemblyType A
double h
constexpr double t
plate stiffness
Definition plate.cpp:58
constexpr auto field_name
FTensor::Index< 'm', 3 > m
static PetscBool l2UserBaseScale
static enum RotSelector rotSelector
static enum RotSelector gradApproximator
static double physicalDt
static PetscBool physicalTimeFlg
static double currentPhysicalTime
MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override
boost::shared_ptr< AnalyticalDisplacementBcVec > bcDispPtr
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenSideDataPtr
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
OpAnalyticalDispBc_dX(const std::string &field_name, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_side_data_ptr, boost::shared_ptr< AnalyticalDisplacementBcVec > bc_disp_ptr, std::map< std::string, boost::shared_ptr< ScalingMethod > > smv, boost::shared_ptr< TopologicalData > topo_ptr, SmartPetscObj< Vec > vec, boost::shared_ptr< double > J_ptr=nullptr, Tag tag=Tag())
OpAssembleBrokenFaceTopologicalDerivativeImplBase(boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_base_side_data, boost::shared_ptr< TopologicalData > topo_ptr, boost::shared_ptr< double > J_ptr, SmartPetscObj< Vec > assemble_vec, Tag topo_tag, boost::shared_ptr< Range > ents_ptr=nullptr)
OpAssembleTopologicalObjectiveDerivativeImplBase(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< TopologicalData > topo_ptr, boost::shared_ptr< double > J_ptr, SmartPetscObj< Vec > assemble_vec, Tag topo_tag)
MoFEMErrorCode assemble(int side, EntityType type, EntData &data) override
OpBodyForce_dX(MoFEM::Interface &m_field, int ms_id, const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, SmartPetscObj< Vec > assemble_vec, boost::shared_ptr< TopologicalData > topo_ptr, std::vector< boost::shared_ptr< ScalingMethod > > smv, boost::shared_ptr< double > J_ptr=nullptr)
MoFEMErrorCode getMeshsetData(MoFEM::Interface &m_field, int ms_id)
std::vector< boost::shared_ptr< ScalingMethod > > scalingMethods
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override
OpBrokenAnalyticalTractionBc_dX(std::string field_name, boost::shared_ptr< AnalyticalTractionBcVec > bc_data, boost::shared_ptr< MatrixDouble > lambda_hybrid_ptr, boost::shared_ptr< TopologicalData > topo_ptr, std::map< std::string, boost::shared_ptr< ScalingMethod > > smv, SmartPetscObj< Vec > vec, boost::shared_ptr< double > J_ptr=nullptr, Tag tag=Tag())
MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
OpBrokenTractionBc_dX(std::string field_name, boost::shared_ptr< TractionBcVec > bc_data, boost::shared_ptr< MatrixDouble > lambda_hybrid_ptr, boost::shared_ptr< TopologicalData > topo_ptr, std::map< std::string, boost::shared_ptr< ScalingMethod > > smv, SmartPetscObj< Vec > vec, boost::shared_ptr< double > J_ptr=nullptr, Tag tag=Tag())
OpDispBc_dX(const std::string &field_name, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_side_data_ptr, boost::shared_ptr< BcDispVec > bc_disp_ptr, std::map< std::string, boost::shared_ptr< ScalingMethod > > smv, boost::shared_ptr< TopologicalData > topo_ptr, SmartPetscObj< Vec > vec, boost::shared_ptr< double > J_ptr=nullptr, Tag tag=Tag())
std::map< std::string, boost::shared_ptr< ScalingMethod > > scalingMethodsMap
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenSideDataPtr
MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override
OpSensitivityInteriorGradient(const std::string field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, boost::shared_ptr< TopologicalData > topo_ptr, SmartPetscObj< Vec > assemble_vec, const double alpha, const double rho, const double alpha_viscous_omega=0, boost::shared_ptr< double > J_ptr=nullptr)
OpSensitivityInterior_dX(const std::string &field_name, boost::shared_ptr< DataAtIntegrationPts > data_ptr, SmartPetscObj< Vec > assemble_vec, boost::shared_ptr< TopologicalData > topo_ptr, const double alpha, const double rho, const double alpha_viscous_omega=0)
MoFEMErrorCode integrate(int side, EntityType type, EntData &data) override
OpTauStabilisation_dX(const std::string &field_name, boost::shared_ptr< std::vector< BrokenBaseSideData > > broken_disp_data_ptr, boost::shared_ptr< MatrixDouble > hybrid_disp_ptr, boost::shared_ptr< MatrixDouble > var_hybrid_disp_ptr, boost::shared_ptr< TopologicalData > topo_ptr, const double alpha_tau, SmartPetscObj< Vec > vec, boost::shared_ptr< double > J_ptr=nullptr, Tag tag=Tag())
boost::shared_ptr< std::vector< BrokenBaseSideData > > brokenDispDataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
OpTopologicalObjectivePythonImpl(boost::shared_ptr< DataAtIntegrationPts > data_at_pts_ptr, boost::shared_ptr< TopologicalData > topo_p, boost::shared_ptr< ObjectiveFunctionData > python_ptr, const ObjectiveModelType eval_energy_model=PYTHON_MODEL)
@ NO_STRETCH_NONLINEAR
No-stretch nonlinear formulation.
virtual moab::Interface & get_moab()=0
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
auto getFTensor0IntegrationWeight()
Get integration weights.
const FEMethod * getFEMethod() const
Return raw pointer to Finite Element Method object.
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
VectorDouble nF
local right hand side vector
double rho
Definition plastic.cpp:145
double scale
Definition plastic.cpp:124