v0.16.3
Loading...
Searching...
No Matches
arc_length_interface.cpp
Go to the documentation of this file.
1/**
2 * \file arc_length_interface.cpp
3 * \example mofem/tutorials/cor-12_cohesive_interface/arc_length_interface.cpp
4 * \brief Example of arc-length with a cohesive interface element
5
6 * \todo Make it work with multi-grid and distributed mesh
7
8 * \todo Make more clever step adaptation
9 */
10
11#include <MoFEM.hpp>
12#include <algorithm>
13#include <limits>
14using namespace MoFEM;
15
16constexpr int SPACE_DIM = 3;
18using DomainEleOp = DomainEle::UserDataOperator;
22
23struct BoundaryBCs {};
24
25#include <ArcLengthTools.hpp>
27#include <HookeOps.hpp>
30
31using namespace boost::numeric;
32
33static char help[] = "\
34 -my_file mesh file name\n\
35 -my_sr reduction of step size\n\
36 -my_its_d desired number of steps\n\
37 -my_ms maximal number of steps\n\
38 -gamma arc-length step adaptation exponent\n\
39 -min_arc_length_step minimum arc-length step\n\
40 -max_arc_length_step maximum arc-length step\n\
41 -field_eval_coords x,y,z coordinates where displacement and stress are evaluated\n\n";
42
43namespace CohesiveElement {
44
46
47 boost::shared_ptr<ArcLengthCtx> arcPtr;
48
49 AssembleRhsVectors(boost::shared_ptr<ArcLengthCtx> &arc_ptr)
50 : arcPtr(arc_ptr) {}
51
54
55 switch (snes_ctx) {
56 case CTX_SNESNONE: {
57 } break;
59 CHKERR VecZeroEntries(snes_f);
60 CHKERR VecGhostUpdateBegin(snes_f, INSERT_VALUES, SCATTER_FORWARD);
61 CHKERR VecGhostUpdateEnd(snes_f, INSERT_VALUES, SCATTER_FORWARD);
62 } break;
63 default:
64 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "not implemented");
65 }
66
68 }
69
72 switch (snes_ctx) {
73 case CTX_SNESNONE: {
74 } break;
76 if (snes_f) {
77 CHKERR VecGhostUpdateBegin(snes_f, ADD_VALUES, SCATTER_REVERSE);
78 CHKERR VecGhostUpdateEnd(snes_f, ADD_VALUES, SCATTER_REVERSE);
79 CHKERR VecAssemblyBegin(snes_f);
80 CHKERR VecAssemblyEnd(snes_f);
81 // Add the complete load tangent, including Neumann forces.
82 CHKERR VecAXPY(snes_f, arcPtr->getFieldData(), arcPtr->F_lambda);
83 MOFEM_LOG_C("ARC_LENGTH", Sev::inform, "\tlambda = %6.4e",
84 arcPtr->getFieldData());
85 // snes_f norm
86 double fnorm;
87 CHKERR VecNorm(snes_f, NORM_2, &fnorm);
88 MOFEM_LOG_C("ARC_LENGTH", Sev::inform, "\tpre-essential fnorm = %6.4e",
89 fnorm);
90 }
91 } break;
92 default:
93 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "not implemented");
94 }
95
97 }
98};
99
100} // namespace CohesiveElement
101
102using namespace CohesiveElement;
103
105
106 ArcLengthInterfaceExample(moab::Interface &moab) : mOab(moab) {}
107
109
110protected:
111 moab::Interface &mOab;
112 boost::shared_ptr<MoFEM::Core> corePtr;
114 double *stepSizePtr = nullptr;
115 int *stepPtr = nullptr;
116
117 PetscScalar stepSizeReduction = 1.;
118 PetscInt maxSteps = 5;
119 PetscInt itsD = 6;
120 PetscInt order = 2;
121 const std::string naturalBcFeName = "NATURAL_BC";
122
125 Vec dRaw = nullptr;
129
130 boost::ptr_vector<CohesiveInterfaceElement::PhysicalEquation>
132 boost::shared_ptr<ArcLengthCtx> arcCtx;
133 boost::shared_ptr<ArcLengthIntElemFEMethod> arcMethodPtr;
134 boost::shared_ptr<ArcLengthSnesCtx> snesCtxPtr;
135 boost::shared_ptr<AssembleRhsVectors> prePostProcFePtr;
136 boost::shared_ptr<CohesiveInterfaceElement> cohesiveElementsPtr;
137 boost::shared_ptr<DomainEle> elasticRhsFe;
138 boost::shared_ptr<DomainEle> elasticLhsFe;
139 boost::shared_ptr<BoundaryEle> naturalBcFe;
140 boost::shared_ptr<PostProcEle> postProcPtr;
141 boost::scoped_ptr<ArcLengthMatShell> matCtx;
142 boost::scoped_ptr<PCArcLengthCtx> pcCtx;
143
144 std::array<double, SPACE_DIM> fieldEvalCoords{0., 0., 0.};
145 PetscBool doEvalField = PETSC_FALSE;
146 boost::shared_ptr<FieldEvaluatorInterface::SetPtsData> fieldEvalData;
147 boost::shared_ptr<MatrixDouble> fieldEvalDispPtr;
148 boost::shared_ptr<MatrixDouble> fieldEvalStressPtr;
149
150 double gamma = 0.5;
151 double reduction = 1.;
152
160 MoFEMErrorCode evaluateFieldAtPoint(const int load_step);
161 MoFEMErrorCode evaluateReactions(const int load_step);
162};
163
164//! [Run problem]
176//! [Run problem]
177
178//! [Read mesh]
181
183
184 // Read the mesh file before constructing MoFEM::Core so that the MOAB
185 // database can be populated first. JsonConfigManager::setMeshFileFromJson()
186 // maps the primary JSON mesh to -file_name.
187 PetscBool flg = PETSC_TRUE;
188 char mesh_file_name[PETSC_MAX_PATH_LEN] = "";
189 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR, "-my_file",
190 mesh_file_name, sizeof(mesh_file_name), &flg);
191 if (flg != PETSC_TRUE) {
192 CHKERR PetscOptionsGetString(PETSC_NULLPTR, PETSC_NULLPTR, "-file_name",
193 mesh_file_name, sizeof(mesh_file_name), &flg);
194 if (flg != PETSC_TRUE)
195 SETERRQ(PETSC_COMM_SELF, MOFEM_INVALID_DATA,
196 "*** ERROR -my_file or -file_name (MESH FILE NEEDED)");
197 }
198
199 // Read mesh to MOAB
200 const char *option;
201 option = "";
202 CHKERR mOab.load_file(mesh_file_name, 0, option);
203
204 // Data stored on mesh for restart
205 Tag th_step_size, th_step;
206 double def_step_size = 1;
207 rval = mOab.tag_get_handle("_STEPSIZE", 1, MB_TYPE_DOUBLE, th_step_size,
208 MB_TAG_CREAT | MB_TAG_MESH, &def_step_size);
209 if (rval == MB_ALREADY_ALLOCATED)
210 rval = MB_SUCCESS;
211 CHKERR rval;
212 int def_step = 1;
213 rval = mOab.tag_get_handle("_STEP", 1, MB_TYPE_INTEGER, th_step,
214 MB_TAG_CREAT | MB_TAG_MESH, &def_step);
215 if (rval == MB_ALREADY_ALLOCATED)
216 rval = MB_SUCCESS;
217 CHKERR rval;
218 const void *tag_data_step_size[1];
219 EntityHandle root = 0;
220 CHKERR mOab.tag_get_by_ptr(th_step_size, &root, 1, tag_data_step_size);
221 double &step_size = *(double *)tag_data_step_size[0];
222 const void *tag_data_step[1];
223 CHKERR mOab.tag_get_by_ptr(th_step, &root, 1, tag_data_step);
224 int &step = *(int *)tag_data_step[0];
225 // end of data stored for restart
226 MOFEM_LOG_C("ARC_LENGTH", Sev::inform, "Start step %d and step_size = %6.4e",
227 step, step_size);
228
229 stepSizePtr = (double *)tag_data_step_size[0];
230 stepPtr = (int *)tag_data_step[0];
231
232 // Create MoFEM database after loading the mesh. This preserves loading of
233 // JSON options by the Core constructor.
234 corePtr = boost::make_shared<MoFEM::Core>(mOab);
235 mField = corePtr.get();
236
238}
239//! [Read mesh]
240
241//! [Set up problem]
244 auto &m_field = *mField;
245 auto &step = *stepPtr;
246 PetscBool flg = PETSC_FALSE;
247
248 // Constructing MoFEM::Core loads -json_config and inserts its "petsc" and
249 // "mofem" sections into the PETSc options database. Read application
250 // controls only after that point so they can be supplied by JSON.
251 CHKERR PetscOptionsGetReal(PETSC_NULLPTR, PETSC_NULLPTR, "-my_sr",
252 &stepSizeReduction, &flg);
253 if (flg != PETSC_TRUE) {
255 }
256
257 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, PETSC_NULLPTR, "-my_ms", &maxSteps,
258 &flg);
259 if (flg != PETSC_TRUE) {
260 maxSteps = 5;
261 }
262
263 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, PETSC_NULLPTR, "-my_its_d", &itsD,
264 &flg);
265 if (flg != PETSC_TRUE) {
266 itsD = 6;
267 }
268
269 CHKERR PetscOptionsGetInt(PETSC_NULLPTR, PETSC_NULLPTR, "-my_order", &order,
270 &flg);
271 if (flg != PETSC_TRUE) {
272 order = 2;
273 }
274
275 MeshsetsManager *meshsets_manager_ptr;
276 CHKERR m_field.getInterface(meshsets_manager_ptr);
277 CHKERR meshsets_manager_ptr->setMeshsetFromFile();
278
279 PrismInterface *interface_ptr;
280 CHKERR m_field.getInterface(interface_ptr);
281
282 Tag th_my_ref_level;
283 BitRefLevel def_bit_level = 0;
284 CHKERR m_field.get_moab().tag_get_handle(
285 "_MY_REFINEMENT_LEVEL", sizeof(BitRefLevel), MB_TYPE_OPAQUE,
286 th_my_ref_level, MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_BYTES,
287 &def_bit_level);
288 const EntityHandle root_meshset = m_field.get_moab().get_root_set();
289 BitRefLevel *ptr_bit_level0;
290 CHKERR m_field.get_moab().tag_get_by_ptr(th_my_ref_level, &root_meshset, 1,
291 (const void **)&ptr_bit_level0);
292 BitRefLevel &bit_level0 = *ptr_bit_level0;
293 BitRefLevel problem_bit_level = bit_level0;
294
295 if (step == 1) {
296
297 // ref meshset ref level 0
298 CHKERR m_field.getInterface<BitRefManager>()->setBitRefLevelByDim(
299 0, 3, BitRefLevel().set(0));
300
301 std::vector<BitRefLevel> bit_levels;
302 bit_levels.push_back(BitRefLevel().set(0));
303
304 int ll = 1;
305
306 auto split_interface = [&](const EntityHandle cubit_meshset,
307 const int meshset_id) -> MoFEMErrorCode {
309 MOFEM_LOG_C("ARC_LENGTH", Sev::inform, "Insert Interface %d", meshset_id);
310 {
311 // get tet entities form back bit_level
312 EntityHandle ref_level_meshset = 0;
313 CHKERR mOab.create_meshset(MESHSET_SET, ref_level_meshset);
314 CHKERR m_field.getInterface<BitRefManager>()
315 ->getEntitiesByTypeAndRefLevel(bit_levels.back(),
316 BitRefLevel().set(), MBTET,
317 ref_level_meshset);
319 ->getEntitiesByTypeAndRefLevel(bit_levels.back(),
320 BitRefLevel().set(), MBPRISM,
321 ref_level_meshset);
322 Range ref_level_tets;
323 CHKERR mOab.get_entities_by_handle(ref_level_meshset, ref_level_tets,
324 true);
325 // get faces and test to split
326 CHKERR interface_ptr->getSides(cubit_meshset, bit_levels.back(), true,
327 0);
328 // set new bit level
329 bit_levels.push_back(BitRefLevel().set(ll++));
330 // split faces and
331 CHKERR interface_ptr->splitSides(ref_level_meshset, bit_levels.back(),
332 cubit_meshset, true, true, 0);
333 // clean meshsets
334 CHKERR mOab.delete_entities(&ref_level_meshset, 1);
335 }
336 // Update cubit meshsets
337 for (_IT_CUBITMESHSETS_FOR_LOOP_(m_field, ciit)) {
338 EntityHandle cubit_meshset = ciit->meshset;
339 CHKERR m_field.getInterface<BitRefManager>()
340 ->updateMeshsetByEntitiesChildren(cubit_meshset, bit_levels.back(),
341 cubit_meshset, MBMAXTYPE, true);
342 }
344 };
345
346 // Prefer Cubit INTERFACESET side sets. Use MAT_INTERF blocksets only as
347 // a fallback for meshes configured through JsonConfigManager, since a
348 // legacy mesh can store the same interface under both set types.
349 std::set<int> split_interface_ids;
350 bool split_from_sideset = false;
352 m_field, SIDESET | INTERFACESET, cit)) {
353 if (split_interface_ids.insert(cit->getMeshsetId()).second) {
354 CHKERR split_interface(cit->getMeshset(), cit->getMeshsetId());
355 split_from_sideset = true;
356 }
357 }
358 if (!split_from_sideset) {
359 const std::string block_name = "MAT_INTERF";
360 for (auto m : m_field.getInterface<MeshsetsManager>()->getCubitMeshsetPtr(
361 std::regex((boost::format("%s(.*)") % block_name).str()))) {
362 if (split_interface_ids.insert(m->getMeshsetId()).second)
363 CHKERR split_interface(m->getMeshset(), m->getMeshsetId());
364 }
365 }
366
367 bit_level0 = bit_levels.back();
368 problem_bit_level = bit_level0;
369
370 /***/
371 // Define problem
372
373 // Fields
374 CHKERR m_field.add_field("DISPLACEMENT", H1, AINSWORTH_LEGENDRE_BASE, 3);
375 CHKERR
376 m_field.add_field("GEOMETRY", H1, AINSWORTH_LEGENDRE_BASE, 3);
377
378 CHKERR m_field.add_field("LAMBDA", NOFIELD, NOBASE, 1);
379
380 // Field for ArcLength
381 CHKERR
382 m_field.add_field("X0_DISPLACEMENT", H1, AINSWORTH_LEGENDRE_BASE, 3);
383
384 // FE
385 CHKERR m_field.add_finite_element("ELASTIC");
386
387 // Define rows/cols and element data
388 CHKERR m_field.modify_finite_element_add_field_row("ELASTIC",
389 "DISPLACEMENT");
390 CHKERR m_field.modify_finite_element_add_field_col("ELASTIC",
391 "DISPLACEMENT");
392 CHKERR m_field.modify_finite_element_add_field_data("ELASTIC",
393 "DISPLACEMENT");
394 CHKERR
395 m_field.modify_finite_element_add_field_data("ELASTIC", "GEOMETRY");
396 CHKERR m_field.modify_finite_element_add_field_row("ELASTIC", "LAMBDA");
397 CHKERR m_field.modify_finite_element_add_field_col("ELASTIC", "LAMBDA");
398 // this is for paremtis
399 CHKERR m_field.modify_finite_element_add_field_data("ELASTIC", "LAMBDA");
400
401 // FE Interface
402 CHKERR m_field.add_finite_element("INTERFACE");
403 CHKERR m_field.modify_finite_element_add_field_row("INTERFACE",
404 "DISPLACEMENT");
405 CHKERR m_field.modify_finite_element_add_field_col("INTERFACE",
406 "DISPLACEMENT");
407 CHKERR m_field.modify_finite_element_add_field_data("INTERFACE",
408 "DISPLACEMENT");
409 CHKERR
410 m_field.modify_finite_element_add_field_data("INTERFACE", "GEOMETRY");
411
412 // FE ArcLength
413 CHKERR m_field.add_finite_element("ARC_LENGTH");
414
415 // Define rows/cols and element data
416 CHKERR m_field.modify_finite_element_add_field_row("ARC_LENGTH", "LAMBDA");
417 CHKERR m_field.modify_finite_element_add_field_col("ARC_LENGTH", "LAMBDA");
418
419 // elem data
420 CHKERR
421 m_field.modify_finite_element_add_field_data("ARC_LENGTH", "LAMBDA");
422
423 // define problems
424 CHKERR m_field.add_problem("ELASTIC_MECHANICS");
425
426 // set finite elements for problem
427 CHKERR m_field.modify_problem_add_finite_element("ELASTIC_MECHANICS",
428 "ELASTIC");
429 CHKERR m_field.modify_problem_add_finite_element("ELASTIC_MECHANICS",
430 "INTERFACE");
431 CHKERR m_field.modify_problem_add_finite_element("ELASTIC_MECHANICS",
432 "ARC_LENGTH");
433 // set refinement level for problem
434 CHKERR m_field.modify_problem_ref_level_add_bit("ELASTIC_MECHANICS",
435 problem_bit_level);
436
437 /***/
438 // Declare problem
439
440 // add entities (by tets) to the field
441 CHKERR m_field.add_ents_to_field_by_type(0, MBTET, "DISPLACEMENT");
442 CHKERR m_field.add_ents_to_field_by_type(0, MBTET, "X0_DISPLACEMENT");
443 CHKERR m_field.add_ents_to_field_by_type(0, MBTET, "GEOMETRY");
444
445 // add finite elements entities
446 CHKERR m_field.add_ents_to_finite_element_by_bit_ref(
447 problem_bit_level, BitRefLevel().set(), "ELASTIC", MBTET);
448 CHKERR m_field.add_ents_to_finite_element_by_bit_ref(
449 problem_bit_level, BitRefLevel().set(), "INTERFACE", MBPRISM);
450
451 // Setting up LAMBDA field and ARC_LENGTH interface
452 {
453 // Add dummy no-field vertex
454 EntityHandle no_field_vertex;
455 {
456 const double coords[] = {0, 0, 0};
457 CHKERR m_field.get_moab().create_vertex(coords, no_field_vertex);
458 Range range_no_field_vertex;
459 range_no_field_vertex.insert(no_field_vertex);
460 CHKERR m_field.getInterface<BitRefManager>()->setBitRefLevel(
461 range_no_field_vertex, BitRefLevel().set());
462
463 EntityHandle lambda_meshset = m_field.get_field_meshset("LAMBDA");
464 CHKERR m_field.get_moab().add_entities(lambda_meshset,
465 range_no_field_vertex);
466 }
467 // this entity will carray data for this finite element
468 EntityHandle meshset_fe_arc_length;
469 {
470 CHKERR mOab.create_meshset(MESHSET_SET, meshset_fe_arc_length);
471 CHKERR mOab.add_entities(meshset_fe_arc_length, &no_field_vertex, 1);
472 CHKERR m_field.getInterface<BitRefManager>()->setBitLevelToMeshset(
473 meshset_fe_arc_length, BitRefLevel().set());
474 }
475 // finally add created meshset to the ARC_LENGTH finite element
476 CHKERR m_field.add_ents_to_finite_element_by_MESHSET(
477 meshset_fe_arc_length, "ARC_LENGTH", false);
478 }
479
480 // set app. order
481 // see Hierarchic Finite Element Bases on Unstructured Tetrahedral Meshes
482 // (Mark Ainsworth & Joe Coyle)
483 CHKERR m_field.set_field_order(0, MBTET, "DISPLACEMENT", order);
484 CHKERR m_field.set_field_order(0, MBTRI, "DISPLACEMENT", order);
485 CHKERR m_field.set_field_order(0, MBEDGE, "DISPLACEMENT", order);
486 CHKERR m_field.set_field_order(0, MBVERTEX, "DISPLACEMENT", 1);
487
488 CHKERR m_field.set_field_order(0, MBTET, "X0_DISPLACEMENT", order);
489 CHKERR m_field.set_field_order(0, MBTRI, "X0_DISPLACEMENT", order);
490 CHKERR m_field.set_field_order(0, MBEDGE, "X0_DISPLACEMENT", order);
491 CHKERR m_field.set_field_order(0, MBVERTEX, "X0_DISPLACEMENT", 1);
492
493 CHKERR m_field.set_field_order(0, MBTET, "GEOMETRY", 2);
494 CHKERR m_field.set_field_order(0, MBTRI, "GEOMETRY", 2);
495 CHKERR m_field.set_field_order(0, MBEDGE, "GEOMETRY", 2);
496 CHKERR m_field.set_field_order(0, MBVERTEX, "GEOMETRY", 1);
497 }
498
499 if (!m_field.check_finite_element(naturalBcFeName)) {
500 CHKERR m_field.add_finite_element(naturalBcFeName);
501 CHKERR m_field.modify_finite_element_add_field_row(naturalBcFeName,
502 "DISPLACEMENT");
503 CHKERR m_field.modify_finite_element_add_field_col(naturalBcFeName,
504 "DISPLACEMENT");
505 CHKERR m_field.modify_finite_element_add_field_data(naturalBcFeName,
506 "DISPLACEMENT");
507 CHKERR m_field.modify_finite_element_add_field_data(naturalBcFeName,
508 "GEOMETRY");
509 CHKERR m_field.modify_problem_add_finite_element("ELASTIC_MECHANICS",
511
512 Range natural_bc_faces;
513 auto meshsets_manager = m_field.getInterface<MeshsetsManager>();
514 for (auto m : meshsets_manager->getCubitMeshsetPtr(NODESET | FORCESET)) {
515 CHKERR mOab.get_entities_by_type(m->getMeshset(), MBTRI, natural_bc_faces,
516 true);
517 }
518 for (auto m : meshsets_manager->getCubitMeshsetPtr(SIDESET | PRESSURESET)) {
519 CHKERR mOab.get_entities_by_type(m->getMeshset(), MBTRI, natural_bc_faces,
520 true);
521 }
522 for (auto m : meshsets_manager->getCubitMeshsetPtr(
523 std::regex("(FORCE|PRESSURE)(.*)"))) {
524 CHKERR mOab.get_entities_by_type(m->getMeshset(), MBTRI, natural_bc_faces,
525 true);
526 }
527 CHKERR m_field.add_ents_to_finite_element_by_type(natural_bc_faces, MBTRI,
529 }
530
531 /****/
532 // build database
533
534 // build field
535 CHKERR m_field.build_fields();
536 Projection10NodeCoordsOnField ent_method_material(m_field, "GEOMETRY");
537 CHKERR m_field.loop_dofs("GEOMETRY", ent_method_material);
538
539 // build finite elemnts
540 CHKERR m_field.build_finite_elements();
541
542 // build adjacencies
543 CHKERR m_field.build_adjacencies(problem_bit_level);
544
545 /****/
546 ProblemsManager *prb_mng_ptr;
547 CHKERR m_field.getInterface(prb_mng_ptr);
548 // build problem
549 CHKERR prb_mng_ptr->buildProblem("ELASTIC_MECHANICS", true);
550 // partition
551 CHKERR prb_mng_ptr->partitionProblem("ELASTIC_MECHANICS");
552 CHKERR prb_mng_ptr->partitionFiniteElements("ELASTIC_MECHANICS", false, 0,
553 m_field.get_comm_size());
554 // what are ghost nodes, see Petsc Manual
555 CHKERR prb_mng_ptr->partitionGhostDofs("ELASTIC_MECHANICS");
556
558}
559//! [Set up problem]
560
561//! [Boundary condition]
564 auto &m_field = *mField;
565
566 auto bc_mng = m_field.getInterface<BcManager>();
568 "ELASTIC_MECHANICS", "DISPLACEMENT");
569
570 // print bcs
571 MeshsetsManager *mmanager_ptr;
572 CHKERR m_field.getInterface(mmanager_ptr);
573 CHKERR mmanager_ptr->printDisplacementSet();
574 CHKERR mmanager_ptr->printForceSet();
575 // print block sets with materials
576 CHKERR mmanager_ptr->printMaterialsSet();
577
579}
580//! [Boundary condition]
581
582//! [Assemble system]
585 auto &m_field = *mField;
586 auto &step = *stepPtr;
587 auto &step_size = *stepSizePtr;
588
589 // create matrices
590 CHKERR m_field.getInterface<VecManager>()->vecCreateGhost("ELASTIC_MECHANICS",
591 COL, f);
593 dRaw = d;
594 CHKERR m_field.getInterface<MatrixManager>()
595 ->createMPIAIJWithArrays<PetscGlobalIdx_mi_tag>("ELASTIC_MECHANICS", aij);
596
597 auto meshsets_manager = m_field.getInterface<MeshsetsManager>();
598 const std::string interface_block_name = "MAT_INTERF";
599 for (auto m : meshsets_manager->getCubitMeshsetPtr(std::regex(
600 (boost::format("%s(.*)") % interface_block_name).str()))) {
601 MOFEM_LOG("ARC_LENGTH", Sev::inform) << *m;
602 Mat_Interf mydata;
603 CHKERR m->getAttributeDataStructure(mydata);
604 MOFEM_LOG("ARC_LENGTH", Sev::inform) << mydata;
605
606 interfaceMaterials.push_back(
608 interfaceMaterials.back().h = 1;
609 interfaceMaterials.back().youngModulus = mydata.data.alpha;
610 interfaceMaterials.back().beta = mydata.data.beta;
611 interfaceMaterials.back().ft = mydata.data.ft;
612 interfaceMaterials.back().Gf = mydata.data.Gf;
613
614 EntityHandle meshset = m->getMeshset();
615 Range tris;
616 CHKERR mOab.get_entities_by_type(meshset, MBTRI, tris, true);
617 Range ents3d;
618 CHKERR mOab.get_adjacencies(tris, 3, false, ents3d, moab::Interface::UNION);
619 interfaceMaterials.back().pRisms = ents3d.subset_by_type(MBPRISM);
620 }
621
622 arcCtx = boost::make_shared<ArcLengthCtx>(m_field, "ELASTIC_MECHANICS");
624 boost::make_shared<ArcLengthIntElemFEMethod>(m_field.get_moab(), arcCtx);
625 snesCtxPtr = boost::make_shared<ArcLengthSnesCtx>(
626 m_field, "ELASTIC_MECHANICS", arcCtx);
627 prePostProcFePtr = boost::make_shared<AssembleRhsVectors>(arcCtx);
628 auto &snes_ctx = *snesCtxPtr;
629 auto &pre_post_proc_fe = *prePostProcFePtr;
630
631 auto essential_pre_proc_zero_rhs = boost::make_shared<FEMethod>();
632 auto essential_pre_proc_lhs = boost::make_shared<FEMethod>();
633 auto essential_post_proc_rhs = boost::make_shared<FEMethod>();
634 auto essential_post_proc_lhs = boost::make_shared<FEMethod>();
635
636 struct ArcScale : public ScalingMethod {
637 boost::shared_ptr<ArcLengthCtx> arcCtx;
638
639 ArcScale(boost::shared_ptr<ArcLengthCtx> arc_ctx) : arcCtx(arc_ctx) {}
640
641 double getScale(const double time) override {
642 return arcCtx->getFieldData();
643 }
644 };
645 auto arc_scale = boost::make_shared<ArcScale>(arcCtx);
646
647 struct ArcZero : public ScalingMethod {
648 double getScale(const double time) override {
649 return 0.0;
650 }
651 };
652 auto arc_zero = boost::make_shared<ArcZero>();
653
654 auto get_essential_pre_proc_zero =
655 [&m_field, essential_pre_proc_zero_rhs, arc_zero]() {
657 m_field, essential_pre_proc_zero_rhs, {arc_zero});
658 };
659 essential_pre_proc_zero_rhs->preProcessHook =
660 get_essential_pre_proc_zero();
661 auto get_essential_pre_proc_lhs =
662 [&m_field, essential_pre_proc_lhs, arc_scale]() {
664 m_field, essential_pre_proc_lhs, {arc_scale});
665 };
666 essential_pre_proc_lhs->preProcessHook = get_essential_pre_proc_lhs();
667
668 essential_post_proc_rhs->postProcessHook =
669 [&m_field, essential_post_proc_rhs, arc_scale]() {
672 m_field, essential_post_proc_rhs, {arc_scale})();
674 m_field, essential_post_proc_rhs, 1.)();
676 };
677
678 // ArcScale sets the reference prescribed field to lambda * F_lambda, so
679 // the constrained residual is u_D - lambda * F_lambda,D.
680 essential_post_proc_lhs->postProcessHook =
682 m_field, essential_post_proc_lhs, 1.);
683
684 elasticRhsFe = boost::make_shared<DomainEle>(m_field);
685 elasticLhsFe = boost::make_shared<DomainEle>(m_field);
686 auto elastic_integration_rule = [](int, int, int approx_order) {
687 return 2 * approx_order + 1;
688 };
689 elasticRhsFe->getRuleHook = elastic_integration_rule;
690 elasticLhsFe->getRuleHook = elastic_integration_rule;
691
693 elasticRhsFe->getOpPtrVector(), {H1}, "GEOMETRY");
695 elasticLhsFe->getOpPtrVector(), {H1}, "GEOMETRY");
696 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, PETSC, GAUSS, DomainEleOp>(
697 m_field, elasticRhsFe->getOpPtrVector(), "DISPLACEMENT", "MAT_ELASTIC",
698 Sev::verbose, true);
699 CHKERR HookeOps::opFactoryDomainLhs<SPACE_DIM, PETSC, GAUSS, DomainEleOp>(
700 m_field, elasticLhsFe->getOpPtrVector(), "DISPLACEMENT", "MAT_ELASTIC",
701 Sev::verbose);
702
703 cohesiveElementsPtr = boost::make_shared<CohesiveInterfaceElement>(m_field);
704 auto &cohesive_elements = *cohesiveElementsPtr;
705 CHKERR cohesive_elements.addOps("DISPLACEMENT", interfaceMaterials);
706
707 PetscInt M, N;
708 CHKERR MatGetSize(aij, &M, &N);
709 PetscInt m, n;
710 CHKERR MatGetLocalSize(aij, &m, &n);
711 matCtx.reset(new ArcLengthMatShell(aij, arcCtx, "ELASTIC_MECHANICS"));
712 Mat shell_aij;
713 CHKERR MatCreateShell(PETSC_COMM_WORLD, m, n, M, N, (void *)matCtx.get(),
714 &shell_aij);
715 shellAij = SmartPetscObj<Mat>(shell_aij);
716 CHKERR MatShellSetOperation(shellAij, MATOP_MULT,
717 (void (*)(void))ArcLengthMatMultShellOp);
718
722
723 naturalBcFe = boost::make_shared<BoundaryEle>(m_field);
724 naturalBcFe->getRuleHook = [](int, int, int approx_order) {
725 return 2 * approx_order + 1;
726 };
727 CHKERR AddHOOps<2, 3, 3>::add(naturalBcFe->getOpPtrVector(), {NOSPACE},
728 "GEOMETRY");
730 naturalBcFe->getOpPtrVector(), m_field, "DISPLACEMENT", Sev::inform);
731
732 snes = createSNES(PETSC_COMM_WORLD);
733 CHKERR SNESSetApplicationContext(snes, &snes_ctx);
734 CHKERR SNESSetFunction(snes, f, SnesRhs, &snes_ctx);
735 CHKERR SNESSetJacobian(snes, shellAij, aij, SnesMat, &snes_ctx);
736 CHKERR SNESSetFromOptions(snes);
737
738 KSP ksp;
739 CHKERR SNESGetKSP(snes, &ksp);
740 PC pc;
741 CHKERR KSPGetPC(ksp, &pc);
742 pcCtx.reset(new PCArcLengthCtx(shellAij, aij, arcCtx));
743 CHKERR PCSetType(pc, PCSHELL);
744 CHKERR PCShellSetContext(pc, pcCtx.get());
745 CHKERR PCShellSetApply(pc, PCApplyArcLength);
746 CHKERR PCShellSetSetUp(pc, PCSetupArcLength);
747
748 // Rhs
749 SnesCtx::FEMethodsSequence &loops_to_do_Rhs = snes_ctx.getComputeRhs();
750 snes_ctx.getPreProcComputeRhs().push_back(essential_pre_proc_zero_rhs);
751 snes_ctx.getPreProcComputeRhs().push_back(&pre_post_proc_fe);
752 loops_to_do_Rhs.push_back(
753 SnesCtx::PairNameFEMethodPtr("INTERFACE", &cohesive_elements.getFeRhs()));
754 loops_to_do_Rhs.push_back(
756 loops_to_do_Rhs.push_back(
757 SnesCtx::PairNameFEMethodPtr("ARC_LENGTH", arcMethodPtr.get()));
758 // Add F_lambda before essential processing replaces the constrained rows
759 // with u_D - lambda * F_lambda,D.
760 snes_ctx.getPostProcComputeRhs().push_back(&pre_post_proc_fe);
761 snes_ctx.getPostProcComputeRhs().push_back(essential_post_proc_rhs);
762
763 // Mat
764 SnesCtx::FEMethodsSequence &loops_to_do_Mat = snes_ctx.getSetOperators();
765 snes_ctx.getPreProcSetOperators().push_back(essential_pre_proc_lhs);
766 loops_to_do_Mat.push_back(
767 SnesCtx::PairNameFEMethodPtr("INTERFACE", &cohesive_elements.getFeLhs()));
768 loops_to_do_Mat.push_back(
770 loops_to_do_Mat.push_back(
771 SnesCtx::PairNameFEMethodPtr("ARC_LENGTH", arcMethodPtr.get()));
772 snes_ctx.getPostProcSetOperators().push_back(essential_post_proc_lhs);
773
774 // step = 1;
775 if (step == 1) {
776 step_size = stepSizeReduction;
777 } else {
779 step++;
780 }
781
782 auto f_lambda_on_essential_bc = boost::make_shared<FEMethod>();
783 f_lambda_on_essential_bc->preProcessHook =
785 m_field, f_lambda_on_essential_bc, {}, false);
786 // EssentialPreProc stores the unit prescribed field. Its derivative in
787 // u_D - lambda * F_lambda,D has the opposite sign, hence vDiag = -1.
788 f_lambda_on_essential_bc->postProcessHook =
790 m_field, f_lambda_on_essential_bc, -1., arcCtx->F_lambda);
791
792 CHKERR VecZeroEntries(arcCtx->F_lambda);
793 CHKERR VecGhostUpdateBegin(arcCtx->F_lambda, INSERT_VALUES, SCATTER_FORWARD);
794 CHKERR VecGhostUpdateEnd(arcCtx->F_lambda, INSERT_VALUES, SCATTER_FORWARD);
795 CHKERR m_field.problem_basic_method_preProcess("ELASTIC_MECHANICS",
796 *f_lambda_on_essential_bc);
797 elasticRhsFe->ksp_f = arcCtx->F_lambda;
798 CHKERR m_field.loop_finite_elements("ELASTIC_MECHANICS", "ELASTIC",
799 *elasticRhsFe);
800 naturalBcFe->ksp_f = arcCtx->F_lambda;
801 CHKERR m_field.loop_finite_elements("ELASTIC_MECHANICS", naturalBcFeName,
802 *naturalBcFe);
803 CHKERR m_field.problem_basic_method_postProcess("ELASTIC_MECHANICS",
804 *f_lambda_on_essential_bc);
805 CHKERR VecGhostUpdateBegin(arcCtx->F_lambda, ADD_VALUES, SCATTER_REVERSE);
806 CHKERR VecGhostUpdateEnd(arcCtx->F_lambda, ADD_VALUES, SCATTER_REVERSE);
807 CHKERR VecAssemblyBegin(arcCtx->F_lambda);
808 CHKERR VecAssemblyEnd(arcCtx->F_lambda);
809
810 // F_lambda2
811 CHKERR VecDot(arcCtx->F_lambda, arcCtx->F_lambda, &arcCtx->F_lambda2);
812 MOFEM_LOG_C("ARC_LENGTH", Sev::inform, "\tFlambda2 = %6.4e",
813 arcCtx->F_lambda2);
814
815 if (step > 1) {
816 CHKERR m_field.getInterface<VecManager>()->setLocalGhostVector(
817 "ELASTIC_MECHANICS", COL, d, INSERT_VALUES, SCATTER_FORWARD);
818 CHKERR m_field.getInterface<VecManager>()->setOtherGlobalGhostVector(
819 "ELASTIC_MECHANICS", "DISPLACEMENT", "X0_DISPLACEMENT", COL, arcCtx->x0,
820 INSERT_VALUES, SCATTER_FORWARD);
821 double x0_nrm;
822 CHKERR VecNorm(arcCtx->x0, NORM_2, &x0_nrm);
823 MOFEM_LOG_C("ARC_LENGTH", Sev::inform,
824 "\tRead x0_nrm = %6.4e dlambda = %6.4e", x0_nrm,
825 arcCtx->dLambda);
826 CHKERR arcCtx->setAlphaBeta(1, 0);
827 } else {
828 CHKERR arcCtx->setS(0);
829 CHKERR arcCtx->setAlphaBeta(0, 1);
830 }
831 CHKERR SnesRhs(snes, d, f, &snes_ctx);
832
833 postProcPtr = boost::make_shared<PostProcEle>(m_field);
834 auto &post_proc = *postProcPtr;
835 auto disp_ptr = boost::make_shared<MatrixDouble>();
837 post_proc.getOpPtrVector(), {H1}, "GEOMETRY");
838 auto hooke_common_ptr =
839 HookeOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
840 m_field, post_proc.getOpPtrVector(), "DISPLACEMENT", "MAT_ELASTIC",
841 Sev::verbose);
842 post_proc.getOpPtrVector().push_back(
843 new OpCalculateVectorFieldValues<SPACE_DIM>("DISPLACEMENT", disp_ptr));
845 post_proc.getOpPtrVector().push_back(
846 new OpPPMap(post_proc.getPostProcMesh(), post_proc.getMapGaussPts(), {},
847 {{"DISPLACEMENT", disp_ptr}},
848 {{"DISPLACEMENT_GRAD", hooke_common_ptr->matGradPtr}},
849 {{"STRAIN", hooke_common_ptr->getMatStrain()},
850 {"STRESS", hooke_common_ptr->getMatCauchyStress()}}));
851
852 int coords_dim = SPACE_DIM;
853 CHKERR PetscOptionsGetRealArray(PETSC_NULLPTR, PETSC_NULLPTR,
854 "-field_eval_coords", fieldEvalCoords.data(),
855 &coords_dim, &doEvalField);
856 if (doEvalField && coords_dim != SPACE_DIM)
857 SETERRQ(PETSC_COMM_WORLD, MOFEM_INVALID_DATA,
858 "-field_eval_coords requires exactly three coordinates");
859
860 if (doEvalField) {
861 fieldEvalData =
862 m_field.getInterface<FieldEvaluatorInterface>()->getData<DomainEle>();
863 CHKERR m_field.getInterface<FieldEvaluatorInterface>()
864 ->buildTree<SPACE_DIM>(fieldEvalData, "ELASTIC");
865 fieldEvalData->setEvalPoints(fieldEvalCoords.data(), 1);
866
867 auto field_eval_fe = fieldEvalData->feMethodPtr;
868 field_eval_fe->getRuleHook = [](int, int, int) { return -1; };
870 field_eval_fe->getOpPtrVector(), {H1}, "GEOMETRY");
871
872 auto field_eval_hooke_common_ptr =
873 HookeOps::commonDataFactory<SPACE_DIM, GAUSS, DomainEleOp>(
874 m_field, field_eval_fe->getOpPtrVector(), "DISPLACEMENT",
875 "MAT_ELASTIC", Sev::verbose);
876 fieldEvalStressPtr = field_eval_hooke_common_ptr->getMatCauchyStress();
877 fieldEvalDispPtr = boost::make_shared<MatrixDouble>();
878 field_eval_fe->getOpPtrVector().push_back(
880 fieldEvalDispPtr));
881 }
882
884}
885//! [Assemble system]
886
890 auto &m_field = *mField;
891
892 if (!doEvalField)
894
895 CHKERR m_field.getInterface<FieldEvaluatorInterface>()
896 ->evalFEAtThePoint<SPACE_DIM>(
897 fieldEvalCoords.data(), 1e-12, "ELASTIC_MECHANICS", "ELASTIC",
898 fieldEvalData, m_field.get_comm_rank(), m_field.get_comm_rank(),
899 nullptr, MF_EXIST, QUIET);
900
901 int point_found = fieldEvalDispPtr->size1() && fieldEvalStressPtr->size1();
902 int global_point_found = 0;
903 MPI_Allreduce(&point_found, &global_point_found, 1, MPI_INT, MPI_SUM,
904 m_field.get_comm());
905
906 if (point_found) {
907 auto t_disp = getFTensor1FromMat<SPACE_DIM>(*fieldEvalDispPtr);
908 auto t_stress = getFTensor2SymmetricFromMat<SPACE_DIM>(*fieldEvalStressPtr);
909 MOFEM_LOG_C("SYNC", Sev::inform,
910 "FieldEvaluator step %d lambda %6.4e point [%6.4e, %6.4e, "
911 "%6.4e]",
912 load_step, arcCtx->getFieldData(), fieldEvalCoords[0],
914 MOFEM_LOG_C("SYNC", Sev::inform,
915 "FieldEvaluator displacement [Ux, Uy, Uz] = [%6.4e, "
916 "%6.4e, %6.4e]",
917 t_disp(0), t_disp(1), t_disp(2));
918 MOFEM_LOG_C("SYNC", Sev::inform,
919 "FieldEvaluator Cauchy stress [Sxx, Syy, Szz, Sxy, Syz, Sxz] "
920 "= [%6.4e, %6.4e, %6.4e, %6.4e, %6.4e, %6.4e]",
921 t_stress(0, 0), t_stress(1, 1), t_stress(2, 2), t_stress(0, 1),
922 t_stress(1, 2), t_stress(0, 2));
923 } else if (!global_point_found && !m_field.get_comm_rank()) {
924 MOFEM_LOG_C("ARC_LENGTH", Sev::warning,
925 "FieldEvaluator did not find point [%6.4e, %6.4e, %6.4e] in "
926 "the ELASTIC domain",
928 }
929 MOFEM_LOG_SYNCHRONISE(m_field.get_comm());
930
932}
933
937 auto &m_field = *mField;
938
939 auto domain_reaction_fe = boost::make_shared<DomainEle>(m_field);
940 domain_reaction_fe->getRuleHook = [](int, int, int approx_order) {
941 return 2 * approx_order + 1;
942 };
943
945 domain_reaction_fe->getOpPtrVector(), {H1}, "GEOMETRY");
946 CHKERR HookeOps::opFactoryDomainRhs<SPACE_DIM, PETSC, GAUSS, DomainEleOp>(
947 m_field, domain_reaction_fe->getOpPtrVector(), "DISPLACEMENT",
948 "MAT_ELASTIC", Sev::verbose, true);
949
950 auto reactions = vectorDuplicate(f);
951 CHKERR VecZeroEntries(reactions);
952 domain_reaction_fe->f = reactions;
953 domain_reaction_fe->vecAssembleSwitch =
954 boost::movelib::make_unique<bool>(true);
955 domain_reaction_fe->postProcessHook =
957 domain_reaction_fe);
958
959 MOFEM_LOG_C("ARC_LENGTH", Sev::inform,
960 "Reactions step %d lambda %6.4e", load_step,
961 arcCtx->getFieldData());
962 CHKERR m_field.loop_finite_elements("ELASTIC_MECHANICS", "ELASTIC",
963 *domain_reaction_fe);
964
966}
967
968//! [Solve]
971
972 double min_arc_length_step = std::numeric_limits<double>::epsilon();
973 double max_arc_length_step = std::numeric_limits<double>::max();
974 CHKERR PetscOptionsGetReal(PETSC_NULLPTR, PETSC_NULLPTR, "-gamma", &gamma,
975 PETSC_NULLPTR);
976 CHKERR PetscOptionsGetReal(PETSC_NULLPTR, PETSC_NULLPTR,
977 "-min_arc_length_step", &min_arc_length_step,
978 PETSC_NULLPTR);
979 CHKERR PetscOptionsGetReal(PETSC_NULLPTR, PETSC_NULLPTR,
980 "-max_arc_length_step", &max_arc_length_step,
981 PETSC_NULLPTR);
982
983 if (min_arc_length_step <= 0.)
984 SETERRQ(PETSC_COMM_WORLD, MOFEM_INVALID_DATA,
985 "-min_arc_length_step must be positive");
986 if (max_arc_length_step <= 0.)
987 SETERRQ(PETSC_COMM_WORLD, MOFEM_INVALID_DATA,
988 "-max_arc_length_step must be positive");
989 if (min_arc_length_step > max_arc_length_step)
990 SETERRQ(PETSC_COMM_WORLD, MOFEM_INVALID_DATA,
991 "-min_arc_length_step must not exceed -max_arc_length_step");
992
993 auto &m_field = *mField;
994 auto &step = *stepPtr;
995 auto &step_size = *stepSizePtr;
996
997 auto &cohesive_elements = *cohesiveElementsPtr;
998 auto &post_proc = *postProcPtr;
999
1000 bool converged_state = false;
1001 for (; step < maxSteps; step++) {
1002
1003 if (step == 1) {
1004 MOFEM_LOG_C("ARC_LENGTH", Sev::inform, "Load Step %d step_size = %6.4e",
1005 step, step_size);
1006 CHKERR arcCtx->setS(step_size);
1007 CHKERR arcCtx->setAlphaBeta(0, 1);
1008 CHKERR VecCopy(d, arcCtx->x0);
1009 double dlambda;
1010 CHKERR arcMethodPtr->calculate_init_dlambda(&dlambda);
1011 CHKERR arcMethodPtr->set_dlambda_to_x(dRaw, dlambda);
1012 } else if (step == 2) {
1013 CHKERR arcCtx->setAlphaBeta(1, 0);
1014 CHKERR arcMethodPtr->calculate_dx_and_dlambda(dRaw);
1015 CHKERR arcMethodPtr->calculate_lambda_int(step_size);
1016 CHKERR arcCtx->setS(step_size);
1017 double dlambda = arcCtx->dLambda;
1018 double dx_nrm;
1019 CHKERR VecNorm(arcCtx->dx, NORM_2, &dx_nrm);
1020 MOFEM_LOG_C("ARC_LENGTH", Sev::inform,
1021 "Load Step %d step_size = %6.4e dlambda0 = %6.4e "
1022 "dx_nrm = %6.4e dx2 = %6.4e",
1023 step, step_size, dlambda, dx_nrm, arcCtx->dx2);
1024 CHKERR VecCopy(d, arcCtx->x0);
1025 CHKERR VecAXPY(d, 1., arcCtx->dx);
1026 CHKERR arcMethodPtr->set_dlambda_to_x(dRaw, dlambda);
1027 } else {
1028 CHKERR arcMethodPtr->calculate_dx_and_dlambda(dRaw);
1029 CHKERR arcMethodPtr->calculate_lambda_int(step_size);
1030 // step_size0_1/step_size0 = step_stize1/step_size
1031 // step_size0_1 = step_size0*(step_stize1/step_size)
1032 step_size *= reduction;
1033 CHKERR arcCtx->setS(step_size);
1034 double dlambda = reduction * arcCtx->dLambda;
1035 CHKERR VecScale(arcCtx->dx, reduction);
1036 double dx_nrm;
1037 CHKERR VecNorm(arcCtx->dx, NORM_2, &dx_nrm);
1038 MOFEM_LOG_C("ARC_LENGTH", Sev::inform,
1039 "Load Step %d step_size = %6.4e dlambda0 = %6.4e "
1040 "dx_nrm = %6.4e dx2 = %6.4e",
1041 step, step_size, dlambda, dx_nrm, arcCtx->dx2);
1042 CHKERR VecCopy(d, arcCtx->x0);
1043 CHKERR VecAXPY(d, 1., arcCtx->dx);
1044 CHKERR arcMethodPtr->set_dlambda_to_x(dRaw, dlambda);
1045 }
1046
1047 CHKERR SNESSolve(snes, PETSC_NULLPTR, d);
1048
1049 int its;
1050 CHKERR SNESGetIterationNumber(snes, &its);
1051 MOFEM_LOG_C("ARC_LENGTH", Sev::inform, "number of Newton iterations = %d",
1052 its);
1053
1054 SNESConvergedReason reason;
1055 CHKERR SNESGetConvergedReason(snes, &reason);
1056
1057 if (reason <= 0) {
1058 CHKERR arcCtx->setAlphaBeta(1, 0);
1059 reduction = 0.1;
1060 converged_state = false;
1061 continue;
1062 } else {
1063 if (step > 1 && converged_state) {
1064 reduction = pow((double)itsD / (double)(its + 1), gamma);
1065 reduction =
1066 std::clamp(reduction, min_arc_length_step / std::abs(step_size),
1067 max_arc_length_step / std::abs(step_size));
1068 MOFEM_LOG_C("ARC_LENGTH", Sev::inform, "reduction step_size = %6.4e",
1069 reduction);
1070 }
1071
1072 // Save data on mesh
1073 CHKERR m_field.getInterface<VecManager>()->setGlobalGhostVector(
1074 "ELASTIC_MECHANICS", COL, d, INSERT_VALUES, SCATTER_REVERSE);
1075 // Commit cohesive history only after SNES convergence.
1076 CHKERR m_field.loop_finite_elements("ELASTIC_MECHANICS", "INTERFACE",
1077 cohesive_elements.getFeHistory(), 0,
1078 m_field.get_comm_size());
1079 CHKERR arcMethodPtr->remove_damaged_prisms_nodes();
1080 CHKERR m_field.getInterface<VecManager>()->setOtherGlobalGhostVector(
1081 "ELASTIC_MECHANICS", "DISPLACEMENT", "X0_DISPLACEMENT", COL,
1082 arcCtx->x0, INSERT_VALUES, SCATTER_REVERSE);
1083 converged_state = true;
1084 }
1085 //
1086 if (reason > 0) {
1089 }
1090
1091 if (step % 1 == 0) {
1092
1093 CHKERR m_field.loop_finite_elements("ELASTIC_MECHANICS", "ELASTIC",
1094 post_proc);
1095 std::ostringstream ss;
1096 ss << "out_values_" << step << ".h5m";
1097 CHKERR post_proc.writeFile(ss.str().c_str());
1098 }
1099 }
1100
1102}
1103//! [Solve]
1104
1105//! [Postprocess results]
1110//! [Postprocess results]
1111
1112//! [Check]
1117//! [Check]
1118
1119int main(int argc, char *argv[]) {
1120
1121 const string default_options = "-ksp_type fgmres \n"
1122 "-pc_type lu \n"
1123 "-pc_factor_mat_solver_type mumps\n"
1124 "-mat_mumps_icntl_20 0\n"
1125 "-ksp_monitor \n"
1126 "-ksp_atol 1e-10 \n"
1127 "-ksp_rtol 1e-10 \n"
1128 "-snes_monitor \n"
1129 "-snes_type newtonls \n"
1130 "-snes_linesearch_type l2 \n"
1131 "-snes_linesearch_monitor \n"
1132 "-snes_max_it 16 \n"
1133 "-snes_atol 1e-8 \n"
1134 "-snes_rtol 1e-8 \n"
1135 "-snes_converged_reason \n";
1136
1137 string param_file = "param_file.petsc";
1138 if (!static_cast<bool>(ifstream(param_file))) {
1139 std::ofstream file(param_file.c_str(), std::ios::ate);
1140 if (file.is_open()) {
1141 file << default_options;
1142 file.close();
1143 }
1144 }
1145 MoFEM::Core::Initialize(&argc, &argv, param_file.c_str(), help);
1146
1147 auto core_log = logging::core::get();
1148 core_log->add_sink(
1150 LogManager::setLog("ARC_LENGTH");
1151 MOFEM_LOG_TAG("ARC_LENGTH", "ArcLength");
1152
1153 try {
1154 moab::Core mb_instance;
1155 moab::Interface &moab = mb_instance;
1156
1157 ArcLengthInterfaceExample example(moab);
1158 CHKERR example.runProblem();
1159 }
1161
1163
1164 return 0;
1165}
Implementation of linear interface element.
Natural force and pressure boundary conditions.
SmartPetscObj< KSP > ksp
Implementation of Hookes operator Hookes for linear elastic problems in MoFEM.
Implementation of arc-length control for cohesive elements.
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
#define MOFEM_LOG_C(channel, severity, format,...)
int main()
static char help[]
constexpr int SPACE_DIM
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
ElementsAndOps< SPACE_DIM >::BoundaryEle BoundaryEle
@ QUIET
@ COL
#define CATCH_ERRORS
Catch errors.
@ MF_EXIST
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ NOBASE
Definition definitions.h:59
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ NOFIELD
scalar or vector of scalars describe (no true field)
Definition definitions.h:84
@ H1
continuous field
Definition definitions.h:85
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ PRESSURESET
@ FORCESET
@ NODESET
@ SIDESET
@ INTERFACESET
@ MOFEM_INVALID_DATA
Definition definitions.h:36
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
@ PETSC
Standard PETSc assembly.
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 _IT_CUBITMESHSETS_BY_BCDATA_TYPE_FOR_LOOP_(MESHSET_MANAGER, CUBITBCTYPE, IT)
Iterator that loops over a specific Cubit MeshSet in a moFEM field.
#define _IT_CUBITMESHSETS_FOR_LOOP_(MESHSET_MANAGER, IT)
Iterator that loops over all the Cubit MeshSets in a moFEM field.
MoFEMErrorCode partitionGhostDofs(const std::string name, int verb=VERBOSE)
determine ghost nodes
MoFEMErrorCode buildProblem(const std::string name, const bool square_matrix, int verb=VERBOSE)
build problem data structures
MoFEMErrorCode partitionProblem(const std::string name, int verb=VERBOSE)
partition problem dofs (collective)
MoFEMErrorCode partitionFiniteElements(const std::string name, bool part_from_moab=false, int low_proc=-1, int hi_proc=-1, int verb=VERBOSE)
partition finite elements
MoFEMErrorCode pushMarkDOFsOnEntities(const std::string problem_name, const std::string block_name, const std::string field_name, int lo, int hi, bool get_low_dim_ents=true)
Mark DOFs on block entities for boundary conditions.
PetscBool doEvalField
const double n
refractive index of diffusive medium
static MoFEMErrorCodeGeneric< moab::ErrorCode > rval
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition Types.hpp:40
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto createSNES(MPI_Comm comm)
PetscErrorCode SnesMat(SNES snes, Vec x, Mat A, Mat B, void *ctx)
This is MoFEM implementation for the left hand side (tangent matrix) evaluation in SNES solver.
Definition SnesCtx.cpp:491
PetscErrorCode PetscOptionsGetInt(PetscOptions *, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
PetscErrorCode PetscOptionsGetReal(PetscOptions *, const char pre[], const char name[], PetscReal *dval, PetscBool *set)
PetscErrorCode SnesRhs(SNES snes, Vec x, Vec f, void *ctx)
This is MoFEM implementation for the right hand side (residual vector) evaluation in SNES solver.
Definition SnesCtx.cpp:227
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)
PetscErrorCode PetscOptionsGetString(PetscOptions *, const char pre[], const char name[], char str[], size_t size, PetscBool *set)
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
static constexpr int approx_order
FTensor::Index< 'm', 3 > m
const int N
Definition speed_test.cpp:3
MoFEMErrorCode boundaryCondition()
[Set up problem]
boost::shared_ptr< ArcLengthIntElemFEMethod > arcMethodPtr
MoFEMErrorCode checkResults()
[Postprocess results]
MoFEMErrorCode readMesh()
[Run problem]
boost::shared_ptr< MatrixDouble > fieldEvalStressPtr
boost::ptr_vector< CohesiveInterfaceElement::PhysicalEquation > interfaceMaterials
boost::scoped_ptr< PCArcLengthCtx > pcCtx
boost::shared_ptr< MoFEM::Core > corePtr
boost::shared_ptr< PostProcEle > postProcPtr
MoFEMErrorCode evaluateReactions(const int load_step)
boost::shared_ptr< CohesiveInterfaceElement > cohesiveElementsPtr
MoFEMErrorCode setupProblem()
[Read mesh]
MoFEMErrorCode assembleSystem()
[Boundary condition]
MoFEMErrorCode solveSystem()
[Solve]
MoFEMErrorCode outputResults()
[Solve]
boost::shared_ptr< AssembleRhsVectors > prePostProcFePtr
MoFEMErrorCode runProblem()
[Run problem]
boost::shared_ptr< ArcLengthCtx > arcCtx
boost::shared_ptr< MatrixDouble > fieldEvalDispPtr
MoFEMErrorCode evaluateFieldAtPoint(const int load_step)
[Assemble system]
boost::shared_ptr< FieldEvaluatorInterface::SetPtsData > fieldEvalData
boost::scoped_ptr< ArcLengthMatShell > matCtx
std::array< double, SPACE_DIM > fieldEvalCoords
boost::shared_ptr< ArcLengthSnesCtx > snesCtxPtr
boost::shared_ptr< DomainEle > elasticLhsFe
ArcLengthInterfaceExample(moab::Interface &moab)
boost::shared_ptr< BoundaryEle > naturalBcFe
boost::shared_ptr< DomainEle > elasticRhsFe
shell matrix for arc-length method
Boundary conditions marker.
MoFEMErrorCode postProcess()
Post-processing function executed at loop completion.
AssembleRhsVectors(boost::shared_ptr< ArcLengthCtx > &arc_ptr)
boost::shared_ptr< ArcLengthCtx > arcPtr
MoFEMErrorCode preProcess()
Pre-processing function executed at loop initialization.
Add operators pushing bases from local to physical configuration.
Boundary condition manager for finite element problem setup.
Managing BitRefLevels.
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:68
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:123
Deprecated interface functions.
Definition of the displacement bc data structure.
Definition BCData.hpp:72
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 calculate residual side diagonal.
Definition Essential.hpp:49
Class (Function) to enforce essential constrains.
Definition Essential.hpp:25
Structure for user loop methods on finite elements.
Field evaluator interface.
static MoFEMErrorCode setMeshFileFromJson()
Set -file_name from JSON before Core is available.
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.
Linear interface data structure.
Matrix manager is used to build and partition problems.
Interface for managing meshsets containing materials and boundary conditions.
MoFEMErrorCode setMeshsetFromFile(const string file_name, const bool clean_file_options=true)
add blocksets reading config file
Assembly methods.
Definition Natural.hpp:65
Specialization for MatrixDouble vector field values calculation.
Post post-proc data at points from hash maps.
Template struct for dimension-specific finite element types.
Create interface from given surface and insert flat prisms in-between.
MoFEMErrorCode getSides(const int msId, const CubitBCType cubit_bc_type, const BitRefLevel mesh_bit_level, const bool recursive, int verb=QUIET)
Store tetrahedra from each side of the interface separately in two child meshsets of the parent meshs...
MoFEMErrorCode splitSides(const EntityHandle meshset, const BitRefLevel &bit, const int msId, const CubitBCType cubit_bc_type, const bool add_interface_entities, const bool recursive=false, int verb=QUIET)
Split nodes and other entities of tetrahedra on both sides of the interface and insert flat prisms in...
Problem manager is used to build and partition problems.
Projection of edge entities with one mid-node on hierarchical basis.
intrusive_ptr for managing petsc objects
MoFEM::FEMethodsSequence FEMethodsSequence
Definition SnesCtx.hpp:18
@ CTX_SNESSETFUNCTION
Setting up nonlinear function evaluation.
@ CTX_SNESNONE
No specific SNES context.
Vec & snes_f
Reference to residual vector.
SNESContext snes_ctx
Current SNES computation context.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Vector manager is used to create vectors \mofem_vectors.
structure for Arc Length pre-conditioner
MoFEMErrorCode PCApplyArcLength(PC pc, Vec pc_f, Vec pc_x)
MoFEMErrorCode ArcLengthMatMultShellOp(Mat A, Vec x, Vec f)
MoFEMErrorCode PCSetupArcLength(PC pc)