v0.15.0
Loading...
Searching...
No Matches
adjoint.cpp
Go to the documentation of this file.
1/**
2 * @file elastic.cpp
3 * @brief elastic example
4 * @author Anonymous author(s) committing under MIT license
5 * @example mofem/tutorials/vec-7/adjoint.cpp
6 *
7 */
8
9#include <boost/python.hpp>
10#include <boost/python/def.hpp>
11#include <boost/python/numpy.hpp>
12namespace bp = boost::python;
13namespace np = boost::python::numpy;
14
15#include <MoFEM.hpp>
16
17using namespace MoFEM;
18
19constexpr int BASE_DIM = 1; //< Dimension of the base functions
20
21//! [Define dimension]
22constexpr int SPACE_DIM =
23 EXECUTABLE_DIMENSION; //< Space dimension of problem, mesh
24
25//! [Define dimension]
26constexpr AssemblyType A = AssemblyType::PETSC;
27constexpr IntegrationType I =
28 IntegrationType::GAUSS; //< selected integration type
29
30//! [Define entities]
35using DomainEleOp = DomainEle::UserDataOperator;
36using BoundaryEleOp = BoundaryEle::UserDataOperator;
37//! [Define entities]
38
39struct DomainBCs {};
40struct BoundaryBCs {};
41
48
49template <int DIM> struct PostProcEleByDim;
50
51template <> struct PostProcEleByDim<2> {
55};
56
57template <> struct PostProcEleByDim<3> {
61};
62
66
67template <int SPACE_DIM, IntegrationType I, typename OpBase>
69
70template <int SPACE_DIM, IntegrationType I, typename OpBase>
72
73constexpr double young_modulus = 1;
74constexpr double poisson_ratio = 0.3;
75constexpr double bulk_modulus_K = young_modulus / (3 * (1 - 2 * poisson_ratio));
76constexpr double shear_modulus_G = young_modulus / (2 * (1 + poisson_ratio));
77
78PetscBool is_plane_strain = PETSC_FALSE;
79
80#include <ElasticSpring.hpp>
81#include <FluidLevel.hpp>
82#include <CalculateTraction.hpp>
83#include <NaturalDomainBC.hpp>
84#include <NaturalBoundaryBC.hpp>
85#include <HookeOps.hpp>
86
88
89 virtual MoFEMErrorCode
91 boost::shared_ptr<MatrixDouble> u_ptr,
92 boost::shared_ptr<MatrixDouble> stress_ptr,
93 boost::shared_ptr<MatrixDouble> strain_ptr,
94 boost::shared_ptr<VectorDouble> o_ptr) = 0;
95
96 virtual MoFEMErrorCode
98 boost::shared_ptr<MatrixDouble> u_ptr,
99 boost::shared_ptr<MatrixDouble> stress_ptr,
100 boost::shared_ptr<MatrixDouble> strain_ptr,
101 boost::shared_ptr<MatrixDouble> o_ptr) = 0;
102
103 virtual MoFEMErrorCode
105 boost::shared_ptr<MatrixDouble> u_ptr,
106 boost::shared_ptr<MatrixDouble> stress_ptr,
107 boost::shared_ptr<MatrixDouble> strain_ptr,
108 boost::shared_ptr<MatrixDouble> o_ptr) = 0;
109
110 virtual MoFEMErrorCode numberOfModes(int block_id, int &modes) = 0;
111
112 virtual MoFEMErrorCode blockModes(int block_id, MatrixDouble &coords,
113 std::array<double, 3> &centroid,
114 std::array<double, 6> &bbox,
115 MatrixDouble &o_ptr) = 0;
116
117 virtual ~ObjectiveFunctionData() = default;
118};
119
120boost::shared_ptr<ObjectiveFunctionData>
121create_python_objective_function(std::string py_file);
122
124 const std::string block_name, int dim);
125
126MoFEMErrorCode save_range(moab::Interface &moab, const std::string name,
127 const Range r);
128struct Example {
129
130 Example(MoFEM::Interface &m_field) : mField(m_field) {}
131
133
134private:
136
137 boost::shared_ptr<MatrixDouble> vectorFieldPtr = nullptr;
138
147 postprocessElastic(int iter, SmartPetscObj<Vec> adjoint_vector = nullptr);
148 MoFEMErrorCode calculateGradient(PetscReal *objective_function_value,
149 Vec objective_function_gradient,
150 Vec adjoint_vector);
151
153 int fieldOrder = 2;
154
157 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
158 std::vector<SmartPetscObj<Vec>> modeVecs;
159 std::vector<std::array<double, 3>> modeCentroids;
160 std::vector<std::array<double, 6>> modeBBoxes;
162};
163
164//! [Run problem]
167
168 char objective_function_file_name[255] = "objective_function.py";
170 PETSC_NULLPTR, PETSC_NULLPTR, "-objective_function",
171 objective_function_file_name, 255, PETSC_NULLPTR);
172 auto file_exists = [](std::string myfile) {
173 std::ifstream file(myfile.c_str());
174 if (file) {
175 return true;
176 }
177 return false;
178 };
179 if (!file_exists(objective_function_file_name)) {
180 MOFEM_LOG("WORLD", Sev::error) << "Objective function file NOT found: "
181 << objective_function_file_name;
182 CHK_THROW_MESSAGE(MOFEM_NOT_FOUND, "file NOT found");
183 }
184
185 pythonPtr = create_python_objective_function(objective_function_file_name);
186
192
193 auto pip = mField.getInterface<PipelineManager>();
194 kspElastic = pip->createKSP();
195 CHKERR KSPSetFromOptions(kspElastic);
196
199
200 auto create_vec_modes = [&](auto block_name) {
202 auto mesh_mng = mField.getInterface<MeshsetsManager>();
203 auto bcs = mesh_mng->getCubitMeshsetPtr(
204
205 std::regex((boost::format("%s(.*)") % block_name).str())
206
207 );
208
209 int nb_total_modes = 0;
210 for (auto &bc : bcs) {
211 auto id = bc->getMeshsetId();
212 int nb_modes;
213 CHKERR pythonPtr->numberOfModes(id, nb_modes);
214 nb_total_modes += nb_modes;
215 }
216
217 MOFEM_LOG("WORLD", Sev::inform)
218 << "Total number of modes to apply: " << nb_total_modes;
219
220 modeVecs.resize(nb_total_modes);
221
223 };
224
225 auto get_modes_bounding_boxes = [&](auto block_name) {
227 auto mesh_mng = mField.getInterface<MeshsetsManager>();
228 auto bcs = mesh_mng->getCubitMeshsetPtr(
229
230 std::regex((boost::format("%s(.*)") % block_name).str())
231
232 );
233
234 for (auto &bc : bcs) {
235 auto meshset = bc->getMeshset();
236 Range ents;
237 CHKERR mField.get_moab().get_entities_by_handle(meshset, ents, true);
238 Range verts;
239 CHKERR mField.get_moab().get_connectivity(ents, verts, false);
240 std::vector<double> x(verts.size());
241 std::vector<double> y(verts.size());
242 std::vector<double> z(verts.size());
243 CHKERR mField.get_moab().get_coords(verts, x.data(), y.data(), z.data());
244 std::array<double, 3> centroid = {0, 0, 0};
245 for (int i = 0; i != verts.size(); ++i) {
246 centroid[0] += x[i];
247 centroid[1] += y[i];
248 centroid[2] += z[i];
249 }
250 MPI_Allreduce(MPI_IN_PLACE, centroid.data(), 3, MPI_DOUBLE, MPI_SUM,
251 mField.get_comm());
252 int nb_vertex = verts.size();
253 MPI_Allreduce(MPI_IN_PLACE, &nb_vertex, 1, MPI_INT, MPI_SUM,
254 mField.get_comm());
255 if (nb_vertex) {
256 centroid[0] /= nb_vertex;
257 centroid[1] /= nb_vertex;
258 centroid[2] /= nb_vertex;
259 }
260 std::array<double, 6> bbox = {centroid[0], centroid[1], centroid[2],
261 centroid[0], centroid[1], centroid[2]};
262 for (int i = 0; i != verts.size(); ++i) {
263 bbox[0] = std::min(bbox[0], x[i]);
264 bbox[1] = std::min(bbox[1], y[i]);
265 bbox[2] = std::min(bbox[2], z[i]);
266 bbox[3] = std::max(bbox[3], x[i]);
267 bbox[4] = std::max(bbox[4], y[i]);
268 bbox[5] = std::max(bbox[5], z[i]);
269 }
270 MPI_Allreduce(MPI_IN_PLACE, &bbox[0], 3, MPI_DOUBLE, MPI_MIN,
271 mField.get_comm());
272 MPI_Allreduce(MPI_IN_PLACE, &bbox[3], 3, MPI_DOUBLE, MPI_MAX,
273 mField.get_comm());
274
275 MOFEM_LOG("WORLD", Sev::inform)
276 << "Block: " << bc->getName() << " centroid: " << centroid[0] << " "
277 << centroid[1] << " " << centroid[2];
278 MOFEM_LOG("WORLD", Sev::inform)
279 << "Block: " << bc->getName() << " bbox: " << bbox[0] << " "
280 << bbox[1] << " " << bbox[2] << " " << bbox[3] << " " << bbox[4]
281 << " " << bbox[5];
282
283 modeCentroids.push_back(centroid);
284 modeBBoxes.push_back(bbox);
285 }
286
288 };
289
290 auto eval_objective_and_gradient = [](Tao tao, Vec x, PetscReal *f, Vec g,
291 void *ctx) -> PetscErrorCode {
293 auto *ex_ptr = (Example *)ctx;
294
295 int iter;
296 CHKERR TaoGetIterationNumber(tao, &iter);
297
298 auto set_geometry = [&](Vec x) {
300
301 VecScatter ctx;
302 Vec x_local;
303 CHKERR VecScatterCreateToAll(x, &ctx, &x_local);
304 // scatter as many times as you need
305 CHKERR VecScatterBegin(ctx, x, x_local, INSERT_VALUES, SCATTER_FORWARD);
306 CHKERR VecScatterEnd(ctx, x, x_local, INSERT_VALUES, SCATTER_FORWARD);
307 // destroy scatter context and local vector when no longer needed
308 CHKERR VecScatterDestroy(&ctx);
309
310 auto current_geometry = vectorDuplicate(ex_ptr->initialGeometry);
311 CHKERR VecCopy(ex_ptr->initialGeometry, current_geometry);
312 const double *a;
313 CHKERR VecGetArrayRead(x_local, &a);
314 const double *coeff = a;
315 for (auto &mode_vec : ex_ptr->modeVecs) {
316 MOFEM_LOG("WORLD", Sev::verbose)
317 << "Adding mode with coeff: " << *coeff;
318 CHKERR VecAXPY(current_geometry, (*coeff), mode_vec);
319 ++coeff;
320 }
321 CHKERR VecRestoreArrayRead(x_local, &a);
322 CHKERR VecGhostUpdateBegin(current_geometry, INSERT_VALUES,
323 SCATTER_FORWARD);
324 CHKERR VecGhostUpdateEnd(current_geometry, INSERT_VALUES,
325 SCATTER_FORWARD);
326 CHKERR ex_ptr->mField.getInterface<VecManager>()
327 ->setOtherLocalGhostVector("ADJOINT", "ADJOINT_FIELD", "GEOMETRY",
328 RowColData::ROW, current_geometry,
329 INSERT_VALUES, SCATTER_REVERSE);
330
331 CHKERR VecDestroy(&x_local);
333 };
334
335 CHKERR set_geometry(x);
336 CHKERR KSPReset(ex_ptr->kspElastic);
337 CHKERR ex_ptr->solveElastic();
338 auto simple = ex_ptr->mField.getInterface<Simple>();
339 auto adjoint_vector = createDMVector(simple->getDM());
340 CHKERR ex_ptr->calculateGradient(f, g, adjoint_vector);
341 CHKERR ex_ptr->postprocessElastic(iter, adjoint_vector);
342
344 };
345
346 CHKERR create_vec_modes("OPTIMISE");
347 CHKERR get_modes_bounding_boxes("OPTIMISE");
348 auto tao = createTao(mField.get_comm());
349 CHKERR TaoSetType(tao, TAOLMVM);
350
351 auto rank = mField.get_comm_rank();
352 auto g = createVectorMPI(mField.get_comm(), (!rank) ? modeVecs.size() : 0,
353 PETSC_DECIDE);
354 CHKERR TaoSetObjectiveAndGradient(tao, g, eval_objective_and_gradient,
355 (void *)this);
356
358 CHKERR mField.getInterface<VecManager>()->setOtherLocalGhostVector(
359 "ADJOINT", "ADJOINT_FIELD", "GEOMETRY", RowColData::ROW, initialGeometry,
360 INSERT_VALUES, SCATTER_FORWARD);
361
363 auto x0 = vectorDuplicate(g);
364
365 CHKERR VecSet(x0, 0.0);
366 CHKERR TaoSetSolution(tao, x0);
367 CHKERR TaoSetFromOptions(tao);
368 CHKERR TaoSolve(tao);
369
371}
372//! [Run problem]
373
374//! [Read mesh]
379 CHKERR simple->loadFile();
380 // Add meshsets if config file provided
381 CHKERR mField.getInterface<MeshsetsManager>()->setMeshsetFromFile();
383}
384//! [Read mesh]
385
386//! [Set up problem]
390
391 enum bases { AINSWORTH, DEMKOWICZ, LASBASETOPT };
392 const char *list_bases[LASBASETOPT] = {"ainsworth", "demkowicz"};
393 PetscInt choice_base_value = AINSWORTH;
394 CHKERR PetscOptionsGetEList(PETSC_NULLPTR, NULL, "-base", list_bases,
395 LASBASETOPT, &choice_base_value, PETSC_NULLPTR);
396
397 switch (choice_base_value) {
398 case AINSWORTH:
400 MOFEM_LOG("WORLD", Sev::inform)
401 << "Set AINSWORTH_LEGENDRE_BASE for displacements";
402 break;
403 case DEMKOWICZ:
405 MOFEM_LOG("WORLD", Sev::inform)
406 << "Set DEMKOWICZ_JACOBI_BASE for displacements";
407 break;
408 default:
409 base = LASTBASE;
410 break;
411 }
412
413 // Add field
414 CHKERR simple->addDomainField("U", H1, base, SPACE_DIM);
415 CHKERR simple->addBoundaryField("U", H1, base, SPACE_DIM);
416 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, "", "-order", &fieldOrder,
417 PETSC_NULLPTR);
418
419 CHKERR simple->addDataField("GEOMETRY", H1, base, SPACE_DIM);
420
421 CHKERR simple->setFieldOrder("U", fieldOrder);
422 CHKERR simple->setFieldOrder("GEOMETRY", fieldOrder);
423 CHKERR simple->setUp();
424
425 auto project_ho_geometry = [&]() {
426 Projection10NodeCoordsOnField ent_method(mField, "GEOMETRY");
427 return mField.loop_dofs("GEOMETRY", ent_method);
428 };
429 CHKERR project_ho_geometry();
430
431 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-plane_strain",
432 &is_plane_strain, PETSC_NULLPTR);
433
435}
436//! [Set up problem]
437
438//! [Setup adjoint]
442
443 // ad adjoint dm
444
445 auto create_adjoint_dm = [&]() {
446 auto adjoint_dm = createDM(mField.get_comm(), "DMMOFEM");
447
448 auto add_field = [&]() {
450 CHKERR mField.add_field("ADJOINT_FIELD", H1, base, SPACE_DIM);
452 "ADJOINT_FIELD");
453 for (auto tt = MBEDGE; tt <= moab::CN::TypeDimensionMap[SPACE_DIM].second;
454 ++tt)
455 CHKERR mField.set_field_order(simple->getMeshset(), tt, "ADJOINT_FIELD",
456 fieldOrder);
457 CHKERR mField.set_field_order(simple->getMeshset(), MBVERTEX,
458 "ADJOINT_FIELD", 1);
461 };
462
463 auto add_adjoint_fe_impl = [&]() {
465 CHKERR mField.add_finite_element("ADJOINT_DOMAIN_FE");
467 "ADJOINT_FIELD");
469 "ADJOINT_FIELD");
471 "ADJOINT_FIELD");
473 "GEOMETRY");
475 simple->getMeshset(), SPACE_DIM, "ADJOINT_DOMAIN_FE");
476 CHKERR mField.build_finite_elements("ADJOINT_DOMAIN_FE");
477
478 CHKERR mField.add_finite_element("ADJOINT_BOUNDARY_FE");
480 "ADJOINT_FIELD");
482 "ADJOINT_FIELD");
484 "ADJOINT_FIELD");
486 "GEOMETRY");
487
488 auto block_name = "OPTIMISE";
489 auto mesh_mng = mField.getInterface<MeshsetsManager>();
490 auto bcs = mesh_mng->getCubitMeshsetPtr(
491
492 std::regex((boost::format("%s(.*)") % block_name).str())
493
494 );
495
496 for (auto bc : bcs) {
498 bc->getMeshset(), SPACE_DIM - 1, "ADJOINT_BOUNDARY_FE");
499 }
500
501 CHKERR mField.build_finite_elements("ADJOINT_BOUNDARY_FE");
502
503 CHKERR mField.build_adjacencies(simple->getBitRefLevel(),
504 simple->getBitRefLevelMask());
505
507 };
508
509 auto set_adjoint_dm_imp = [&]() {
511 CHKERR DMMoFEMCreateMoFEM(adjoint_dm, &mField, "ADJOINT",
512 simple->getBitRefLevel(),
513 simple->getBitRefLevelMask());
514 CHKERR DMMoFEMSetDestroyProblem(adjoint_dm, PETSC_TRUE);
515 CHKERR DMSetFromOptions(adjoint_dm);
516 CHKERR DMMoFEMAddElement(adjoint_dm, "ADJOINT_DOMAIN_FE");
517 CHKERR DMMoFEMAddElement(adjoint_dm, "ADJOINT_BOUNDARY_FE");
518 CHKERR DMMoFEMSetSquareProblem(adjoint_dm, PETSC_TRUE);
519 CHKERR DMMoFEMSetIsPartitioned(adjoint_dm, PETSC_TRUE);
520 mField.getInterface<ProblemsManager>()->buildProblemFromFields =
521 PETSC_TRUE;
522 CHKERR DMSetUp(adjoint_dm);
523 mField.getInterface<ProblemsManager>()->buildProblemFromFields =
524 PETSC_FALSE;
526 };
527
528 CHK_THROW_MESSAGE(add_field(), "add adjoint field");
529 CHK_THROW_MESSAGE(add_adjoint_fe_impl(), "add adjoint fe");
530 CHK_THROW_MESSAGE(set_adjoint_dm_imp(), "set adjoint dm");
531
532 return adjoint_dm;
533 };
534
535 adjointDM = create_adjoint_dm();
536
538}
539//
540
541//! [Boundary condition]
545 auto bc_mng = mField.getInterface<BcManager>();
546
547 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_X",
548 "U", 0, 0);
549 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Y",
550 "U", 1, 1);
551 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(), "REMOVE_Z",
552 "U", 2, 2);
553 CHKERR bc_mng->removeBlockDOFsOnEntities(simple->getProblemName(),
554 "REMOVE_ALL", "U", 0, 3);
555 CHKERR bc_mng->pushMarkDOFsOnEntities<DisplacementCubitBcData>(
556 simple->getProblemName(), "U");
557
559}
560//! [Boundary condition]
561
562//! [Adjoint modes]
565
566 auto opt_ents = get_range_from_block(mField, "OPTIMISE", SPACE_DIM - 1);
567 auto subset_dm_bdy = createDM(mField.get_comm(), "DMMOFEM");
568 CHKERR DMMoFEMSetSquareProblem(subset_dm_bdy, PETSC_TRUE);
569 CHKERR DMMoFEMCreateSubDM(subset_dm_bdy, adjointDM, "SUBSET_BDY");
570 CHKERR DMMoFEMAddElement(subset_dm_bdy, "ADJOINT_BOUNDARY_FE");
571 CHKERR DMMoFEMAddSubFieldRow(subset_dm_bdy, "ADJOINT_FIELD",
572 boost::make_shared<Range>(opt_ents));
573 CHKERR DMMoFEMAddSubFieldCol(subset_dm_bdy, "ADJOINT_FIELD",
574 boost::make_shared<Range>(opt_ents));
575 CHKERR DMSetUp(subset_dm_bdy);
576
577 auto subset_dm_domain = createDM(mField.get_comm(), "DMMOFEM");
578 CHKERR DMMoFEMSetSquareProblem(subset_dm_domain, PETSC_TRUE);
579 CHKERR DMMoFEMCreateSubDM(subset_dm_domain, adjointDM, "SUBSET_DOMAIN");
580 CHKERR DMMoFEMAddElement(subset_dm_domain, "ADJOINT_DOMAIN_FE");
581 CHKERR DMMoFEMAddSubFieldRow(subset_dm_domain, "ADJOINT_FIELD");
582 CHKERR DMMoFEMAddSubFieldCol(subset_dm_domain, "ADJOINT_FIELD");
583 CHKERR DMSetUp(subset_dm_domain);
584
585 // remove dofs on boundary of the domain
586 auto remove_dofs = [&]() {
588
589 std::array<Range, 3> remove_dim_ents;
590 remove_dim_ents[0] =
591 get_range_from_block(mField, "OPT_REMOVE_X", SPACE_DIM - 1);
592 remove_dim_ents[1] =
593 get_range_from_block(mField, "OPT_REMOVE_Y", SPACE_DIM - 1);
594 remove_dim_ents[2] =
595 get_range_from_block(mField, "OPT_REMOVE_Z", SPACE_DIM - 1);
596
597 for (int d = 0; d != 3; ++d) {
598 MOFEM_LOG("WORLD", Sev::inform)
599 << "Removing topology modes on block OPT_REMOVE_" << (char)('X' + d)
600 << " with " << remove_dim_ents[d].size() << " entities";
601 }
602
603 Range body_ents;
604 CHKERR mField.get_moab().get_entities_by_dimension(0, SPACE_DIM, body_ents,
605 true);
606 auto skin = moab::Skinner(&mField.get_moab());
607 Range boundary_ents;
608 CHKERR skin.find_skin(0, body_ents, false, boundary_ents);
609 for (int d = 0; d != 3; ++d) {
610 boundary_ents = subtract(boundary_ents, remove_dim_ents[d]);
611 }
612 ParallelComm *pcomm =
613 ParallelComm::get_pcomm(&mField.get_moab(), MYPCOMM_INDEX);
614 CHKERR pcomm->filter_pstatus(boundary_ents,
615 PSTATUS_SHARED | PSTATUS_MULTISHARED,
616 PSTATUS_NOT, -1, nullptr);
617 for (auto d = SPACE_DIM - 2; d >= 0; --d) {
618 if (d >= 0) {
619 Range ents;
620 CHKERR mField.get_moab().get_adjacencies(boundary_ents, d, false, ents,
621 moab::Interface::UNION);
622 boundary_ents.merge(ents);
623 } else {
624 Range verts;
625 CHKERR mField.get_moab().get_connectivity(boundary_ents, verts);
626 boundary_ents.merge(verts);
627 }
628 CHKERR mField.getInterface<CommInterface>()->synchroniseEntities(
629 boundary_ents);
630 }
631 boundary_ents.merge(opt_ents);
632 CHKERR mField.getInterface<ProblemsManager>()->removeDofsOnEntities(
633 "SUBSET_DOMAIN", "ADJOINT_FIELD", boundary_ents);
634 for (int d = 0; d != 3; ++d) {
635 CHKERR mField.getInterface<ProblemsManager>()->removeDofsOnEntities(
636 "SUBSET_DOMAIN", "ADJOINT_FIELD", remove_dim_ents[d], d, d);
637 }
638
639 // #ifndef NDEBUG
640 if (mField.get_comm_rank() == 0) {
641 CHKERR save_range(mField.get_moab(), "topoMode_boundary_ents.vtk",
642 boundary_ents);
643 }
644 // #endif
645
647 };
648
649 CHKERR remove_dofs();
650
651 auto get_lhs_fe = [&]() {
652 auto fe_lhs = boost::make_shared<BoundaryEle>(mField);
653 fe_lhs->getRuleHook = [](int, int, int p_data) {
654 return 2 * p_data + p_data - 1;
655 };
656 auto &pip = fe_lhs->getOpPtrVector();
658 "GEOMETRY");
661 pip.push_back(new OpMass("ADJOINT_FIELD", "ADJOINT_FIELD",
662 [](double, double, double) { return 1.; }));
663 return fe_lhs;
664 };
665
666 auto get_rhs_fe = [&]() {
667 auto fe_rhs = boost::make_shared<BoundaryEle>(mField);
668 fe_rhs->getRuleHook = [](int, int, int p_data) {
669 return 2 * p_data + p_data - 1;
670 };
671 auto &pip = fe_rhs->getOpPtrVector();
673 "GEOMETRY");
674
675 return fe_rhs;
676 };
677
678 auto block_name = "OPTIMISE";
679 auto mesh_mng = mField.getInterface<MeshsetsManager>();
680 auto bcs = mesh_mng->getCubitMeshsetPtr(
681
682 std::regex((boost::format("%s(.*)") % block_name).str())
683
684 );
685
686 for (auto &v : modeVecs) {
687 v = createDMVector(subset_dm_bdy);
688 }
689
691 struct OpMode : public OP {
692 OpMode(const std::string name,
693 boost::shared_ptr<ObjectiveFunctionData> python_ptr, int id,
694 std::vector<SmartPetscObj<Vec>> mode_vecs,
695 std::vector<std::array<double, 3>> mode_centroids,
696 std::vector<std::array<double, 6>> mode_bboxes, int block_counter,
697 int mode_counter, boost::shared_ptr<Range> range = nullptr)
698 : OP(name, name, OP::OPROW, range), pythonPtr(python_ptr), iD(id),
699 modeVecs(mode_vecs), modeCentroids(mode_centroids),
700 modeBboxes(mode_bboxes), blockCounter(block_counter),
701 modeCounter(mode_counter) {}
702
703 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
705
706 if (OP::entsPtr) {
707 if (OP::entsPtr->find(this->getFEEntityHandle()) == OP::entsPtr->end())
709 }
710
711 auto nb_rows = data.getIndices().size();
712 if (!nb_rows) {
714 }
715 auto nb_base_functions = data.getN().size2();
716
718 CHKERR pythonPtr->blockModes(iD, OP::getCoordsAtGaussPts(),
719 modeCentroids[blockCounter],
720 modeBboxes[blockCounter], blockModes);
721
722 auto nb_integration_pts = getGaussPts().size2();
723 if (blockModes.size2() != 3 * nb_integration_pts) {
724 MOFEM_LOG("WORLD", Sev::error)
725 << "Number of modes does not match number of integration points: "
726 << blockModes.size2() << "!=" << 3 * nb_integration_pts;
727 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "modes/integration points");
728 }
729
730 VectorDouble nf(nb_rows);
731
732 int nb_modes = blockModes.size1();
733 for (auto mode = 0; mode != nb_modes; ++mode) {
734 nf.clear();
735 // get mode
736 auto t_mode = getFTensor1FromPtr<3>(&blockModes(mode, 0));
737 // get element volume
738 const double vol = OP::getMeasure();
739 // get integration weights
740 auto t_w = OP::getFTensor0IntegrationWeight();
741 // get base function gradient on rows
742 auto t_base = data.getFTensor0N();
743 // loop over integration points
744 for (int gg = 0; gg != nb_integration_pts; gg++) {
745
746 // take into account Jacobian
747 const double alpha = t_w * vol;
748 // loop over rows base functions
749 auto t_nf = getFTensor1FromPtr<SPACE_DIM>(nf.data().data());
750 int rr = 0;
751 for (; rr != nb_rows / SPACE_DIM; ++rr) {
752 t_nf(i) += alpha * t_base * t_mode(i);
753 ++t_base;
754 ++t_nf;
755 }
756 for (; rr < nb_base_functions; ++rr)
757 ++t_base;
758 ++t_w; // move to another integration weight
759 ++t_mode; // move to another mode
760 }
761 Vec vec = modeVecs[modeCounter + mode];
762 auto size = data.getIndices().size();
763 auto *indices = data.getIndices().data().data();
764 auto *nf_data = nf.data().data();
765 CHKERR VecSetValues(vec, size, indices, nf_data, ADD_VALUES);
766 }
767
769 }
770
771 private:
772 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
773 MatrixDouble blockModes;
774 std::vector<std::array<double, 3>> modeCentroids;
775 std::vector<std::array<double, 6>> modeBboxes;
776 int iD;
777 std::vector<SmartPetscObj<Vec>> modeVecs;
778 int blockCounter;
779 int modeCounter;
780 };
781
782 auto solve_bdy = [&]() {
784
785 auto fe_lhs = get_lhs_fe();
786 auto fe_rhs = get_rhs_fe();
787 int block_counter = 0;
788 int mode_counter = 0;
789 for (auto &bc : bcs) {
790 auto id = bc->getMeshsetId();
791 Range ents;
792 CHKERR mField.get_moab().get_entities_by_handle(bc->getMeshset(), ents,
793 true);
794 auto range = boost::make_shared<Range>(ents);
795 auto &pip_rhs = fe_rhs->getOpPtrVector();
796 pip_rhs.push_back(new OpMode("ADJOINT_FIELD", pythonPtr, id, modeVecs,
797 modeCentroids, modeBBoxes, block_counter,
798 mode_counter, range));
799 CHKERR DMoFEMLoopFiniteElements(subset_dm_bdy, "ADJOINT_BOUNDARY_FE",
800 fe_rhs);
801 pip_rhs.pop_back();
802 int nb_modes;
803 CHKERR pythonPtr->numberOfModes(id, nb_modes);
804 ++block_counter;
805 mode_counter += nb_modes;
806 MOFEM_LOG("WORLD", Sev::inform)
807 << "Setting mode block block: " << bc->getName()
808 << " with ID: " << bc->getMeshsetId()
809 << " total modes: " << mode_counter;
810 }
811
812 for (auto &v : modeVecs) {
813 CHKERR VecAssemblyBegin(v);
814 CHKERR VecAssemblyEnd(v);
815 CHKERR VecGhostUpdateBegin(v, ADD_VALUES, SCATTER_REVERSE);
816 CHKERR VecGhostUpdateEnd(v, ADD_VALUES, SCATTER_REVERSE);
817 }
818
819 auto M = createDMMatrix(subset_dm_bdy);
820 fe_lhs->B = M;
821 CHKERR DMoFEMLoopFiniteElements(subset_dm_bdy, "ADJOINT_BOUNDARY_FE",
822 fe_lhs);
823 CHKERR MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY);
824 CHKERR MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY);
825
826 auto solver = createKSP(mField.get_comm());
827 CHKERR KSPSetOperators(solver, M, M);
828 CHKERR KSPSetFromOptions(solver);
829 CHKERR KSPSetUp(solver);
830 auto v = createDMVector(subset_dm_bdy);
831 for (auto &f : modeVecs) {
832 CHKERR KSPSolve(solver, f, v);
833 CHKERR VecSwap(f, v);
834 }
835
836 for (auto &v : modeVecs) {
837 CHKERR VecGhostUpdateBegin(v, INSERT_VALUES, SCATTER_FORWARD);
838 CHKERR VecGhostUpdateEnd(v, INSERT_VALUES, SCATTER_FORWARD);
839 }
840
842 };
843
844 CHKERR solve_bdy();
845
846 auto get_elastic_fe_lhs = [&]() {
847 auto fe = boost::make_shared<DomainEle>(mField);
848 fe->getRuleHook = [](int, int, int p_data) {
849 return 2 * p_data + p_data - 1;
850 };
851 auto &pip = fe->getOpPtrVector();
853 "GEOMETRY");
855 mField, pip, "ADJOINT_FIELD", "MAT_ADJOINT", Sev::noisy);
856 return fe;
857 };
858
859 auto get_elastic_fe_rhs = [&]() {
860 auto fe = boost::make_shared<DomainEle>(mField);
861 fe->getRuleHook = [](int, int, int p_data) {
862 return 2 * p_data + p_data - 1;
863 };
864 auto &pip = fe->getOpPtrVector();
866 "GEOMETRY");
868 mField, pip, "ADJOINT_FIELD", "MAT_ADJOINT", Sev::noisy);
869 return fe;
870 };
871
872 auto adjoint_gradient_postprocess = [&](auto mode) {
874 auto post_proc_mesh = boost::make_shared<moab::Core>();
875 auto post_proc_begin =
876 boost::make_shared<PostProcBrokenMeshInMoabBaseBegin>(mField,
877 post_proc_mesh);
878 auto post_proc_end = boost::make_shared<PostProcBrokenMeshInMoabBaseEnd>(
879 mField, post_proc_mesh);
880
881 auto geom_vec = boost::make_shared<MatrixDouble>();
882
883 auto post_proc_fe =
884 boost::make_shared<PostProcEleDomain>(mField, post_proc_mesh);
886 post_proc_fe->getOpPtrVector(), {H1}, "GEOMETRY");
887 post_proc_fe->getOpPtrVector().push_back(
888 new OpCalculateVectorFieldValues<SPACE_DIM>("ADJOINT_FIELD", geom_vec,
889 modeVecs[mode]));
890
892
893 post_proc_fe->getOpPtrVector().push_back(
894
895 new OpPPMap(
896
897 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
898
899 {},
900
901 {{"MODE", geom_vec}},
902
903 {},
904
905 {}
906
907 )
908
909 );
910
912 post_proc_begin->getFEMethod());
913 CHKERR DMoFEMLoopFiniteElements(adjointDM, "ADJOINT_DOMAIN_FE",
914 post_proc_fe);
916 post_proc_begin->getFEMethod());
917
918 CHKERR post_proc_end->writeFile("mode_" + std::to_string(mode) + ".h5m");
919
921 };
922
923 auto solve_domain = [&]() {
925 auto fe_lhs = get_elastic_fe_lhs();
926 auto fe_rhs = get_elastic_fe_rhs();
927 auto v = createDMVector(subset_dm_domain);
928 auto F = vectorDuplicate(v);
929 fe_rhs->f = F;
930
931 auto M = createDMMatrix(subset_dm_domain);
932 fe_lhs->B = M;
933 CHKERR DMoFEMLoopFiniteElements(subset_dm_domain, "ADJOINT_DOMAIN_FE",
934 fe_lhs);
935 CHKERR MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY);
936 CHKERR MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY);
937
938 auto solver = createKSP(mField.get_comm());
939 CHKERR KSPSetOperators(solver, M, M);
940 CHKERR KSPSetFromOptions(solver);
941 CHKERR KSPSetUp(solver);
942
943 int mode_counter = 0;
944 for (auto &f : modeVecs) {
945 CHKERR mField.getInterface<FieldBlas>()->setField(0, "ADJOINT_FIELD");
946 CHKERR DMoFEMMeshToLocalVector(subset_dm_bdy, f, INSERT_VALUES,
947 SCATTER_REVERSE);
948 CHKERR VecZeroEntries(F);
949 CHKERR DMoFEMLoopFiniteElements(subset_dm_domain, "ADJOINT_DOMAIN_FE",
950 fe_rhs);
951 CHKERR VecAssemblyBegin(F);
952 CHKERR VecAssemblyEnd(F);
953 CHKERR VecGhostUpdateBegin(F, ADD_VALUES, SCATTER_REVERSE);
954 CHKERR VecGhostUpdateEnd(F, ADD_VALUES, SCATTER_REVERSE);
955 CHKERR KSPSolve(solver, F, v);
956 CHKERR VecGhostUpdateBegin(v, INSERT_VALUES, SCATTER_FORWARD);
957 CHKERR VecGhostUpdateEnd(v, INSERT_VALUES, SCATTER_FORWARD);
958 CHKERR DMoFEMMeshToLocalVector(subset_dm_domain, v, INSERT_VALUES,
959 SCATTER_REVERSE);
960 auto m = createDMVector(adjointDM);
961 CHKERR DMoFEMMeshToLocalVector(adjointDM, m, INSERT_VALUES,
962 SCATTER_FORWARD);
963 f = m;
964 ++mode_counter;
965 }
967 };
968
969 CHKERR solve_domain();
970
971 for (int i = 0; i < modeVecs.size(); ++i) {
972 CHKERR adjoint_gradient_postprocess(i);
973 }
974
976}
977//! [Adjoint modes]
978
979//! [Push operators to pipeline]
982 auto pip = mField.getInterface<PipelineManager>();
983
984 //! [Integration rule]
985 auto integration_rule = [](int, int, int approx_order) {
986 return 2 * approx_order + 1;
987 };
988
989 auto integration_rule_bc = [](int, int, int approx_order) {
990 return 2 * approx_order + 1;
991 };
992
994 CHKERR pip->setDomainLhsIntegrationRule(integration_rule);
995 CHKERR pip->setBoundaryRhsIntegrationRule(integration_rule_bc);
996 CHKERR pip->setBoundaryLhsIntegrationRule(integration_rule_bc);
997 //! [Integration rule]
998
1000 pip->getOpDomainLhsPipeline(), {H1}, "GEOMETRY");
1002 pip->getOpDomainRhsPipeline(), {H1}, "GEOMETRY");
1004 pip->getOpBoundaryRhsPipeline(), {NOSPACE}, "GEOMETRY");
1006 pip->getOpBoundaryLhsPipeline(), {NOSPACE}, "GEOMETRY");
1007
1008 //! [Push domain stiffness matrix to pipeline]
1009 // Add LHS operator for elasticity (stiffness matrix)
1011 mField, pip->getOpDomainLhsPipeline(), "U", "MAT_ELASTIC", Sev::noisy);
1012 //! [Push domain stiffness matrix to pipeline]
1013
1014 // Add RHS operator for internal forces
1016 mField, pip->getOpDomainRhsPipeline(), "U", "MAT_ELASTIC", Sev::noisy);
1017
1018 //! [Push Body forces]
1020 pip->getOpDomainRhsPipeline(), mField, "U", Sev::inform);
1021 //! [Push Body forces]
1022
1023 //! [Push natural boundary conditions]
1024 // Add force boundary condition
1026 pip->getOpBoundaryRhsPipeline(), mField, "U", -1, Sev::inform);
1027 // Add case for mix type of BCs
1029 pip->getOpBoundaryLhsPipeline(), mField, "U", Sev::noisy);
1030 //! [Push natural boundary conditions]
1032}
1033//! [Push operators to pipeline]
1034
1035//! [Solve]
1038 auto simple = mField.getInterface<Simple>();
1039 auto dm = simple->getDM();
1040 auto f = createDMVector(dm);
1041 auto d = vectorDuplicate(f);
1042 CHKERR VecZeroEntries(d);
1043 CHKERR DMoFEMMeshToLocalVector(dm, d, INSERT_VALUES, SCATTER_REVERSE);
1044
1045 auto set_essential_bc = [&]() {
1047 // This is low level pushing finite elements (pipelines) to solver
1048
1049 auto ksp_ctx_ptr = getDMKspCtx(dm);
1050 auto pre_proc_rhs = boost::make_shared<FEMethod>();
1051 auto post_proc_rhs = boost::make_shared<FEMethod>();
1052 auto post_proc_lhs = boost::make_shared<FEMethod>();
1053
1054 auto get_pre_proc_hook = [&]() {
1056 {});
1057 };
1058 pre_proc_rhs->preProcessHook = get_pre_proc_hook();
1059
1060 auto get_post_proc_hook_rhs = [this, post_proc_rhs]() {
1062
1064 post_proc_rhs, 1.)();
1066 };
1067
1068 auto get_post_proc_hook_lhs = [this, post_proc_lhs]() {
1070
1072 post_proc_lhs, 1.)();
1074 };
1075
1076 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1077 post_proc_lhs->postProcessHook = get_post_proc_hook_lhs;
1078
1079 ksp_ctx_ptr->getPreProcComputeRhs().push_front(pre_proc_rhs);
1080 ksp_ctx_ptr->getPostProcComputeRhs().push_back(post_proc_rhs);
1081 ksp_ctx_ptr->getPostProcSetOperators().push_back(post_proc_lhs);
1083 };
1084
1085 auto setup_and_solve = [&](auto solver) {
1087 BOOST_LOG_SCOPED_THREAD_ATTR("Timeline", attrs::timer());
1088 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSetUp";
1089 CHKERR KSPSetUp(solver);
1090 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSetUp <= Done";
1091 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSolve";
1092 CHKERR KSPSolve(solver, f, d);
1093 MOFEM_LOG("TIMER", Sev::noisy) << "KSPSolve <= Done";
1095 };
1096
1097 MOFEM_LOG_CHANNEL("TIMER");
1098 MOFEM_LOG_TAG("TIMER", "timer");
1099
1100 CHKERR set_essential_bc();
1101 CHKERR setup_and_solve(kspElastic);
1102
1103 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
1104 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
1105 CHKERR DMoFEMMeshToLocalVector(dm, d, INSERT_VALUES, SCATTER_REVERSE);
1106
1107 auto evaluate_field_at_the_point = [&]() {
1109
1110 int coords_dim = 3;
1111 std::array<double, 3> field_eval_coords{0.0, 0.0, 0.0};
1112 PetscBool do_eval_field = PETSC_FALSE;
1113 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
1114 field_eval_coords.data(), &coords_dim,
1115 &do_eval_field);
1116
1117 if (do_eval_field) {
1118
1119 vectorFieldPtr = boost::make_shared<MatrixDouble>();
1120 auto field_eval_data =
1121 mField.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
1122
1124 ->buildTree<SPACE_DIM>(field_eval_data, simple->getDomainFEName());
1125
1126 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
1127 auto no_rule = [](int, int, int) { return -1; };
1128 auto field_eval_fe_ptr = field_eval_data->feMethodPtr.lock();
1129 field_eval_fe_ptr->getRuleHook = no_rule;
1130
1131 field_eval_fe_ptr->getOpPtrVector().push_back(
1133
1135 ->evalFEAtThePoint<SPACE_DIM>(
1136 field_eval_coords.data(), 1e-12, simple->getProblemName(),
1137 simple->getDomainFEName(), field_eval_data,
1139 QUIET);
1140
1141 if (vectorFieldPtr->size1()) {
1143 if constexpr (SPACE_DIM == 2)
1144 MOFEM_LOG("FieldEvaluator", Sev::inform)
1145 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1);
1146 else
1147 MOFEM_LOG("FieldEvaluator", Sev::inform)
1148 << "U_X: " << t_disp(0) << " U_Y: " << t_disp(1)
1149 << " U_Z: " << t_disp(2);
1150 }
1151
1153 }
1155 };
1156
1157 CHKERR evaluate_field_at_the_point();
1158
1160}
1161//! [Solve]
1162
1163//! [Postprocess results]
1165 SmartPetscObj<Vec> adjoint_vector) {
1167 auto simple = mField.getInterface<Simple>();
1168 auto pip = mField.getInterface<PipelineManager>();
1169 auto det_ptr = boost::make_shared<VectorDouble>();
1170 auto jac_ptr = boost::make_shared<MatrixDouble>();
1171 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
1172 //! [Postprocess clean]
1173 pip->getDomainRhsFE().reset();
1174 pip->getDomainLhsFE().reset();
1175 pip->getBoundaryRhsFE().reset();
1176 pip->getBoundaryLhsFE().reset();
1177 //! [Postprocess clean]
1178
1179 //! [Postprocess initialise]
1180 auto post_proc_mesh = boost::make_shared<moab::Core>();
1181 auto post_proc_begin = boost::make_shared<PostProcBrokenMeshInMoabBaseBegin>(
1182 mField, post_proc_mesh);
1183 auto post_proc_end = boost::make_shared<PostProcBrokenMeshInMoabBaseEnd>(
1184 mField, post_proc_mesh);
1185 //! [Postprocess initialise]
1186
1187 // lambada function to calculate displacement, strain and stress
1188 auto calculate_stress_ops = [&](auto &pip) {
1189 // Add H1 geometry ops
1191
1192 // Use HookeOps commonDataFactory to get matStrainPtr and matCauchyStressPtr
1194 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1195
1196 // Store U and GEOMETRY values if needed
1197 auto u_ptr = boost::make_shared<MatrixDouble>();
1198 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1199 auto x_ptr = boost::make_shared<MatrixDouble>();
1200 pip.push_back(
1201 new OpCalculateVectorFieldValues<SPACE_DIM>("GEOMETRY", x_ptr));
1202
1203 using DataMapMat = std::map<std::string, boost::shared_ptr<MatrixDouble>>;
1204
1205 DataMapMat vec_map = {{"U", u_ptr}, {"GEOMETRY", x_ptr}};
1206 DataMapMat sym_map = {{"STRAIN", common_ptr->getMatStrain()},
1207 {"STRESS", common_ptr->getMatCauchyStress()}};
1208
1209 if (adjoint_vector) {
1210 auto adjoint_ptr = boost::make_shared<MatrixDouble>();
1212 "U", adjoint_ptr, adjoint_vector));
1213 vec_map["ADJOINT"] = adjoint_ptr;
1214 }
1215
1216 // Return what you need: displacements, coordinates, strain, stress
1217 return boost::make_tuple(u_ptr, x_ptr, common_ptr->getMatStrain(),
1218 common_ptr->getMatCauchyStress(), vec_map,
1219 sym_map);
1220 };
1221
1222 auto get_tag_id_on_pmesh = [&](bool post_proc_skin) {
1223 int def_val_int = 0;
1224 Tag tag_mat;
1225 CHKERR mField.get_moab().tag_get_handle(
1226 "MAT_ELASTIC", 1, MB_TYPE_INTEGER, tag_mat,
1227 MB_TAG_CREAT | MB_TAG_SPARSE, &def_val_int);
1228 auto meshset_vec_ptr =
1229 mField.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
1230 std::regex((boost::format("%s(.*)") % "MAT_ELASTIC").str()));
1231
1232 Range skin_ents;
1233 std::unique_ptr<Skinner> skin_ptr;
1234 if (post_proc_skin) {
1235 skin_ptr = std::make_unique<Skinner>(&mField.get_moab());
1236 auto boundary_meshset = simple->getBoundaryMeshSet();
1237 CHKERR mField.get_moab().get_entities_by_handle(boundary_meshset,
1238 skin_ents, true);
1239 }
1240
1241 for (auto m : meshset_vec_ptr) {
1242 Range ents_3d;
1243 CHKERR mField.get_moab().get_entities_by_handle(m->getMeshset(), ents_3d,
1244 true);
1245 int const id = m->getMeshsetId();
1246 ents_3d = ents_3d.subset_by_dimension(SPACE_DIM);
1247 if (post_proc_skin) {
1248 Range skin_faces;
1249 CHKERR skin_ptr->find_skin(0, ents_3d, false, skin_faces);
1250 ents_3d = intersect(skin_ents, skin_faces);
1251 }
1252 CHKERR mField.get_moab().tag_clear_data(tag_mat, ents_3d, &id);
1253 }
1254
1255 return tag_mat;
1256 };
1257
1258 auto post_proc_domain = [&](auto post_proc_mesh) {
1259 auto post_proc_fe =
1260 boost::make_shared<PostProcEleDomain>(mField, post_proc_mesh);
1262
1263 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr, vec_map, sym_map] =
1264 calculate_stress_ops(post_proc_fe->getOpPtrVector());
1265
1266 post_proc_fe->getOpPtrVector().push_back(
1267
1268 new OpPPMap(
1269
1270 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1271
1272 {},
1273
1274 vec_map,
1275
1276 {},
1277
1278 sym_map
1279
1280 )
1281
1282 );
1283
1284 post_proc_fe->setTagsToTransfer({get_tag_id_on_pmesh(false)});
1285 return post_proc_fe;
1286 };
1287
1288 auto post_proc_boundary = [&](auto post_proc_mesh) {
1289 auto post_proc_fe =
1290 boost::make_shared<PostProcEleBdy>(mField, post_proc_mesh);
1292 post_proc_fe->getOpPtrVector(), {}, "GEOMETRY");
1293 auto op_loop_side =
1294 new OpLoopSide<SideEle>(mField, simple->getDomainFEName(), SPACE_DIM);
1295 // push ops to side element, through op_loop_side operator
1296 auto [u_ptr, x_ptr, mat_strain_ptr, mat_stress_ptr, vec_map, sym_map] =
1297 calculate_stress_ops(op_loop_side->getOpPtrVector());
1298 post_proc_fe->getOpPtrVector().push_back(op_loop_side);
1299 auto mat_traction_ptr = boost::make_shared<MatrixDouble>();
1300 post_proc_fe->getOpPtrVector().push_back(
1301 new ElasticExample::OpCalculateTraction(mat_stress_ptr,
1302 mat_traction_ptr));
1303 vec_map["T"] = mat_traction_ptr;
1304
1306
1307 post_proc_fe->getOpPtrVector().push_back(
1308
1309 new OpPPMap(
1310
1311 post_proc_fe->getPostProcMesh(), post_proc_fe->getMapGaussPts(),
1312
1313 {},
1314
1315 vec_map,
1316
1317 {},
1318
1319 sym_map
1320
1321 )
1322
1323 );
1324
1325 post_proc_fe->setTagsToTransfer({get_tag_id_on_pmesh(true)});
1326 return post_proc_fe;
1327 };
1328
1329 PetscBool post_proc_skin_only = PETSC_FALSE;
1330 if (SPACE_DIM == 3) {
1331 post_proc_skin_only = PETSC_TRUE;
1332 CHKERR PetscOptionsGetBool(PETSC_NULLPTR, "", "-post_proc_skin_only",
1333 &post_proc_skin_only, PETSC_NULLPTR);
1334 }
1335 if (post_proc_skin_only == PETSC_FALSE) {
1336 pip->getDomainRhsFE() = post_proc_domain(post_proc_mesh);
1337 } else {
1338 pip->getBoundaryRhsFE() = post_proc_boundary(post_proc_mesh);
1339 }
1340
1342 post_proc_begin->getFEMethod());
1343 CHKERR pip->loopFiniteElements();
1345 post_proc_end->getFEMethod());
1346
1347 CHKERR post_proc_end->writeFile("out_elastic_" + std::to_string(iter) +
1348 ".h5m");
1350}
1351//! [Postprocess results]
1352
1353//! [calculateGradient]
1354
1356
1357template <int SPACE_DIM>
1359 : public DomainBaseOp {
1360
1362
1363 OpAdJointTestOp(const std::string field_name,
1364 boost::shared_ptr<HookeOps::CommonData> comm_ptr)
1365 : OP(field_name, field_name, DomainEleOp::OPROW), commPtr(comm_ptr) {}
1366
1367protected:
1368 boost::shared_ptr<HookeOps::CommonData> commPtr;
1370};
1371
1372template <int SPACE_DIM>
1375 EntitiesFieldData::EntData &row_data) {
1383
1384 // get element volume
1385 const double vol = OP::getMeasure();
1386 // get integration weights
1387 auto t_w = OP::getFTensor0IntegrationWeight();
1388 // get base function gradient on rows
1389 auto t_row_grad = row_data.getFTensor1DiffN<SPACE_DIM>();
1390 // get stress
1391 auto t_cauchy_stress =
1392 getFTensor2SymmetricFromMat<SPACE_DIM>(*(commPtr->getMatCauchyStress()));
1393 // loop over integration points
1394 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1395 // take into account Jacobian
1396 const double alpha = t_w * vol;
1397
1398 // get rhs vector
1399 auto t_nf = OP::template getNf<SPACE_DIM>();
1400 // loop over rows base functions
1401 int rr = 0;
1402 for (; rr != OP::nbRows / SPACE_DIM; rr++) {
1403 // Variation due to change in geometry (diff base)
1404 t_nf(j) += alpha * t_row_grad(i) * t_cauchy_stress(i, j);
1405
1406 ++t_row_grad;
1407 ++t_nf;
1408 }
1409 for (; rr < OP::nbRowBaseFunctions; ++rr) {
1410 ++t_row_grad;
1411 }
1412
1413 ++t_cauchy_stress;
1414 ++t_w; // move to another integration weight
1415 }
1417}
1418
1419template <int SPACE_DIM>
1421 DomainBaseOp> : public DomainBaseOp {
1422
1424
1426 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
1427 boost::shared_ptr<MatrixDouble> jac,
1428 boost::shared_ptr<MatrixDouble> diff_jac,
1429 boost::shared_ptr<VectorDouble> cof_vals)
1430 : OP(field_name, field_name, DomainEleOp::OPROW), commPtr(comm_ptr),
1431 jac(jac), diffJac(diff_jac), cofVals(cof_vals) {}
1432
1433protected:
1434 boost::shared_ptr<HookeOps::CommonData> commPtr;
1435 boost::shared_ptr<MatrixDouble> jac;
1436 boost::shared_ptr<MatrixDouble> diffJac;
1437 boost::shared_ptr<VectorDouble> cofVals;
1439};
1440
1441template <int DIM> inline auto diff_symmetrize(FTensor::Number<DIM>) {
1442
1443 FTensor::Index<'i', DIM> i;
1444 FTensor::Index<'j', DIM> j;
1445 FTensor::Index<'k', DIM> k;
1446 FTensor::Index<'l', DIM> l;
1447
1449
1450 t_diff(i, j, k, l) = 0;
1451 t_diff(0, 0, 0, 0) = 1;
1452 t_diff(1, 1, 1, 1) = 1;
1453
1454 t_diff(1, 0, 1, 0) = 0.5;
1455 t_diff(1, 0, 0, 1) = 0.5;
1456
1457 t_diff(0, 1, 0, 1) = 0.5;
1458 t_diff(0, 1, 1, 0) = 0.5;
1459
1460 if constexpr (DIM == 3) {
1461 t_diff(2, 2, 2, 2) = 1;
1462
1463 t_diff(2, 0, 2, 0) = 0.5;
1464 t_diff(2, 0, 0, 2) = 0.5;
1465 t_diff(0, 2, 0, 2) = 0.5;
1466 t_diff(0, 2, 2, 0) = 0.5;
1467
1468 t_diff(2, 1, 2, 1) = 0.5;
1469 t_diff(2, 1, 1, 2) = 0.5;
1470 t_diff(1, 2, 1, 2) = 0.5;
1471 t_diff(1, 2, 2, 1) = 0.5;
1472 }
1473
1474 return t_diff;
1475};
1476
1477template <int SPACE_DIM>
1488
1489 auto t_diff_symm = diff_symmetrize(FTensor::Number<SPACE_DIM>());
1490
1491 // get element volume
1492 const double vol = OP::getMeasure();
1493 // get integration weights
1494 auto t_w = OP::getFTensor0IntegrationWeight();
1495 // get Jacobian values
1496 auto t_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(jac));
1497 // get diff Jacobian values
1498 auto t_diff_jac = getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(diffJac));
1499 // get cofactor values
1500 auto t_cof = getFTensor0FromVec(*(cofVals));
1501 // get base function gradient on rows
1502 auto t_row_grad = row_data.getFTensor1DiffN<SPACE_DIM>();
1503 // get fradient of the field
1504 auto t_grad_u =
1505 getFTensor2FromMat<SPACE_DIM, SPACE_DIM>(*(commPtr->matGradPtr));
1506 // get field gradient values
1507 auto t_cauchy_stress =
1508 getFTensor2SymmetricFromMat<SPACE_DIM>(*(commPtr->getMatCauchyStress()));
1509 // material stiffness tensor
1510 auto t_D =
1512 // loop over integration points
1513 for (int gg = 0; gg != OP::nbIntegrationPts; gg++) {
1514 // take into account Jacobian
1515 const double alpha = t_w * vol;
1516
1517 auto t_det = determinantTensor(t_jac);
1519 CHKERR invertTensor(t_jac, t_det, t_inv_jac);
1520
1521 // Calculate the variation of the gradient due to geometry change
1523 t_diff_inv_jac(i, j) =
1524 -(t_inv_jac(i, I) * t_diff_jac(I, J)) * t_inv_jac(J, j);
1526 t_diff_grad(i, j) = t_grad_u(i, k) * t_diff_inv_jac(k, j);
1527
1528 // Calculate the variation of the strain tensor
1530 t_diff_strain(i, j) = t_diff_symm(i, j, k, l) * t_diff_grad(k, l);
1531
1532 // Calculate the variation of the stress tensor
1534 t_diff_stress(i, j) = t_D(i, j, k, l) * t_diff_strain(k, l);
1535
1536 // get rhs vector
1537 auto t_nf = OP::template getNf<SPACE_DIM>();
1538 // loop over rows base functions
1539 int rr = 0;
1540 for (; rr != OP::nbRows / SPACE_DIM; rr++) {
1541
1543 t_diff_row_grad(k) = t_row_grad(j) * t_diff_inv_jac(j, k);
1544
1545 // Variation due to change in geometry (diff base)
1546 t_nf(j) += alpha * t_diff_row_grad(i) * t_cauchy_stress(i, j);
1547
1548 // Variation due to change in domain (cofactor)
1549 t_nf(j) += (alpha * t_cof) * t_row_grad(i) * t_cauchy_stress(i, j);
1550
1551 // Variation due to change in stress (diff stress)
1552 t_nf(j) += alpha * t_row_grad(i) * t_diff_stress(i, j);
1553
1554 ++t_row_grad;
1555 ++t_nf;
1556 }
1557 for (; rr < OP::nbRowBaseFunctions; ++rr) {
1558 ++t_row_grad;
1559 }
1560
1561 ++t_grad_u;
1562 ++t_cauchy_stress;
1563 ++t_jac;
1564 ++t_diff_jac;
1565 ++t_cof;
1566 ++t_w; // move to another integration weight
1567 }
1569}
1570
1571struct OpAdJointObjective : public ForcesAndSourcesCore::UserDataOperator {
1572 using OP = ForcesAndSourcesCore::UserDataOperator;
1573 OpAdJointObjective(boost::shared_ptr<ObjectiveFunctionData> python_ptr,
1574 boost::shared_ptr<HookeOps::CommonData> comm_ptr,
1575 boost::shared_ptr<MatrixDouble> jac_ptr,
1576 boost::shared_ptr<MatrixDouble> diff_jac,
1577 boost::shared_ptr<VectorDouble> cof_vals,
1578 boost::shared_ptr<MatrixDouble> d_grad_ptr,
1579 boost::shared_ptr<MatrixDouble> u_ptr,
1580 boost::shared_ptr<double> glob_objective_ptr,
1581 boost::shared_ptr<double> glob_objective_grad_ptr)
1582 : OP(NOSPACE, OP::OPSPACE), pythonPtr(python_ptr), commPtr(comm_ptr),
1583 jacPtr(jac_ptr), diffJacPtr(diff_jac), cofVals(cof_vals),
1584 dGradPtr(d_grad_ptr), uPtr(u_ptr), globObjectivePtr(glob_objective_ptr),
1585 globObjectiveGradPtr(glob_objective_grad_ptr) {}
1586
1587 MoFEMErrorCode doWork(int side, EntityType type,
1590
1595
1598
1599 constexpr auto symm_size = (SPACE_DIM * (SPACE_DIM + 1)) / 2;
1600
1601 auto t_diff_symm = diff_symmetrize(FTensor::Number<SPACE_DIM>());
1602
1603 auto nb_gauss_pts = getGaussPts().size2();
1604 auto objective_ptr = boost::make_shared<VectorDouble>(nb_gauss_pts);
1605 auto objective_dstress =
1606 boost::make_shared<MatrixDouble>(symm_size, nb_gauss_pts);
1607 auto objective_dstrain =
1608 boost::make_shared<MatrixDouble>(symm_size, nb_gauss_pts);
1609 auto obj_grad = boost::make_shared<MatrixDouble>(SPACE_DIM, nb_gauss_pts);
1610
1611 auto evaluate_python = [&]() {
1613 auto &coords = OP::getCoordsAtGaussPts();
1614 CHKERR pythonPtr->evalObjectiveFunction(
1615 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
1616 objective_ptr);
1617 CHKERR pythonPtr->evalObjectiveGradientStress(
1618 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
1619 objective_dstress);
1620 CHKERR pythonPtr->evalObjectiveGradientStrain(
1621 coords, uPtr, commPtr->getMatCauchyStress(), commPtr->getMatStrain(),
1622 objective_dstrain);
1623
1624 auto t_grad_u =
1626 auto t_D =
1630 auto t_cof = getFTensor0FromVec(*(cofVals));
1632
1633 auto t_obj = getFTensor0FromVec(*objective_ptr);
1634 auto t_obj_dstress =
1635 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstress);
1636 auto t_obj_dstrain =
1637 getFTensor2SymmetricFromMat<SPACE_DIM>(*objective_dstrain);
1638
1639 auto vol = OP::getMeasure();
1640 auto t_w = getFTensor0IntegrationWeight();
1641 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
1642
1643 auto t_det = determinantTensor(t_jac);
1645 CHKERR invertTensor(t_jac, t_det, t_inv_jac);
1646
1648 t_diff_inv_jac(i, j) =
1649 -(t_inv_jac(i, I) * t_diff_jac(I, J)) * t_inv_jac(J, j);
1651 t_diff_grad(i, j) = t_grad_u(i, k) * t_diff_inv_jac(k, j);
1652
1654 t_d_strain(i, j) = t_diff_symm(i, j, k, l) * (
1655
1656 t_d_grad(k, l)
1657
1658 +
1659
1660 t_diff_grad(k, l)
1661
1662 );
1663
1664 auto alpha = t_w * vol;
1665
1666 (*globObjectivePtr) += alpha * t_obj;
1667 (*globObjectiveGradPtr) +=
1668 alpha *
1669 (
1670
1671 t_obj_dstress(i, j) * (t_D(i, j, k, l) * t_d_strain(k, l))
1672
1673 +
1674
1675 t_obj_dstrain(i, j) * t_d_strain(i, j)
1676
1677 +
1678
1679 t_obj * t_cof
1680
1681 );
1682
1683 ++t_w;
1684 ++t_jac;
1685 ++t_diff_jac;
1686 ++t_cof;
1687
1688 ++t_obj;
1689 ++t_obj_dstress;
1690 ++t_obj_dstrain;
1691
1692 ++t_grad_u;
1693 ++t_d_grad;
1694 }
1696 };
1697
1698 CHKERR evaluate_python();
1699
1701 }
1702
1703private:
1704 boost::shared_ptr<ObjectiveFunctionData> pythonPtr;
1705 boost::shared_ptr<HookeOps::CommonData> commPtr;
1706 boost::shared_ptr<MatrixDouble> jacPtr;
1707 boost::shared_ptr<MatrixDouble> diffJacPtr;
1708 boost::shared_ptr<VectorDouble> cofVals;
1709 boost::shared_ptr<MatrixDouble> dGradPtr;
1710 boost::shared_ptr<MatrixDouble> uPtr;
1711
1712 boost::shared_ptr<double> globObjectivePtr;
1713 boost::shared_ptr<double> globObjectiveGradPtr;
1714};
1715
1716MoFEMErrorCode Example::calculateGradient(PetscReal *objective_function_value,
1717 Vec objective_function_gradient,
1718 Vec adjoint_vector) {
1719 MOFEM_LOG_CHANNEL("WORLD");
1721 auto simple = mField.getInterface<Simple>();
1722
1723 auto ents = get_range_from_block(mField, "OPTIMISE", SPACE_DIM - 1);
1724
1725 auto get_essential_fe = [this]() {
1726 auto post_proc_rhs = boost::make_shared<FEMethod>();
1727 auto get_post_proc_hook_rhs = [this, post_proc_rhs]() {
1729
1731 post_proc_rhs, 0)();
1733 };
1734 post_proc_rhs->postProcessHook = get_post_proc_hook_rhs;
1735 return post_proc_rhs;
1736 };
1737
1738 auto get_fd_direvative_fe = [&]() {
1739 auto fe = boost::make_shared<DomainEle>(mField);
1740 fe->getRuleHook = [](int, int, int p_data) {
1741 return 2 * p_data + p_data - 1;
1742 };
1743 auto &pip = fe->getOpPtrVector();
1745 // Add RHS operators for internal forces
1746 constexpr bool debug = false;
1747 if constexpr (debug) {
1749 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1750 pip.push_back(
1751 new OpAdJointTestOp<SPACE_DIM, I, DomainBaseOp>("U", common_ptr));
1752 } else {
1754 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1755 }
1756 return fe;
1757 };
1758
1759 auto calulate_fd_residual = [&](auto eps, auto diff_vec, auto fd_vec) {
1761
1762 constexpr bool debug = false;
1763
1764 auto geom_norm = [](MoFEM::Interface &mField) {
1766 auto field_blas = mField.getInterface<FieldBlas>();
1767 double nrm2 = 0.0;
1768 auto norm2_field = [&](const double val) {
1769 nrm2 += val * val;
1770 return val;
1771 };
1772 CHKERR field_blas->fieldLambdaOnValues(norm2_field, "GEOMETRY");
1773 MPI_Allreduce(MPI_IN_PLACE, &nrm2, 1, MPI_DOUBLE, MPI_SUM,
1774 mField.get_comm());
1775 MOFEM_LOG("WORLD", Sev::inform) << "Geometry norm: " << sqrt(nrm2);
1777 };
1778
1779 if constexpr (debug)
1780 CHKERR geom_norm(mField);
1781
1782 auto initial_current_geometry = createDMVector(adjointDM);
1783 CHKERR mField.getInterface<VecManager>()->setOtherLocalGhostVector(
1784 "ADJOINT", "ADJOINT_FIELD", "GEOMETRY", RowColData::ROW,
1785 initial_current_geometry, INSERT_VALUES, SCATTER_FORWARD);
1786 CHKERR VecAssemblyBegin(initial_current_geometry);
1787 CHKERR VecAssemblyEnd(initial_current_geometry);
1788
1789 if constexpr (debug)
1790 CHKERR geom_norm(mField);
1791
1792 auto perturb_geometry = [&](auto eps, auto diff_vec) {
1794 auto current_geometry = vectorDuplicate(initial_current_geometry);
1795 CHKERR VecCopy(initial_current_geometry, current_geometry);
1796 CHKERR VecAXPY(current_geometry, eps, diff_vec);
1797 CHKERR mField.getInterface<VecManager>()->setOtherLocalGhostVector(
1798 "ADJOINT", "ADJOINT_FIELD", "GEOMETRY", RowColData::ROW,
1799 current_geometry, INSERT_VALUES, SCATTER_REVERSE);
1801 };
1802
1803 auto fe = get_fd_direvative_fe();
1804 auto fp = vectorDuplicate(diff_vec);
1805 auto fm = vectorDuplicate(diff_vec);
1806 auto calc_impl = [&](auto f, auto eps) {
1808 CHKERR VecZeroEntries(f);
1809 fe->f = f;
1810 CHKERR perturb_geometry(eps, diff_vec);
1812 simple->getDomainFEName(), fe);
1813 CHKERR VecAssemblyBegin(f);
1814 CHKERR VecAssemblyEnd(f);
1815 CHKERR VecGhostUpdateBegin(f, ADD_VALUES, SCATTER_REVERSE);
1816 CHKERR VecGhostUpdateEnd(f, ADD_VALUES, SCATTER_REVERSE);
1817 auto post_proc_rhs = get_essential_fe();
1818 post_proc_rhs->f = f;
1820 post_proc_rhs.get());
1822 };
1823 CHKERR calc_impl(fp, eps);
1824 CHKERR calc_impl(fm, -eps);
1825 CHKERR VecWAXPY(fd_vec, -1.0, fm, fp);
1826 CHKERR VecScale(fd_vec, 1.0 / (2.0 * eps));
1827
1828 CHKERR mField.getInterface<VecManager>()->setOtherLocalGhostVector(
1829 "ADJOINT", "ADJOINT_FIELD", "GEOMETRY", RowColData::ROW,
1830 initial_current_geometry, INSERT_VALUES, SCATTER_REVERSE);
1831
1832 if constexpr (debug)
1833 CHKERR geom_norm(mField);
1834
1836 };
1837
1838 auto get_direvative_fe = [&](auto diff_vec) {
1839 auto fe_adjoint = boost::make_shared<DomainEle>(mField);
1840 fe_adjoint->getRuleHook = [](int, int, int p_data) {
1841 return 2 * p_data + p_data - 1;
1842 };
1843 auto &pip = fe_adjoint->getOpPtrVector();
1844
1845 auto jac_ptr = boost::make_shared<MatrixDouble>();
1846 auto det_ptr = boost::make_shared<VectorDouble>();
1847 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
1848 auto diff_jac_ptr = boost::make_shared<MatrixDouble>();
1849 auto cof_ptr = boost::make_shared<VectorDouble>();
1850
1851 using OpCoFactor =
1852 AdJoint<DomainEleOp>::Integration<GAUSS>::OpGetCoFactor<SPACE_DIM>;
1853
1855
1857 "GEOMETRY", jac_ptr));
1859 "U", diff_jac_ptr,
1860 diff_vec)); // Note: that vector is stored on displacemnt vector, that
1861 // why is used here
1862
1863 pip.push_back(new OpCoFactor(jac_ptr, diff_jac_ptr, cof_ptr));
1864
1865 // Add RHS operators for internal forces
1867 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1869 "U", common_ptr, jac_ptr, diff_jac_ptr, cof_ptr));
1870
1871 return fe_adjoint;
1872 };
1873
1874 auto get_objective_fe = [&](auto diff_vec, auto grad_vec,
1875 auto glob_objective_ptr,
1876 auto glob_objective_grad_ptr) {
1877 auto fe_adjoint = boost::make_shared<DomainEle>(mField);
1878 fe_adjoint->getRuleHook = [](int, int, int p_data) {
1879 return 2 * p_data + p_data - 1;
1880 };
1881 auto &pip = fe_adjoint->getOpPtrVector();
1883
1884 auto jac_ptr = boost::make_shared<MatrixDouble>();
1885 auto det_ptr = boost::make_shared<VectorDouble>();
1886 auto inv_jac_ptr = boost::make_shared<MatrixDouble>();
1887 auto diff_jac_ptr = boost::make_shared<MatrixDouble>();
1888 auto cof_ptr = boost::make_shared<VectorDouble>();
1889 auto d_grad_ptr = boost::make_shared<MatrixDouble>();
1890 auto u_ptr = boost::make_shared<MatrixDouble>();
1891
1892 using OpCoFactor =
1893 AdJoint<DomainEleOp>::Integration<GAUSS>::OpGetCoFactor<SPACE_DIM>;
1895 "GEOMETRY", jac_ptr));
1897 "U", diff_jac_ptr,
1898 diff_vec)); // Note: that vector is stored on displacemnt vector, that
1899 // why is used here
1900 pip.push_back(new OpCoFactor(jac_ptr, diff_jac_ptr, cof_ptr));
1902 "U", d_grad_ptr, grad_vec));
1903 pip.push_back(new OpCalculateVectorFieldValues<SPACE_DIM>("U", u_ptr));
1904
1906 mField, pip, "U", "MAT_ELASTIC", Sev::noisy);
1907 pip.push_back(new OpAdJointObjective(
1908 pythonPtr, common_ptr, jac_ptr, diff_jac_ptr, cof_ptr, d_grad_ptr,
1909 u_ptr, glob_objective_ptr, glob_objective_grad_ptr));
1910
1911 return fe_adjoint;
1912 };
1913
1914 auto dm = simple->getDM();
1915 auto f = createDMVector(dm);
1916 auto d = vectorDuplicate(f);
1917 auto dm_diff_vec = vectorDuplicate(d);
1918
1919 auto adjoint_fe = get_direvative_fe(dm_diff_vec);
1920 auto glob_objective_ptr = boost::make_shared<double>(0.0);
1921 auto glob_objective_grad_ptr = boost::make_shared<double>(0.0);
1922 auto objective_fe = get_objective_fe(dm_diff_vec, d, glob_objective_ptr,
1923 glob_objective_grad_ptr);
1924
1925 auto set_variance_of_geometry = [&](auto mode, auto mod_vec) {
1927 CHKERR DMoFEMMeshToLocalVector(adjointDM, mod_vec, INSERT_VALUES,
1928 SCATTER_REVERSE);
1929 CHKERR mField.getInterface<VecManager>()->setOtherLocalGhostVector(
1930 simple->getProblemName(), "U", "ADJOINT_FIELD", RowColData::ROW,
1931 dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1932 CHKERR VecGhostUpdateBegin(dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1933 CHKERR VecGhostUpdateEnd(dm_diff_vec, INSERT_VALUES, SCATTER_FORWARD);
1935 };
1936
1937 auto calculate_variance_internal_forces = [&](auto mode, auto mod_vec) {
1939 CHKERR VecZeroEntries(f);
1940 CHKERR VecGhostUpdateBegin(f, INSERT_VALUES, SCATTER_FORWARD);
1941 CHKERR VecGhostUpdateEnd(f, INSERT_VALUES, SCATTER_FORWARD);
1942 adjoint_fe->f = f;
1943 CHKERR DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(), adjoint_fe);
1944 CHKERR VecAssemblyBegin(f);
1945 CHKERR VecAssemblyEnd(f);
1946 CHKERR VecGhostUpdateBegin(f, ADD_VALUES, SCATTER_REVERSE);
1947 CHKERR VecGhostUpdateEnd(f, ADD_VALUES, SCATTER_REVERSE);
1948 auto post_proc_rhs = get_essential_fe();
1949 post_proc_rhs->f = f;
1951 post_proc_rhs.get());
1952 CHKERR VecScale(f, -1.0);
1953
1954#ifndef NDEBUG
1955 constexpr bool debug = false;
1956 if constexpr (debug) {
1957 double norm0;
1958 CHKERR VecNorm(f, NORM_2, &norm0);
1959 auto fd_check = vectorDuplicate(f);
1960 double eps = 1e-5;
1961 CHKERR calulate_fd_residual(eps, dm_diff_vec, fd_check);
1962 double nrm;
1963 CHKERR VecAXPY(fd_check, -1.0, f);
1964 CHKERR VecNorm(fd_check, NORM_2, &nrm);
1965 MOFEM_LOG("WORLD", Sev::inform)
1966 << " FD check for internal forces [ " << mode << " ]: " << nrm
1967 << " / " << norm0 << " ( " << (nrm / norm0) << " )";
1968 }
1969#endif
1970
1972 };
1973
1974 auto calulate_variance_of_displacemnte = [&](auto mode, auto mod_vec) {
1976 CHKERR KSPSolve(kspElastic, f, d);
1977 CHKERR VecGhostUpdateBegin(d, INSERT_VALUES, SCATTER_FORWARD);
1978 CHKERR VecGhostUpdateEnd(d, INSERT_VALUES, SCATTER_FORWARD);
1980 };
1981
1982 auto calculate_variance_of_objective_function = [&](auto mode, auto mod_vec) {
1984 *glob_objective_ptr = 0.0;
1985 *glob_objective_grad_ptr = 0.0;
1986 CHKERR DMoFEMLoopFiniteElements(dm, simple->getDomainFEName(),
1987 objective_fe);
1988 CHKERR VecSetValue(objective_function_gradient, mode,
1989 *glob_objective_grad_ptr, ADD_VALUES);
1990 std::array<double, 2> array = {*glob_objective_ptr,
1991 *glob_objective_grad_ptr};
1992 MPI_Allreduce(MPI_IN_PLACE, array.data(), 2, MPI_DOUBLE, MPI_SUM,
1993 mField.get_comm());
1994 *glob_objective_ptr = array[0];
1995 *glob_objective_grad_ptr = array[1];
1996 (*objective_function_value) += *glob_objective_ptr;
1997 MOFEM_LOG_CHANNEL("WORLD");
1998 MOFEM_LOG("WORLD", Sev::verbose) << " Objective gradient [ " << mode
1999 << " ]: " << *glob_objective_grad_ptr;
2001 };
2002
2003 CHKERR VecZeroEntries(objective_function_gradient);
2004 CHKERR VecZeroEntries(adjoint_vector);
2005 *objective_function_value = 0.0;
2006 int mode = 0;
2007 for (auto mod_vec : modeVecs) {
2008
2009 CHKERR set_variance_of_geometry(mode, mod_vec);
2010 CHKERR calculate_variance_internal_forces(mode, mod_vec);
2011 CHKERR calulate_variance_of_displacemnte(mode, mod_vec);
2012 CHKERR calculate_variance_of_objective_function(mode, mod_vec);
2013
2014 CHKERR VecAXPY(adjoint_vector, *glob_objective_grad_ptr, dm_diff_vec);
2015 ++mode;
2016 }
2017
2018 (*objective_function_value) /= modeVecs.size();
2019 MOFEM_LOG("WORLD", Sev::verbose)
2020 << "Objective function: " << *glob_objective_ptr;
2021
2022 CHKERR VecAssemblyBegin(objective_function_gradient);
2023 CHKERR VecAssemblyEnd(objective_function_gradient);
2024
2025 CHKERR VecAssemblyBegin(adjoint_vector);
2026 CHKERR VecAssemblyEnd(adjoint_vector);
2027 CHKERR VecGhostUpdateBegin(adjoint_vector, INSERT_VALUES, SCATTER_FORWARD);
2028 CHKERR VecGhostUpdateEnd(adjoint_vector, INSERT_VALUES, SCATTER_FORWARD);
2029
2031}
2032//! [calculateGradient]
2033
2034static char help[] = "...\n\n";
2035
2036int main(int argc, char *argv[]) {
2037
2038 Py_Initialize();
2039 np::initialize();
2040
2041 // Initialisation of MoFEM/PETSc and MOAB data structures
2042 const char param_file[] = "param_file.petsc";
2043 MoFEM::Core::Initialize(&argc, &argv, param_file, help);
2044
2045 auto core_log = logging::core::get();
2046 core_log->add_sink(
2048
2049 core_log->add_sink(
2050 LogManager::createSink(LogManager::getStrmSync(), "FieldEvaluator"));
2051 LogManager::setLog("FieldEvaluator");
2052 MOFEM_LOG_TAG("FieldEvaluator", "field_eval");
2053
2054 try {
2055
2056 //! [Register MoFEM discrete manager in PETSc]
2057 DMType dm_name = "DMMOFEM";
2058 CHKERR DMRegister_MoFEM(dm_name);
2059 DMType dm_name_mg = "DMMOFEM_MG";
2061 //! [Register MoFEM discrete manager in PETSc
2062
2063 //! [Create MoAB]
2064 moab::Core mb_instance; ///< mesh database
2065 moab::Interface &moab = mb_instance; ///< mesh database interface
2066 //! [Create MoAB]
2067
2068 //! [Create MoFEM]
2069 MoFEM::Core core(moab); ///< finite element database
2070 MoFEM::Interface &m_field = core; ///< finite element database interface
2071 //! [Create MoFEM]
2072
2073 //! [Example]
2074 Example ex(m_field);
2075 CHKERR ex.runProblem();
2076 //! [Example]
2077 }
2079
2081
2082 if (Py_FinalizeEx() < 0) {
2083 exit(120);
2084 }
2085}
2086
2089 virtual ~ObjectiveFunctionDataImpl() = default;
2090
2091 MoFEMErrorCode initPython(const std::string py_file);
2092
2095 boost::shared_ptr<MatrixDouble> u_ptr,
2096 boost::shared_ptr<MatrixDouble> stress_ptr,
2097 boost::shared_ptr<MatrixDouble> strain_ptr,
2098 boost::shared_ptr<VectorDouble> o_ptr);
2099
2102 boost::shared_ptr<MatrixDouble> u_ptr,
2103 boost::shared_ptr<MatrixDouble> stress_ptr,
2104 boost::shared_ptr<MatrixDouble> strain_ptr,
2105 boost::shared_ptr<MatrixDouble> o_ptr);
2106
2109 boost::shared_ptr<MatrixDouble> u_ptr,
2110 boost::shared_ptr<MatrixDouble> stress_ptr,
2111 boost::shared_ptr<MatrixDouble> strain_ptr,
2112 boost::shared_ptr<MatrixDouble> o_ptr);
2113
2116 boost::shared_ptr<MatrixDouble> u_ptr,
2117 boost::shared_ptr<MatrixDouble> stress_ptr,
2118 boost::shared_ptr<MatrixDouble> strain_ptr,
2119 boost::shared_ptr<MatrixDouble> o_ptr);
2120
2121 MoFEMErrorCode numberOfModes(int block_id, int &modes);
2122
2123 MoFEMErrorCode blockModes(int block_id, MatrixDouble &coords,
2124 std::array<double, 3> &centroid,
2125 std::array<double, 6> &bbodx, MatrixDouble &o_ptr);
2126
2127private:
2128 bp::object mainNamespace;
2135
2137
2138 np::ndarray coords, np::ndarray u,
2139
2140 np::ndarray stress, np::ndarray strain, np::ndarray &o
2141
2142 );
2143
2145
2146 np::ndarray coords, np::ndarray u,
2147
2148 np::ndarray stress, np::ndarray strain, np::ndarray &o
2149
2150 );
2151
2153
2154 np::ndarray coords, np::ndarray u,
2155
2156 np::ndarray stress, np::ndarray strain, np::ndarray &o
2157
2158 );
2159
2161
2162 np::ndarray coords, np::ndarray u,
2163
2164 np::ndarray stress, np::ndarray strain, np::ndarray &o
2165
2166 );
2167
2169
2170 int block_id, np::ndarray coords, np::ndarray centroid, np::ndarray bbodx,
2171 np::ndarray &o_ptr
2172
2173 );
2174
2175 np::ndarray convertToNumPy(std::vector<double> &data, int rows,
2176 int nb_gauss_pts);
2177
2178 np::ndarray convertToNumPy(double *ptr, int s);
2179
2181 void copyToSymmetric(double *ptr, MatrixDouble &s);
2182};
2183
2184boost::shared_ptr<ObjectiveFunctionData>
2186 auto ptr = boost::make_shared<ObjectiveFunctionDataImpl>();
2187 CHK_THROW_MESSAGE(ptr->initPython(py_file), "init python");
2188 return ptr;
2189}
2190
2192ObjectiveFunctionDataImpl::initPython(const std::string py_file) {
2194 try {
2195
2196 // create main module
2197 auto main_module = bp::import("__main__");
2198 mainNamespace = main_module.attr("__dict__");
2199 bp::exec_file(py_file.c_str(), mainNamespace, mainNamespace);
2200 // create a reference to python function
2205 objectNumberOfModes = mainNamespace["number_of_modes"];
2206 objectBlockModes = mainNamespace["block_modes"];
2207
2208 } catch (bp::error_already_set const &) {
2209 // print all other errors to stderr
2210 PyErr_Print();
2212 }
2214}
2215
2217 MatrixDouble f(9, s.size2());
2218 f.clear();
2221 auto t_f = getFTensor2FromMat<3, 3>(f);
2223 for (int ii = 0; ii != s.size2(); ++ii) {
2224 t_f(i, j) = t_s(i, j);
2225 ++t_f;
2226 ++t_s;
2227 }
2228 return f;
2229};
2230
2235
2236 ptr + 0 * s.size2(), ptr + 1 * s.size2(),
2237 ptr + 2 * s.size2(), ptr + 3 * s.size2(),
2238 ptr + 4 * s.size2(), ptr + 5 * s.size2(),
2239 ptr + 6 * s.size2(), ptr + 7 * s.size2(),
2240 ptr + 8 * s.size2()
2241
2242 };
2244 for (int ii = 0; ii != s.size2(); ++ii) {
2245 t_s(i, j) = (t_f(i, j) || t_f(j, i)) / 2.0;
2246 ++t_f;
2247 ++t_s;
2248 }
2249}
2250
2252 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
2253 boost::shared_ptr<MatrixDouble> stress_ptr,
2254 boost::shared_ptr<MatrixDouble> strain_ptr,
2255 boost::shared_ptr<VectorDouble> o_ptr) {
2257 try {
2258
2259 auto np_coords =
2260 convertToNumPy(coords.data(), coords.size1(), coords.size2());
2261 auto np_u = convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
2262
2263 auto full_stress = copyToFull(*(stress_ptr));
2264 auto full_strain = copyToFull(*(strain_ptr));
2265
2266 auto np_stress = convertToNumPy(full_stress.data(), full_stress.size1(),
2267 full_stress.size2());
2268 auto np_strain = convertToNumPy(full_strain.data(), full_strain.size1(),
2269 full_strain.size2());
2270 np::ndarray np_output = np::empty(bp::make_tuple(strain_ptr->size2()),
2271 np::dtype::get_builtin<double>());
2272 CHKERR objectiveFunctionImpl(np_coords, np_u, np_stress, np_strain,
2273 np_output);
2274 o_ptr->resize(stress_ptr->size2(), false);
2275 double *val_ptr = reinterpret_cast<double *>(np_output.get_data());
2276 std::copy(val_ptr, val_ptr + strain_ptr->size2(), o_ptr->data().begin());
2277
2278 } catch (bp::error_already_set const &) {
2279 PyErr_Print();
2281 }
2283}
2284
2286 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
2287 boost::shared_ptr<MatrixDouble> stress_ptr,
2288 boost::shared_ptr<MatrixDouble> strain_ptr,
2289 boost::shared_ptr<MatrixDouble> o_ptr) {
2291 try {
2292
2293 auto np_coords =
2294 convertToNumPy(coords.data(), coords.size1(), coords.size2());
2295 auto np_u = convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
2296
2297 auto full_stress = copyToFull(*(stress_ptr));
2298 auto full_strain = copyToFull(*(strain_ptr));
2299
2300 auto np_stress = convertToNumPy(full_stress.data(), full_stress.size1(),
2301 full_stress.size2());
2302 auto np_strain = convertToNumPy(full_strain.data(), full_strain.size1(),
2303 full_strain.size2());
2304 np::ndarray np_output =
2305 np::empty(bp::make_tuple(full_strain.size1(), full_strain.size2()),
2306 np::dtype::get_builtin<double>());
2307 CHKERR objectiveGradientStressImpl(np_coords, np_u, np_stress, np_strain,
2308 np_output);
2309 o_ptr->resize(stress_ptr->size1(), stress_ptr->size2(), false);
2310 double *val_ptr = reinterpret_cast<double *>(np_output.get_data());
2311 copyToSymmetric(val_ptr, *(o_ptr));
2312
2313 } catch (bp::error_already_set const &) {
2314 PyErr_Print();
2316 }
2318}
2319
2321 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
2322 boost::shared_ptr<MatrixDouble> stress_ptr,
2323 boost::shared_ptr<MatrixDouble> strain_ptr,
2324 boost::shared_ptr<MatrixDouble> o_ptr) {
2326 try {
2327
2328 auto np_coords =
2329 convertToNumPy(coords.data(), coords.size1(), coords.size2());
2330 auto np_u = convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
2331
2332 auto full_stress = copyToFull(*(stress_ptr));
2333 auto full_strain = copyToFull(*(strain_ptr));
2334 auto np_stress = convertToNumPy(full_stress.data(), full_stress.size1(),
2335 full_stress.size2());
2336 auto np_strain = convertToNumPy(full_strain.data(), full_strain.size1(),
2337 full_strain.size2());
2338
2339 np::ndarray np_output =
2340 np::empty(bp::make_tuple(full_strain.size1(), full_strain.size2()),
2341 np::dtype::get_builtin<double>());
2342 CHKERR objectiveGradientStrainImpl(np_coords, np_u, np_stress, np_strain,
2343 np_output);
2344 o_ptr->resize(strain_ptr->size1(), strain_ptr->size2(), false);
2345 double *val_ptr = reinterpret_cast<double *>(np_output.get_data());
2346 copyToSymmetric(val_ptr, *(o_ptr));
2347
2348 } catch (bp::error_already_set const &) {
2349 PyErr_Print();
2351 }
2353}
2354
2356 MatrixDouble &coords, boost::shared_ptr<MatrixDouble> u_ptr,
2357 boost::shared_ptr<MatrixDouble> stress_ptr,
2358 boost::shared_ptr<MatrixDouble> strain_ptr,
2359 boost::shared_ptr<MatrixDouble> o_ptr) {
2361 try {
2362
2363 auto np_coords =
2364 convertToNumPy(coords.data(), coords.size1(), coords.size2());
2365 auto np_u = convertToNumPy(u_ptr->data(), u_ptr->size1(), u_ptr->size2());
2366
2367 auto full_stress = copyToFull(*(stress_ptr));
2368 auto full_strain = copyToFull(*(strain_ptr));
2369 auto np_stress = convertToNumPy(full_stress.data(), full_stress.size1(),
2370 full_stress.size2());
2371 auto np_strain = convertToNumPy(full_strain.data(), full_strain.size1(),
2372 full_strain.size2());
2373
2374 np::ndarray np_output =
2375 np::empty(bp::make_tuple(u_ptr->size1(), u_ptr->size2()),
2376 np::dtype::get_builtin<double>());
2377 CHKERR objectiveGradientStrainImpl(np_coords, np_u, np_stress, np_strain,
2378 np_output);
2379 o_ptr->resize(u_ptr->size1(), u_ptr->size2(), false);
2380 double *val_ptr = reinterpret_cast<double *>(np_output.get_data());
2381 std::copy(val_ptr, val_ptr + u_ptr->size1() * u_ptr->size2(),
2382 o_ptr->data().begin());
2383
2384 } catch (bp::error_already_set const &) {
2385 PyErr_Print();
2387 }
2389}
2390
2392 int block_id, MatrixDouble &coords, std::array<double, 3> &centroid,
2393 std::array<double, 6> &bbodx, MatrixDouble &o_ptr) {
2395 try {
2396
2397 int nb_modes = bp::extract<int>(objectNumberOfModes(block_id));
2398
2399 auto np_coords =
2400 convertToNumPy(coords.data(), coords.size1(), coords.size2());
2401
2402 auto np_centroid = convertToNumPy(centroid.data(), 3);
2403 auto np_bbodx = convertToNumPy(bbodx.data(), 6);
2404
2405 np::ndarray np_output =
2406 np::empty(bp::make_tuple(coords.size1(), nb_modes, 3),
2407 np::dtype::get_builtin<double>());
2408 CHKERR blockModesImpl(block_id, np_coords, np_centroid, np_bbodx,
2409 np_output);
2410
2411 o_ptr.resize(nb_modes, coords.size1() * coords.size2(), false);
2412 double *val_ptr = reinterpret_cast<double *>(np_output.get_data());
2413 std::copy(val_ptr, val_ptr + coords.size1() * coords.size2() * nb_modes,
2414 o_ptr.data().begin());
2415
2416 } catch (bp::error_already_set const &) {
2417 PyErr_Print();
2419 }
2421}
2422
2424
2425 np::ndarray coords, np::ndarray u,
2426
2427 np::ndarray stress, np::ndarray strain, np::ndarray &o
2428
2429) {
2431 try {
2432
2433 // call python function
2434 o = bp::extract<np::ndarray>(objectiveFunction(coords, u, stress, strain));
2435
2436 } catch (bp::error_already_set const &) {
2437 // print all other errors to stderr
2438 PyErr_Print();
2440 }
2442}
2443
2445
2446 np::ndarray coords, np::ndarray u,
2447
2448 np::ndarray stress, np::ndarray strain, np::ndarray &o
2449
2450) {
2452 try {
2453
2454 // call python function
2455 o = bp::extract<np::ndarray>(
2456 objectiveGradientStress(coords, u, stress, strain));
2457
2458 } catch (bp::error_already_set const &) {
2459 // print all other errors to stderr
2460 PyErr_Print();
2462 }
2464}
2465
2467
2468 np::ndarray coords, np::ndarray u,
2469
2470 np::ndarray stress, np::ndarray strain, np::ndarray &o
2471
2472) {
2474 try {
2475
2476 // call python function
2477 o = bp::extract<np::ndarray>(
2478 objectiveGradientStrain(coords, u, stress, strain));
2479
2480 } catch (bp::error_already_set const &) {
2481 // print all other errors to stderr
2482 PyErr_Print();
2484 }
2486}
2487
2489
2490 np::ndarray coords, np::ndarray u,
2491
2492 np::ndarray stress, np::ndarray strain, np::ndarray &o
2493
2494) {
2496 try {
2497
2498 // call python function
2499 o = bp::extract<np::ndarray>(objectiveGradientU(coords, u, stress, strain));
2500
2501 } catch (bp::error_already_set const &) {
2502 // print all other errors to stderr
2503 PyErr_Print();
2505 }
2507}
2508
2510 int &modes) {
2512 try {
2513
2514 modes = bp::extract<int>(objectNumberOfModes(block_id));
2515
2516 } catch (bp::error_already_set const &) {
2517 // print all other errors to stderr
2518 PyErr_Print();
2520 }
2522}
2523
2525 np::ndarray coords,
2526 np::ndarray centroid,
2527 np::ndarray bbodx,
2528 np::ndarray &o) {
2530 try {
2531 // call python function
2532 o = bp::extract<np::ndarray>(
2533 objectBlockModes(block_id, coords, centroid, bbodx));
2534 } catch (bp::error_already_set const &) {
2535 // print all other errors to stderr
2536 PyErr_Print();
2538 }
2540}
2541
2542/**
2543 * @brief Converts a std::vector<double> to a NumPy ndarray.
2544 *
2545 * This function wraps the given vector data into a NumPy array with the
2546 * specified number of rows and Gauss points. The resulting ndarray shares
2547 * memory with the input vector, so changes to one will affect the other.
2548 *
2549 * @param data Reference to the vector containing double values to be converted.
2550 * @param rows Number of rows in the resulting NumPy array.
2551 * @param nb_gauss_pts Number of Gauss points (columns) in the resulting NumPy
2552 * array.
2553 * @return np::ndarray NumPy array view of the input data.
2554 *
2555 * @note
2556 * - `size` specifies the shape of the resulting ndarray as a tuple (rows,
2557 * nb_gauss_pts).
2558 * - `stride` specifies the step size in bytes to move to the next element in
2559 * memory. Here, it is set to sizeof(double), indicating contiguous storage for
2560 * each element.
2561 */
2562inline np::ndarray
2563ObjectiveFunctionDataImpl::convertToNumPy(std::vector<double> &data, int rows,
2564 int nb_gauss_pts) {
2565 auto dtype = np::dtype::get_builtin<double>();
2566 auto size = bp::make_tuple(rows, nb_gauss_pts);
2567 auto stride = bp::make_tuple(nb_gauss_pts * sizeof(double), sizeof(double));
2568 return (np::from_data(data.data(), dtype, size, stride, bp::object()));
2569}
2570
2571inline np::ndarray ObjectiveFunctionDataImpl::convertToNumPy(double *ptr,
2572 int s) {
2573 auto dtype = np::dtype::get_builtin<double>();
2574 auto size = bp::make_tuple(s);
2575 auto stride = bp::make_tuple(sizeof(double));
2576 return (np::from_data(ptr, dtype, size, stride, bp::object()));
2577}
2578
2580 const std::string block_name, int dim) {
2581 Range r;
2582
2583 auto mesh_mng = m_field.getInterface<MeshsetsManager>();
2584 auto bcs = mesh_mng->getCubitMeshsetPtr(
2585
2586 std::regex((boost::format("%s(.*)") % block_name).str())
2587
2588 );
2589
2590 for (auto bc : bcs) {
2591 Range faces;
2592 CHK_MOAB_THROW(bc->getMeshsetIdEntitiesByDimension(m_field.get_moab(), dim,
2593 faces, true),
2594 "get meshset ents");
2595 r.merge(faces);
2596 }
2597
2598 for (auto dd = dim - 1; dd >= 0; --dd) {
2599 if (dd >= 0) {
2600 Range ents;
2601 CHK_MOAB_THROW(m_field.get_moab().get_adjacencies(r, dd, false, ents,
2602 moab::Interface::UNION),
2603 "get adjs");
2604 r.merge(ents);
2605 } else {
2606 Range verts;
2607 CHK_MOAB_THROW(m_field.get_moab().get_connectivity(r, verts),
2608 "get verts");
2609 r.merge(verts);
2610 }
2612 m_field.getInterface<CommInterface>()->synchroniseEntities(r), "comm");
2613 }
2614
2615 return r;
2616};
2617
2618MoFEMErrorCode save_range(moab::Interface &moab, const std::string name,
2619 const Range r) {
2621 auto out_meshset = get_temp_meshset_ptr(moab);
2622 CHKERR moab.add_entities(*out_meshset, r);
2623 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1);
2625};
Calculate traction for linear problem.
Implementation of elastic spring bc.
Natural boundary condition applying pressure from fluid.
Implementation of Hookes operator Hookes for linear elastic problems in MoFEM.
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
Implementation of natural boundary conditions.
Boundary conditions in domain, i.e. body forces.
#define FTENSOR_INDEX(DIM, I)
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
auto diff_symmetrize(FTensor::Number< DIM >)
Definition adjoint.cpp:1441
static char help[]
[calculateGradient]
Definition adjoint.cpp:2034
PetscBool is_plane_strain
Definition adjoint.cpp:78
constexpr int SPACE_DIM
[Define dimension]
Definition adjoint.cpp:22
constexpr double poisson_ratio
Definition adjoint.cpp:74
constexpr int BASE_DIM
Definition adjoint.cpp:19
constexpr double shear_modulus_G
Definition adjoint.cpp:76
constexpr IntegrationType I
Definition adjoint.cpp:27
constexpr double bulk_modulus_K
Definition adjoint.cpp:75
FormsIntegrators< DomainEleOp >::Assembly< A >::OpBase DomainBaseOp
[Postprocess results]
Definition adjoint.cpp:1355
boost::shared_ptr< ObjectiveFunctionData > create_python_objective_function(std::string py_file)
Definition adjoint.cpp:2185
Range get_range_from_block(MoFEM::Interface &m_field, const std::string block_name, int dim)
Definition adjoint.cpp:2579
constexpr double young_modulus
Definition adjoint.cpp:73
int main()
constexpr double a
static const double eps
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
[Define dimension]
@ QUIET
@ ROW
#define CATCH_ERRORS
Catch errors.
@ MF_EXIST
FieldApproximationBase
approximation base
Definition definitions.h:58
@ LASTBASE
Definition definitions.h:69
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base nme:nme847.
Definition definitions.h:60
@ DEMKOWICZ_JACOBI_BASE
Definition definitions.h:66
#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()
@ H1
continuous field
Definition definitions.h:85
@ NOSPACE
Definition definitions.h:83
#define MYPCOMM_INDEX
default communicator number PCOMM
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_NOT_FOUND
Definition definitions.h:33
@ MOFEM_OPERATION_UNSUCCESSFUL
Definition definitions.h:34
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
PostProcEleByDim< SPACE_DIM >::PostProcEleDomain PostProcEleDomain
PostProcEleByDim< SPACE_DIM >::PostProcEleBdy PostProcEleBdy
@ F
auto integration_rule
PetscErrorCode DMMoFEMSetIsPartitioned(DM dm, PetscBool is_partitioned)
Definition DMMoFEM.cpp:1113
PetscErrorCode DMMoFEMCreateSubDM(DM subdm, DM dm, const char problem_name[])
Must be called by user to set Sub DM MoFEM data structures.
Definition DMMoFEM.cpp:215
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
Definition DMMoFEM.cpp:488
PetscErrorCode DMMoFEMSetSquareProblem(DM dm, PetscBool square_problem)
set squared problem
Definition DMMoFEM.cpp:450
PetscErrorCode DMMoFEMCreateMoFEM(DM dm, MoFEM::Interface *m_field_ptr, const char problem_name[], const MoFEM::BitRefLevel bit_level, const MoFEM::BitRefLevel bit_mask=MoFEM::BitRefLevel().set())
Must be called by user to set MoFEM data structures.
Definition DMMoFEM.cpp:114
PetscErrorCode DMoFEMPostProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:546
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:514
PetscErrorCode DMMoFEMAddSubFieldRow(DM dm, const char field_name[])
Definition DMMoFEM.cpp:238
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition DMMoFEM.cpp:43
MoFEMErrorCode DMRegister_MGViaApproxOrders(const char sname[])
Register DM for Multi-Grid via approximation orders.
PetscErrorCode DMoFEMLoopFiniteElements(DM dm, const char fe_name[], MoFEM::FEMethod *method, CacheTupleWeakPtr cache_ptr=CacheTupleSharedPtr())
Executes FEMethod for finite elements in DM.
Definition DMMoFEM.cpp:576
auto createDMVector(DM dm)
Get smart vector from DM.
Definition DMMoFEM.hpp:1102
PetscErrorCode DMMoFEMAddSubFieldCol(DM dm, const char field_name[])
Definition DMMoFEM.cpp:280
auto createDMMatrix(DM dm)
Get smart matrix from DM.
Definition DMMoFEM.hpp:1059
PetscErrorCode DMoFEMPreProcessFiniteElements(DM dm, MoFEM::FEMethod *method)
execute finite element method for each element in dm (problem)
Definition DMMoFEM.cpp:536
virtual MoFEMErrorCode add_ents_to_finite_element_by_dim(const EntityHandle entities, const int dim, const std::string name, const bool recursive=true)=0
add entities to finite element
virtual MoFEMErrorCode add_finite_element(const std::string &fe_name, enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
add finite element
virtual MoFEMErrorCode build_finite_elements(int verb=DEFAULT_VERBOSITY)=0
Build finite elements.
virtual MoFEMErrorCode modify_finite_element_add_field_col(const std::string &fe_name, const std::string name_row)=0
set field col which finite element use
virtual MoFEMErrorCode modify_finite_element_add_field_row(const std::string &fe_name, const std::string name_row)=0
set field row which finite element use
virtual MoFEMErrorCode modify_finite_element_add_field_data(const std::string &fe_name, const std::string name_field)=0
set finite element field data
virtual MoFEMErrorCode build_fields(int verb=DEFAULT_VERBOSITY)=0
virtual MoFEMErrorCode add_ents_to_field_by_dim(const Range &ents, const int dim, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
virtual MoFEMErrorCode set_field_order(const EntityHandle meshset, const EntityType type, const std::string &name, const ApproximationOrder order, int verb=DEFAULT_VERBOSITY)=0
Set order approximation of the entities in the field.
IntegrationType
Form integrator integration types.
AssemblyType
[Storage and set boundary conditions]
static LoggerType & setLog(const std::string channel)
Set ans resset chanel logger.
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_TAG(channel, tag)
Tag channel.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
virtual MoFEMErrorCode loop_dofs(const Problem *problem_ptr, const std::string &field_name, RowColData rc, DofMethod &method, int lower_rank, int upper_rank, int verb=DEFAULT_VERBOSITY)=0
Make a loop over dofs.
MoFEMErrorCode getCubitMeshsetPtr(const int ms_id, const CubitBCType cubit_bc_type, const CubitMeshSets **cubit_meshset_ptr) const
get cubit meshset
FTensor::Index< 'i', SPACE_DIM > i
const double v
phase velocity of light in medium (cm/ns)
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
MoFEMErrorCode opFactoryDomainLhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, boost::shared_ptr< HookeOps::CommonData > common_ptr, Sev sev)
Assemble domain LHS K factory (LHS first overload) Initializes and pushes operators to assemble the L...
Definition HookeOps.hpp:302
auto commonDataFactory(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, std::string block_name, Sev sev, double scale=1)
Definition HookeOps.hpp:208
MoFEMErrorCode opFactoryDomainRhs(MoFEM::Interface &m_field, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip, std::string field_name, boost::shared_ptr< HookeOps::CommonData > common_ptr, Sev sev, bool is_non_linear=false)
Factory function to create and push internal force operators for the domain RHS. (RHS first overload)...
Definition HookeOps.hpp:242
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto createKSP(MPI_Comm comm)
PetscErrorCode DMMoFEMSetDestroyProblem(DM dm, PetscBool destroy_problem)
Definition DMMoFEM.cpp:434
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
static const bool debug
PetscErrorCode PetscOptionsGetBool(PetscOptions *, const char pre[], const char name[], PetscBool *bval, PetscBool *set)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
PetscErrorCode PetscOptionsGetRealArray(PetscOptions *, const char pre[], const char name[], PetscReal dval[], PetscInt *nmax, PetscBool *set)
auto createVectorMPI(MPI_Comm comm, PetscInt n, PetscInt N)
Create MPI Vector.
static FTensor::Ddg< FTensor::PackPtr< T *, 1 >, Tensor_Dim01, Tensor_Dim23 > getFTensor4DdgFromMat(ublas::matrix< T, L, A > &data)
Get symmetric tensor rank 4 on first two and last indices from form data matrix.
auto getDMKspCtx(DM dm)
Get KSP context data structure used by DM.
Definition DMMoFEM.hpp:1116
FTensor::Tensor1< FTensor::PackPtr< T *, S >, Tensor_Dim > getFTensor1FromMat(ublas::matrix< T, L, A > &data)
Get tensor rank 1 (vector) form data matrix.
static MoFEMErrorCode invertTensor(FTensor::Tensor2< T1, DIM, DIM > &t, T2 &det, FTensor::Tensor2< T3, DIM, DIM > &inv_t)
FTensor::Tensor2< FTensor::PackPtr< double *, 1 >, Tensor_Dim1, Tensor_Dim2 > getFTensor2FromMat(MatrixDouble &data)
Get tensor rank 2 (matrix) form data matrix.
static auto getFTensor2SymmetricFromMat(ublas::matrix< T, L, A > &data)
Get symmetric tensor rank 2 (matrix) form data matrix.
FTensor::Tensor1< FTensor::PackPtr< double *, S >, DIM > getFTensor1FromPtr(double *ptr)
Make Tensor1 from pointer.
static auto determinantTensor(FTensor::Tensor2< T, DIM, DIM > &t)
Calculate the determinant of a tensor of rank DIM.
static auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
PetscErrorCode PetscOptionsGetEList(PetscOptions *, const char pre[], const char name[], const char *const *list, PetscInt next, PetscInt *value, PetscBool *set)
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
PetscErrorCode TaoSetObjectiveAndGradient(Tao tao, Vec x, PetscReal *f, Vec g, void *ctx)
Sets the objective function value and gradient for a TAO optimization solver.
Definition TaoCtx.cpp:178
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
MoFEMErrorCode VecSetValues(Vec V, const EntitiesFieldData::EntData &data, const double *ptr, InsertMode iora)
Assemble PETSc vector.
auto createTao(MPI_Comm comm)
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
#define EXECUTABLE_DIMENSION
Definition plastic.cpp:13
PetscBool do_eval_field
Evaluate field.
Definition plastic.cpp:119
ElementsAndOps< SPACE_DIM >::SideEle SideEle
Definition plastic.cpp:61
constexpr auto field_name
static constexpr int approx_order
OpBaseImpl< PETSC, EdgeEleOp > OpBase
Definition radiation.cpp:29
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, SPACE_DIM > OpMass
[Only used with Hooke equation (linear material model)]
Definition seepage.cpp:55
constexpr double g
FTensor::Index< 'm', 3 > m
[Define entities]
Definition elastic.cpp:37
[Example]
Definition plastic.cpp:216
MoFEMErrorCode boundaryCondition()
MoFEMErrorCode assembleSystem()
MoFEMErrorCode readMesh()
SmartPetscObj< KSP > kspElastic
Definition adjoint.cpp:155
std::vector< SmartPetscObj< Vec > > modeVecs
Definition adjoint.cpp:158
FieldApproximationBase base
Definition plot_base.cpp:68
std::vector< std::array< double, 3 > > modeCentroids
Definition adjoint.cpp:159
MoFEMErrorCode topologyModes()
[Boundary condition]
Definition adjoint.cpp:563
SmartPetscObj< Vec > initialGeometry
Definition adjoint.cpp:161
int fieldOrder
Definition adjoint.cpp:153
Example(MoFEM::Interface &m_field)
Definition adjoint.cpp:130
SmartPetscObj< Mat > M
MoFEMErrorCode runProblem()
MoFEMErrorCode calculateGradient(PetscReal *objective_function_value, Vec objective_function_gradient, Vec adjoint_vector)
Definition adjoint.cpp:1716
MoFEMErrorCode setupAdJoint()
[Set up problem]
Definition adjoint.cpp:439
MoFEM::Interface & mField
Definition plastic.cpp:226
std::vector< std::array< double, 6 > > modeBBoxes
Definition adjoint.cpp:160
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Definition adjoint.cpp:157
SmartPetscObj< DM > adjointDM
Definition adjoint.cpp:156
MoFEMErrorCode setupProblem()
MoFEMErrorCode postprocessElastic(int iter, SmartPetscObj< Vec > adjoint_vector=nullptr)
[Solve]
Definition adjoint.cpp:1164
MoFEMErrorCode solveElastic()
[Push operators to pipeline]
Definition adjoint.cpp:1036
boost::shared_ptr< MatrixDouble > vectorFieldPtr
Definition elastic.cpp:87
Add operators pushing bases from local to physical configuration.
Simple interface for fast problem set-up.
Definition BcManager.hpp:29
Managing BitRefLevels.
MoFEMErrorCode synchroniseEntities(Range &ent, std::map< int, Range > *received_ents, int verb=DEFAULT_VERBOSITY)
synchronize entity range on processors (collective)
virtual moab::Interface & get_moab()=0
virtual MoFEMErrorCode build_adjacencies(const Range &ents, int verb=DEFAULT_VERBOSITY)=0
build adjacencies
virtual MoFEMErrorCode add_field(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)=0
Add field.
virtual MPI_Comm & get_comm() const =0
virtual int get_comm_rank() const =0
Core (interface) class.
Definition Core.hpp:82
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:72
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:118
Deprecated interface functions.
Definition of the displacement bc data structure.
Definition BCData.hpp:72
Data on single entity (This is passed as argument to DataOperator::doWork)
FTensor::Tensor1< FTensor::PackPtr< double *, Tensor_Dim >, Tensor_Dim > getFTensor1DiffN(const FieldApproximationBase base)
Get derivatives of base functions.
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
const VectorInt & getIndices() const
Get global indices of dofs on entity.
Class (Function) to enforce essential constrains on the left hand side diagonal.
Definition Essential.hpp:33
Class (Function) to enforce essential constrains on the right hand side diagonal.
Definition Essential.hpp:41
Class (Function) to enforce essential constrains.
Definition Essential.hpp:25
Basic algebra on fields.
Definition FieldBlas.hpp:21
MoFEMErrorCode fieldLambdaOnValues(OneFieldFunctionOnValues lambda, const std::string field_name, Range *ents_ptr=nullptr)
field lambda
Definition FieldBlas.cpp:21
Field evaluator interface.
static boost::shared_ptr< SinkType > createSink(boost::shared_ptr< std::ostream > stream_ptr, std::string comm_filter)
Create a sink object.
static boost::shared_ptr< std::ostream > getStrmWorld()
Get the strm world object.
static boost::shared_ptr< std::ostream > getStrmSync()
Get the strm sync object.
Interface for managing meshsets containing materials and boundary conditions.
Assembly methods.
Definition Natural.hpp:65
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Get values at integration pts for tensor field rank 1, i.e. vector field.
Element used to execute operators on side of the element.
Post post-proc data at points from hash maps.
PipelineManager interface.
MoFEMErrorCode setDomainRhsIntegrationRule(RuleHookFun rule)
Problem manager is used to build and partition problems.
Projection of edge entities with one mid-node on hierarchical basis.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode getOptions()
get options
Definition Simple.cpp:180
MoFEMErrorCode getDM(DM *dm)
Get DM.
Definition Simple.cpp:800
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Vector manager is used to create vectors \mofem_vectors.
MoFEMErrorCode objectiveGradientStrainImpl(np::ndarray coords, np::ndarray u, np::ndarray stress, np::ndarray strain, np::ndarray &o)
Definition adjoint.cpp:2466
MoFEMErrorCode numberOfModes(int block_id, int &modes)
Definition adjoint.cpp:2509
MoFEMErrorCode blockModesImpl(int block_id, np::ndarray coords, np::ndarray centroid, np::ndarray bbodx, np::ndarray &o_ptr)
Definition adjoint.cpp:2524
MoFEMErrorCode evalObjectiveGradientStrain(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr)
Definition adjoint.cpp:2320
bp::object objectiveGradientStress
Definition adjoint.cpp:2130
ObjectiveFunctionDataImpl()=default
MoFEMErrorCode initPython(const std::string py_file)
Definition adjoint.cpp:2192
MoFEMErrorCode blockModes(int block_id, MatrixDouble &coords, std::array< double, 3 > &centroid, std::array< double, 6 > &bbodx, MatrixDouble &o_ptr)
Definition adjoint.cpp:2391
bp::object objectiveGradientStrain
Definition adjoint.cpp:2131
MoFEMErrorCode evalObjectiveGradientU(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr)
Definition adjoint.cpp:2355
virtual ~ObjectiveFunctionDataImpl()=default
MoFEMErrorCode evalObjectiveGradientStress(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr)
Definition adjoint.cpp:2285
MoFEMErrorCode evalObjectiveFunction(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< VectorDouble > o_ptr)
Definition adjoint.cpp:2251
MatrixDouble copyToFull(MatrixDouble &s)
Definition adjoint.cpp:2216
np::ndarray convertToNumPy(std::vector< double > &data, int rows, int nb_gauss_pts)
Converts a std::vector<double> to a NumPy ndarray.
Definition adjoint.cpp:2563
MoFEMErrorCode objectiveGradientUImpl(np::ndarray coords, np::ndarray u, np::ndarray stress, np::ndarray strain, np::ndarray &o)
Definition adjoint.cpp:2488
MoFEMErrorCode objectiveGradientStressImpl(np::ndarray coords, np::ndarray u, np::ndarray stress, np::ndarray strain, np::ndarray &o)
Definition adjoint.cpp:2444
void copyToSymmetric(double *ptr, MatrixDouble &s)
Definition adjoint.cpp:2231
MoFEMErrorCode objectiveFunctionImpl(np::ndarray coords, np::ndarray u, np::ndarray stress, np::ndarray strain, np::ndarray &o)
Definition adjoint.cpp:2423
virtual ~ObjectiveFunctionData()=default
virtual MoFEMErrorCode evalObjectiveGradientStress(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr)=0
virtual MoFEMErrorCode evalObjectiveGradientStrain(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< MatrixDouble > o_ptr)=0
virtual MoFEMErrorCode numberOfModes(int block_id, int &modes)=0
virtual MoFEMErrorCode blockModes(int block_id, MatrixDouble &coords, std::array< double, 3 > &centroid, std::array< double, 6 > &bbox, MatrixDouble &o_ptr)=0
virtual MoFEMErrorCode evalObjectiveFunction(MatrixDouble &coords, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< MatrixDouble > stress_ptr, boost::shared_ptr< MatrixDouble > strain_ptr, boost::shared_ptr< VectorDouble > o_ptr)=0
OpAdJointGradTimesSymTensor(const std::string field_name, boost::shared_ptr< HookeOps::CommonData > comm_ptr, boost::shared_ptr< MatrixDouble > jac, boost::shared_ptr< MatrixDouble > diff_jac, boost::shared_ptr< VectorDouble > cof_vals)
Definition adjoint.cpp:1425
boost::shared_ptr< MatrixDouble > dGradPtr
Definition adjoint.cpp:1709
boost::shared_ptr< double > globObjectiveGradPtr
Definition adjoint.cpp:1713
boost::shared_ptr< ObjectiveFunctionData > pythonPtr
Definition adjoint.cpp:1704
boost::shared_ptr< double > globObjectivePtr
Definition adjoint.cpp:1712
ForcesAndSourcesCore::UserDataOperator OP
Definition adjoint.cpp:1572
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Definition adjoint.cpp:1587
boost::shared_ptr< HookeOps::CommonData > commPtr
Definition adjoint.cpp:1705
boost::shared_ptr< VectorDouble > cofVals
Definition adjoint.cpp:1708
boost::shared_ptr< MatrixDouble > uPtr
Definition adjoint.cpp:1710
OpAdJointObjective(boost::shared_ptr< ObjectiveFunctionData > python_ptr, boost::shared_ptr< HookeOps::CommonData > comm_ptr, boost::shared_ptr< MatrixDouble > jac_ptr, boost::shared_ptr< MatrixDouble > diff_jac, boost::shared_ptr< VectorDouble > cof_vals, boost::shared_ptr< MatrixDouble > d_grad_ptr, boost::shared_ptr< MatrixDouble > u_ptr, boost::shared_ptr< double > glob_objective_ptr, boost::shared_ptr< double > glob_objective_grad_ptr)
Definition adjoint.cpp:1573
boost::shared_ptr< MatrixDouble > diffJacPtr
Definition adjoint.cpp:1707
boost::shared_ptr< MatrixDouble > jacPtr
Definition adjoint.cpp:1706
OpAdJointTestOp(const std::string field_name, boost::shared_ptr< HookeOps::CommonData > comm_ptr)
Definition adjoint.cpp:1363
auto save_range