v0.16.0
Loading...
Searching...
No Matches
Classes | Typedefs | Functions | Variables
elasticity.cpp File Reference
#include <BasicFiniteElements.hpp>
#include <Hooke.hpp>

Go to the source code of this file.

Classes

struct  BlockOptionData
 
struct  VolRule
 Set integration rule to volume elements. More...
 
struct  PrismFE
 

Typedefs

using BlockData = NonlinearElasticElement::BlockData
 
using MassBlockData = ConvectiveMassElement::BlockData
 
using VolUserDataOperator = VolumeElementForcesAndSourcesCore::UserDataOperator
 
using EdgeEle = MoFEM::EdgeElementForcesAndSourcesCore
 

Functions

int main (int argc, char *argv[])
 

Variables

static char help []
 

Typedef Documentation

◆ BlockData

Definition at line 74 of file elasticity.cpp.

◆ EdgeEle

Definition at line 94 of file elasticity.cpp.

◆ MassBlockData

Definition at line 75 of file elasticity.cpp.

◆ VolUserDataOperator

Definition at line 76 of file elasticity.cpp.

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)

PETSC_VIEWER_ASCII_DENSE, PETSC_VIEWER_ASCII_MATLAB

Definition at line 96 of file elasticity.cpp.

96 {
97
98 const string default_options = "-ksp_type gmres \n"
99 "-pc_type lu \n"
100 "-pc_factor_mat_solver_type mumps \n"
101 "-mat_mumps_icntl_20 0 \n"
102 "-ksp_monitor \n"
103 "-snes_type newtonls \n"
104 "-snes_linesearch_type basic \n"
105 "-snes_atol 1e-8 \n"
106 "-snes_rtol 1e-8 \n"
107 "-snes_monitor \n"
108 "-ts_monitor \n"
109 "-ts_type beuler \n";
110
111 string param_file = "param_file.petsc";
112 if (!static_cast<bool>(ifstream(param_file))) {
113 std::ofstream file(param_file.c_str(), std::ios::ate);
114 if (file.is_open()) {
115 file << default_options;
116 file.close();
117 }
118 }
119
120 MoFEM::Core::Initialize(&argc, &argv, param_file.c_str(), help);
121 auto core_log = logging::core::get();
122 core_log->add_sink(
124 LogManager::setLog("ELASTIC");
125 MOFEM_LOG_TAG("ELASTIC", "elasticity")
126
127 core_log->add_sink(
128 LogManager::createSink(LogManager::getStrmSync(), "ELASTIC_SYNC"));
129 LogManager::setLog("ELASTIC_SYNC");
130 MOFEM_LOG_TAG("ELASTIC_SYNC", "elastic_sync");
131
132 try {
133
134 PetscBool flg_block_config, flg_file;
135 char mesh_file_name[255];
136 char block_config_file[255];
137 PetscInt test_nb = 0;
138 PetscInt order = 2;
139 PetscBool is_partitioned = PETSC_FALSE;
140 PetscBool is_calculating_frequency = PETSC_FALSE;
141 PetscBool is_post_proc_volume = PETSC_TRUE;
142
143 // Select base
144 enum bases { LEGENDRE, LOBATTO, BERNSTEIN_BEZIER, JACOBI, LASBASETOP };
145 const char *list_bases[] = {"legendre", "lobatto", "bernstein_bezier",
146 "jacobi"};
147 PetscInt choice_base_value = LOBATTO;
148
149 // Read options from command line
150 PetscOptionsBegin(PETSC_COMM_WORLD, "", "Elastic Config", "none");
151 CHKERR PetscOptionsString("-my_file", "mesh file name", "", "mesh.h5m",
152 mesh_file_name, 255, &flg_file);
153
154 CHKERR PetscOptionsInt("-my_order", "default approximation order", "",
155 order, &order, PETSC_NULLPTR);
156
157 CHKERR PetscOptionsEList("-base", "approximation base", "", list_bases,
158 LASBASETOP, list_bases[choice_base_value],
159 &choice_base_value, PETSC_NULLPTR);
160
161 CHKERR PetscOptionsInt("-is_atom_test", "ctest number", "", test_nb,
162 &test_nb, PETSC_NULLPTR);
163
164 CHKERR PetscOptionsBool("-my_is_partitioned",
165 "set if mesh is partitioned (this result that each "
166 "process keeps only one part of the mesh)",
167 "", is_partitioned, &is_partitioned, PETSC_NULLPTR);
168
169 CHKERR PetscOptionsString("-my_block_config", "elastic configure file name",
170 "", "block_conf.in", block_config_file, 255,
171 &flg_block_config);
172
173 CHKERR PetscOptionsBool(
174 "-my_is_calculating_frequency", "set if frequency will be calculated",
175 "", is_calculating_frequency, &is_calculating_frequency, PETSC_NULLPTR);
176
177 CHKERR PetscOptionsBool("-my_is_post_proc_volume",
178 "if true post proc volume", "", is_post_proc_volume,
179 &is_post_proc_volume, PETSC_NULLPTR);
180
181 PetscOptionsEnd();
182
183 // Throw error if file with mesh is not provided
184 if (flg_file != PETSC_TRUE) {
185 SETERRQ(PETSC_COMM_SELF, 1, "*** ERROR -my_file (MESH FILE NEEDED)");
186 }
187
188 // Create mesh database
189 moab::Core mb_instance;
190 moab::Interface &moab = mb_instance;
191
192 // Create moab communicator
193 // Create separate MOAB communicator, it is duplicate of PETSc communicator.
194 // NOTE That this should eliminate potential communication problems between
195 // MOAB and PETSC functions.
196 MPI_Comm moab_comm_world;
197 MPI_Comm_dup(PETSC_COMM_WORLD, &moab_comm_world);
198 ParallelComm *pcomm = ParallelComm::get_pcomm(&moab, MYPCOMM_INDEX);
199 if (pcomm == NULL)
200 pcomm = new ParallelComm(&moab, moab_comm_world);
201
202 // Read whole mesh or part of it if partitioned
203 if (is_partitioned == PETSC_TRUE) {
204 // This is a case of distributed mesh and algebra. In this case each
205 // processor keeps only one part of the problem.
206 const char *option;
207 option = "PARALLEL=READ_PART;"
208 "PARALLEL_RESOLVE_SHARED_ENTS;"
209 "PARTITION=PARALLEL_PARTITION;";
210 CHKERR moab.load_file(mesh_file_name, 0, option);
211 } else {
212 // If that case we have distributed algebra, i.e. assembly of vectors and
213 // matrices is in parallel, but whole mesh is stored on all processors.
214 // Solver and matrix scales well, however problem set-up of problem is
215 // not fully parallel.
216 const char *option;
217 option = "";
218 CHKERR moab.load_file(mesh_file_name, 0, option);
219 }
220
221 // Create MoFEM database and link it to MoAB
222 MoFEM::Core core(moab);
223 MoFEM::Interface &m_field = core;
224
225 // Print boundary conditions and material parameters
226 MeshsetsManager *meshsets_mng_ptr;
227 CHKERR m_field.getInterface(meshsets_mng_ptr);
228 CHKERR meshsets_mng_ptr->printDisplacementSet();
229 CHKERR meshsets_mng_ptr->printForceSet();
230 CHKERR meshsets_mng_ptr->printMaterialsSet();
231
232 bool mesh_has_tets = false;
233 bool mesh_has_prisms = false;
234 int nb_tets = 0;
235 int nb_hexs = 0;
236 int nb_prisms = 0;
237
238 CHKERR moab.get_number_entities_by_type(0, MBTET, nb_tets, true);
239 CHKERR moab.get_number_entities_by_type(0, MBHEX, nb_hexs, true);
240 CHKERR moab.get_number_entities_by_type(0, MBPRISM, nb_prisms, true);
241
242 mesh_has_tets = (nb_tets + nb_hexs) > 0;
243 mesh_has_prisms = nb_prisms > 0;
244
245 // Set bit refinement level to all entities (we do not refine mesh in
246 // this example so all entities have the same bit refinement level)
247 BitRefLevel bit_level0;
248 bit_level0.set(0);
249 CHKERR m_field.getInterface<BitRefManager>()->setBitRefLevelByDim(
250 0, 3, bit_level0);
251
252 // CHECK IF EDGE BLOCKSET EXIST AND IF IT IS ADD ALL ENTITIES FROM IT
253 // CHKERR m_field.getInterface<BitRefManager>()->setBitRefLevelByDim(
254 // MESHSET_OF_EDGE_BLOCKSET, 1, bit_level0);
255
257 if (bit->getName().compare(0, 3, "ROD") == 0) {
258 CHKERR m_field.getInterface<BitRefManager>()->setBitRefLevelByDim(
259 0, 1, bit_level0);
260 }
261 }
262
263 // Declare approximation fields
265 switch (choice_base_value) {
266 case LEGENDRE:
268 break;
269 case LOBATTO:
271 break;
272 case BERNSTEIN_BEZIER:
274 break;
275 case JACOBI:
277 break;
278 default:
279 SETERRQ(PETSC_COMM_WORLD, MOFEM_NOT_IMPLEMENTED, "Base not implemented");
280 };
281 CHKERR m_field.add_field("DISPLACEMENT", H1, base, 3, MB_TAG_DENSE,
282 MF_ZERO);
283
284 // We can use higher oder geometry to define body
285 CHKERR m_field.add_field("MESH_NODE_POSITIONS", H1, base, 3, MB_TAG_DENSE,
286 MF_ZERO);
287
288 // Declare problem
289
290 // Add entities (by tets) to the field (all entities in the mesh, root_set
291 // = 0 )
292 CHKERR m_field.add_ents_to_field_by_dim(0, 3, "DISPLACEMENT");
293 CHKERR m_field.add_ents_to_field_by_dim(0, 3, "MESH_NODE_POSITIONS");
294
295 // Get all edges in the mesh
296 Range all_edges;
297 CHKERR m_field.get_moab().get_entities_by_type(0, MBEDGE, all_edges, true);
298
299 // Get edges associated with simple rod
300 Range edges_in_simple_rod;
302 if (bit->getName().compare(0, 3, "ROD") == 0) {
303 Range edges;
304 CHKERR m_field.get_moab().get_entities_by_type(bit->getMeshset(),
305 MBEDGE, edges, true);
306 edges_in_simple_rod.merge(edges);
307 }
308 }
309
310 CHKERR m_field.add_ents_to_field_by_type(edges_in_simple_rod, MBEDGE,
311 "DISPLACEMENT");
312
313 // Set order of edge in rod to be 1
314 CHKERR m_field.set_field_order(edges_in_simple_rod, "DISPLACEMENT", 1);
315
316 // Get remaining edges (not associated with simple rod) to set order
317 Range edges_to_set_order;
318 edges_to_set_order = subtract(all_edges, edges_in_simple_rod);
319
320 // Set approximation order.
321 // See Hierarchical Finite Element Bases on Unstructured Tetrahedral
322 // Meshes.
323 CHKERR m_field.set_field_order(0, MBPRISM, "DISPLACEMENT", order);
324 CHKERR m_field.set_field_order(0, MBTET, "DISPLACEMENT", order);
325 CHKERR m_field.set_field_order(0, MBHEX, "DISPLACEMENT", order);
326 CHKERR m_field.set_field_order(0, MBTRI, "DISPLACEMENT", order);
327 CHKERR m_field.set_field_order(0, MBQUAD, "DISPLACEMENT", order);
328 CHKERR m_field.set_field_order(edges_to_set_order, "DISPLACEMENT", order);
329 CHKERR m_field.set_field_order(0, MBVERTEX, "DISPLACEMENT", 1);
330
332 CHKERR m_field.set_field_order(0, MBVERTEX, "DISPLACEMENT", order);
333 else
334 CHKERR m_field.set_field_order(0, MBVERTEX, "DISPLACEMENT", 1);
335
336 // Set order of approximation of geometry.
337 // Apply 2nd order only on skin (or in whole body)
338 auto setting_second_order_geometry = [&m_field]() {
340 // Setting geometry order everywhere
341 Range tets, edges;
342 CHKERR m_field.get_moab().get_entities_by_dimension(0, 3, tets);
343 CHKERR m_field.get_moab().get_adjacencies(tets, 1, false, edges,
344 moab::Interface::UNION);
345
346 // Setting 2nd geometry order only on skin
347 // Range tets, faces, edges;
348 // Skinner skin(&m_field.get_moab());
349 // CHKERR skin.find_skin(0,tets,false,faces);
350 // CHKERR m_field.get_moab().get_adjacencies(
351 // faces,1,false,edges,moab::Interface::UNION
352 // );
353 // CHKERR
354 // m_field.getInterface<CommInterface>()->synchroniseEntities(edges);
355
356 CHKERR m_field.set_field_order(edges, "MESH_NODE_POSITIONS", 2);
357 CHKERR m_field.set_field_order(0, MBVERTEX, "MESH_NODE_POSITIONS", 1);
358
360 };
361 CHKERR setting_second_order_geometry();
362
363 // Configure blocks by parsing config file. It allows setting
364 // approximation order for each block independently.
365 std::map<int, BlockOptionData> block_data;
366 auto setting_blocks_data_and_order_from_config_file =
367 [&m_field, &moab, &block_data, flg_block_config, block_config_file,
368 order](boost::shared_ptr<std::map<int, BlockData>> &block_sets_ptr) {
370 if (flg_block_config) {
371 ifstream ini_file(block_config_file);
372 po::variables_map vm;
373 po::options_description config_file_options;
375 it)) {
376 std::ostringstream str_order;
377 str_order << "block_" << it->getMeshsetId()
378 << ".displacement_order";
379 config_file_options.add_options()(
380 str_order.str().c_str(),
381 po::value<int>(&block_data[it->getMeshsetId()].oRder)
382 ->default_value(order));
383
384 std::ostringstream str_cond;
385 str_cond << "block_" << it->getMeshsetId() << ".young_modulus";
386 config_file_options.add_options()(
387 str_cond.str().c_str(),
388 po::value<double>(&block_data[it->getMeshsetId()].yOung)
389 ->default_value(-1));
390
391 std::ostringstream str_capa;
392 str_capa << "block_" << it->getMeshsetId() << ".poisson_ratio";
393 config_file_options.add_options()(
394 str_capa.str().c_str(),
395 po::value<double>(&block_data[it->getMeshsetId()].pOisson)
396 ->default_value(-2));
397
398 std::ostringstream str_init_temp;
399 str_init_temp << "block_" << it->getMeshsetId()
400 << ".initial_temperature";
401 config_file_options.add_options()(
402 str_init_temp.str().c_str(),
403 po::value<double>(&block_data[it->getMeshsetId()].initTemp)
404 ->default_value(0));
405 }
406 po::parsed_options parsed =
407 parse_config_file(ini_file, config_file_options, true);
408 store(parsed, vm);
409 po::notify(vm);
411 it)) {
412 if (block_data[it->getMeshsetId()].oRder == -1)
413 continue;
414 if (block_data[it->getMeshsetId()].oRder == order)
415 continue;
416 MOFEM_LOG_C("ELASTIC", Sev::inform, "Set block %d order to %d",
417 it->getMeshsetId(),
418 block_data[it->getMeshsetId()].oRder);
419 Range block_ents;
420 CHKERR moab.get_entities_by_handle(it->getMeshset(), block_ents,
421 true);
422 Range ents_to_set_order;
423 CHKERR moab.get_adjacencies(block_ents, 3, false,
424 ents_to_set_order,
425 moab::Interface::UNION);
426 ents_to_set_order = ents_to_set_order.subset_by_dimension(3);
427 CHKERR moab.get_adjacencies(block_ents, 2, false,
428 ents_to_set_order,
429 moab::Interface::UNION);
430 CHKERR moab.get_adjacencies(block_ents, 1, false,
431 ents_to_set_order,
432 moab::Interface::UNION);
433 CHKERR m_field.getInterface<CommInterface>()->synchroniseEntities(
434 ents_to_set_order);
435
436 CHKERR m_field.set_field_order(
437 ents_to_set_order, "DISPLACEMENT",
438 block_data[it->getMeshsetId()].oRder);
439 }
440 std::vector<std::string> additional_parameters;
441 additional_parameters =
442 collect_unrecognized(parsed.options, po::include_positional);
443 for (std::vector<std::string>::iterator vit =
444 additional_parameters.begin();
445 vit != additional_parameters.end(); vit++) {
446 MOFEM_LOG_C("ELASTIC", Sev::warning, "Unrecognized option %s",
447 vit->c_str());
448 }
449 }
450
451 // Update material parameters. Set material parameters block by
452 // block.
454 m_field, BLOCKSET | MAT_ELASTICSET, it)) {
455 const int id = it->getMeshsetId();
456 auto &bd = (*block_sets_ptr)[id];
457 if (block_data[id].yOung > 0)
458 bd.E = block_data[id].yOung;
459 if (block_data[id].pOisson >= -1)
460 bd.PoissonRatio = block_data[id].pOisson;
461 MOFEM_LOG_C("ELASTIC", Sev::inform, "Block %d", id);
462 MOFEM_LOG_C("ELASTIC", Sev::inform, "\tYoung modulus %3.4g", bd.E);
463 MOFEM_LOG_C("ELASTIC", Sev::inform, "\tPoisson ratio %3.4g",
464 bd.PoissonRatio);
465 }
466
468 };
469
470 // Add elastic element
471
472 boost::shared_ptr<std::map<int, HookeElement::BlockData>> block_sets_ptr =
473 boost::make_shared<std::map<int, HookeElement::BlockData>>();
474 CHKERR HookeElement::setBlocks(m_field, block_sets_ptr);
475 CHKERR setting_blocks_data_and_order_from_config_file(block_sets_ptr);
476
477 boost::shared_ptr<std::map<int, MassBlockData>> mass_block_sets_ptr =
478 boost::make_shared<std::map<int, MassBlockData>>();
479 CHKERR ConvectiveMassElement::setBlocks(m_field, mass_block_sets_ptr);
480
481 auto fe_lhs_ptr =
482 boost::make_shared<VolumeElementForcesAndSourcesCore>(m_field);
483 auto fe_rhs_ptr =
484 boost::make_shared<VolumeElementForcesAndSourcesCore>(m_field);
485 fe_lhs_ptr->getRuleHook = VolRule();
486 fe_rhs_ptr->getRuleHook = VolRule();
487
488 CHKERR AddHOOps<3, 3, 3>::add(fe_lhs_ptr->getOpPtrVector(), {H1},
489 "MESH_NODE_POSITIONS");
490 CHKERR AddHOOps<3, 3, 3>::add(fe_rhs_ptr->getOpPtrVector(), {H1},
491 "MESH_NODE_POSITIONS");
492
493 boost::shared_ptr<ForcesAndSourcesCore> prism_fe_lhs_ptr(
494 new PrismFE(m_field));
495 boost::shared_ptr<ForcesAndSourcesCore> prism_fe_rhs_ptr(
496 new PrismFE(m_field));
497
498 CHKERR HookeElement::addElasticElement(m_field, block_sets_ptr, "ELASTIC",
499 "DISPLACEMENT",
500 "MESH_NODE_POSITIONS", false);
501
502 auto add_skin_element_for_post_processing = [&]() {
504 Range elastic_element_ents;
506 "ELASTIC", 3, elastic_element_ents);
507 Skinner skin(&m_field.get_moab());
508 Range skin_faces; // skin faces from 3d ents
509 CHKERR skin.find_skin(0, elastic_element_ents, false, skin_faces);
510 Range proc_skin;
511 if (is_partitioned) {
512 CHKERR pcomm->filter_pstatus(skin_faces,
513 PSTATUS_SHARED | PSTATUS_MULTISHARED,
514 PSTATUS_NOT, -1, &proc_skin);
515 } else {
516 proc_skin = skin_faces;
517 }
518 CHKERR m_field.add_finite_element("POST_PROC_SKIN");
519 CHKERR m_field.modify_finite_element_add_field_row("POST_PROC_SKIN",
520 "DISPLACEMENT");
521 CHKERR m_field.modify_finite_element_add_field_col("POST_PROC_SKIN",
522 "DISPLACEMENT");
523 CHKERR m_field.modify_finite_element_add_field_data("POST_PROC_SKIN",
524 "DISPLACEMENT");
525 if (m_field.check_field("TEMP")) {
526 // CHKERR m_field.modify_finite_element_add_field_row("POST_PROC_SKIN",
527 // "TEMP");
528 // CHKERR m_field.modify_finite_element_add_field_col("POST_PROC_SKIN",
529 // "TEMP");
530 CHKERR m_field.modify_finite_element_add_field_data("POST_PROC_SKIN",
531 "TEMP");
532 }
534 "POST_PROC_SKIN", "MESH_NODE_POSITIONS");
535 CHKERR m_field.add_ents_to_finite_element_by_dim(proc_skin, 2,
536 "POST_PROC_SKIN");
538 };
539 CHKERR add_skin_element_for_post_processing();
540
541 auto data_at_pts = boost::make_shared<HookeElement::DataAtIntegrationPts>();
542 if (mesh_has_tets) {
543 CHKERR HookeElement::setOperators(fe_lhs_ptr, fe_rhs_ptr, block_sets_ptr,
544 "DISPLACEMENT", "MESH_NODE_POSITIONS",
545 false, true, MBTET, data_at_pts);
546 }
547 if (mesh_has_prisms) {
548 CHKERR HookeElement::setOperators(
549 prism_fe_lhs_ptr, prism_fe_rhs_ptr, block_sets_ptr, "DISPLACEMENT",
550 "MESH_NODE_POSITIONS", false, true, MBPRISM, data_at_pts);
551 }
552
553 if (test_nb == 4) {
554
555 auto thermal_strain =
558 constexpr double alpha = 1;
559 FTensor::Index<'i', 3> i;
560 FTensor::Index<'k', 3> j;
562 t_thermal_strain(i, j) = alpha * t_coords(2) * t_kd(i, j);
563 return t_thermal_strain;
564 };
565
566 fe_rhs_ptr->getOpPtrVector().push_back(
567 new HookeElement::OpAnalyticalInternalStrain_dx<0>(
568 "DISPLACEMENT", data_at_pts, thermal_strain));
569 }
570
571 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_mass_ptr(
573
574 for (auto &sit : *block_sets_ptr) {
575 for (auto &mit : *mass_block_sets_ptr) {
576 fe_mass_ptr->getOpPtrVector().push_back(
577 new HookeElement::OpCalculateMassMatrix("DISPLACEMENT",
578 "DISPLACEMENT", sit.second,
579 mit.second, data_at_pts));
580 }
581 }
582
583 // Add spring boundary condition applied on surfaces.
584 // This is only declaration not implementation.
585 CHKERR MetaSpringBC::addSpringElements(m_field, "DISPLACEMENT",
586 "MESH_NODE_POSITIONS");
587
588 // Implementation of spring element
589 // Create new instances of face elements for springs
590 boost::shared_ptr<FaceElementForcesAndSourcesCore> fe_spring_lhs_ptr(
592 boost::shared_ptr<FaceElementForcesAndSourcesCore> fe_spring_rhs_ptr(
594
595 CHKERR MetaSpringBC::setSpringOperators(m_field, fe_spring_lhs_ptr,
596 fe_spring_rhs_ptr, "DISPLACEMENT",
597 "MESH_NODE_POSITIONS");
598
599 // Add Simple Rod elements
600 // This is only declaration not implementation.
602 "MESH_NODE_POSITIONS");
603
604 // CHKERR m_field.add_ents_to_finite_element_by_type(edges_in_simple_rod,
605 // MBEDGE, "SIMPLE_ROD");
606
607 // Implementation of Simple Rod element
608 // Create new instances of edge elements for Simple Rod
609 boost::shared_ptr<EdgeEle> fe_simple_rod_lhs_ptr(new EdgeEle(m_field));
610 boost::shared_ptr<EdgeEle> fe_simple_rod_rhs_ptr(new EdgeEle(m_field));
611
612
614 m_field, fe_simple_rod_lhs_ptr, fe_simple_rod_rhs_ptr, "DISPLACEMENT",
615 "MESH_NODE_POSITIONS");
616
617 // Add body force element. This is only declaration of element. not its
618 // implementation.
619 CHKERR m_field.add_finite_element("BODY_FORCE");
620 CHKERR m_field.modify_finite_element_add_field_row("BODY_FORCE",
621 "DISPLACEMENT");
622 CHKERR m_field.modify_finite_element_add_field_col("BODY_FORCE",
623 "DISPLACEMENT");
624 CHKERR m_field.modify_finite_element_add_field_data("BODY_FORCE",
625 "DISPLACEMENT");
626 CHKERR m_field.modify_finite_element_add_field_data("BODY_FORCE",
627 "MESH_NODE_POSITIONS");
628
630 m_field, BLOCKSET | BODYFORCESSET, it)) {
631 Range tets;
632 CHKERR m_field.get_moab().get_entities_by_dimension(it->meshset, 3, tets,
633 true);
634 CHKERR m_field.add_ents_to_finite_element_by_dim(tets, 3, "BODY_FORCE");
635 }
636 CHKERR m_field.build_finite_elements("BODY_FORCE");
637
638 // Add Neumann forces, i.e. pressure or traction forces applied on body
639 // surface. This is only declaration not implementation.
640 CHKERR MetaNeumannForces::addNeumannBCElements(m_field, "DISPLACEMENT");
641 CHKERR MetaNodalForces::addElement(m_field, "DISPLACEMENT");
642 CHKERR MetaEdgeForces::addElement(m_field, "DISPLACEMENT");
643
644 // Add fluid pressure finite elements. This is special pressure on the
645 // surface from fluid, i.e. pressure which linearly change with the depth.
646 FluidPressure fluid_pressure_fe(m_field);
647 // This function only declare element. Element is implemented by operators
648 // in class FluidPressure.
649 fluid_pressure_fe.addNeumannFluidPressureBCElements("DISPLACEMENT");
650
651 // Add elements for thermo elasticity if temperature field is defined.
652 ThermalStressElement thermal_stress_elem(m_field);
653 // Check if TEMP field exist, and then add element.
654 if (!m_field.check_field("TEMP")) {
655 bool add_temp_field = false;
657 if (block_data[it->getMeshsetId()].initTemp != 0) {
658 add_temp_field = true;
659 break;
660 }
661 }
662 if (add_temp_field) {
663 CHKERR m_field.add_field("TEMP", H1, AINSWORTH_LEGENDRE_BASE, 1,
664 MB_TAG_SPARSE, MF_ZERO);
665
666 CHKERR m_field.add_ents_to_field_by_type(0, MBTET, "TEMP");
667 CHKERR m_field.set_field_order(0, MBVERTEX, "TEMP", 1);
668 }
669 }
670 if (m_field.check_field("TEMP")) {
671 CHKERR thermal_stress_elem.addThermalStressElement(
672 "ELASTIC", "DISPLACEMENT", "TEMP");
673 }
674
675 // All is declared, at this point build fields first,
676 CHKERR m_field.build_fields();
677 // If 10-node test are on the mesh, use mid nodes to set HO-geometry. Class
678 // Projection10NodeCoordsOnField
679 // do the trick.
680 Projection10NodeCoordsOnField ent_method_material(m_field,
681 "MESH_NODE_POSITIONS");
682 CHKERR m_field.loop_dofs("MESH_NODE_POSITIONS", ent_method_material);
683 if (m_field.check_field("TEMP")) {
685 if (block_data[it->getMeshsetId()].initTemp != 0) {
686 MOFEM_LOG_C("ELASTIC", Sev::inform,
687 "Set block %d temperature to %3.2g\n", it->getMeshsetId(),
688 block_data[it->getMeshsetId()].initTemp);
689 Range block_ents;
690 CHKERR moab.get_entities_by_handle(it->meshset, block_ents, true);
691 Range vertices;
692 CHKERR moab.get_connectivity(block_ents, vertices, true);
693 CHKERR m_field.getInterface<FieldBlas>()->setField(
694 block_data[it->getMeshsetId()].initTemp, MBVERTEX, vertices,
695 "TEMP");
696 }
697 }
698 }
699
700 // Build database for elements. Actual implementation of element is not need
701 // here, only elements has to be declared.
703 // Build adjacencies between elements and field entities
704 CHKERR m_field.build_adjacencies(bit_level0);
705
706 // Register MOFEM DM implementation in PETSc
708
709 // Create DM manager
710 auto dm = createDM(PETSC_COMM_WORLD, "MOFEM");
711 CHKERR DMMoFEMCreateMoFEM(dm, &m_field, "ELASTIC_PROB", bit_level0);
712 CHKERR DMSetFromOptions(dm);
713 CHKERR DMMoFEMSetIsPartitioned(dm, is_partitioned);
714 // Add elements to DM manager
715 CHKERR DMMoFEMAddElement(dm, "ELASTIC");
716 CHKERR DMMoFEMAddElement(dm, "SPRING");
717 CHKERR DMMoFEMAddElement(dm, "SIMPLE_ROD");
718 CHKERR DMMoFEMAddElement(dm, "BODY_FORCE");
719 CHKERR DMMoFEMAddElement(dm, "FLUID_PRESSURE_FE");
720 CHKERR DMMoFEMAddElement(dm, "FORCE_FE");
721 CHKERR DMMoFEMAddElement(dm, "PRESSURE_FE");
722 CHKERR DMMoFEMAddElement(dm, "POST_PROC_SKIN");
723 CHKERR DMSetUp(dm);
724
725 // Create matrices & vectors. Note that native PETSc DM interface is used,
726 // but under the PETSc interface MoFEM implementation is running.
729 auto D = vectorDuplicate(F);
730 auto D0 = vectorDuplicate(F);
733 CHKERR MatSetOption(Aij, MAT_SPD, PETSC_TRUE);
734
735 // Initialise mass matrix
737 if (is_calculating_frequency == PETSC_TRUE) {
738 Mij = matDuplicate(Aij, MAT_DO_NOT_COPY_VALUES);
739 CHKERR MatSetOption(Mij, MAT_SPD, PETSC_TRUE);
740 // MatView(Mij, PETSC_VIEWER_STDOUT_SELF);
741 }
742
743 // Assign global matrix/vector contributed by springs
744 fe_spring_lhs_ptr->ksp_B = Aij;
745 fe_spring_rhs_ptr->ksp_f = F;
746
747 // Assign global matrix/vector contributed by Simple Rod
748 fe_simple_rod_lhs_ptr->ksp_B = Aij;
749 fe_simple_rod_rhs_ptr->ksp_f = F;
750
751 // Zero vectors and matrices
752 CHKERR VecZeroEntries(F);
753 CHKERR VecGhostUpdateBegin(F, INSERT_VALUES, SCATTER_FORWARD);
754 CHKERR VecGhostUpdateEnd(F, INSERT_VALUES, SCATTER_FORWARD);
755 CHKERR VecZeroEntries(D);
756 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
757 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
758 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
759 CHKERR MatZeroEntries(Aij);
760
761 // Below particular implementations of finite elements are used to assemble
762 // problem matrixes and vectors. Implementation of element does not change
763 // how element is declared.
764
765 // Assemble Aij and F. Define Dirichlet bc element, which sets constrains
766 // to MatrixDouble and the right hand side vector.
767
768 // if normally defined boundary conditions are not found,
769 // DirichletDisplacementBc will try to use DISPLACEMENT blockset. Two
770 // implementations are available, depending how BC is defined on mesh file.
771 auto dirichlet_bc_ptr = boost::make_shared<DirichletDisplacementBc>(
772 m_field, "DISPLACEMENT", Aij, D0, F);
773
774 // That sets Dirichlet bc objects that problem is linear, i.e. no newton
775 // (SNES) solver is run for this problem.
776 dirichlet_bc_ptr->snes_ctx = FEMethod::CTX_SNESNONE;
777 dirichlet_bc_ptr->ts_ctx = FEMethod::CTX_TSNONE;
778
779 // D0 vector will store initial displacements
780 CHKERR VecZeroEntries(D0);
781 CHKERR VecGhostUpdateBegin(D0, INSERT_VALUES, SCATTER_FORWARD);
782 CHKERR VecGhostUpdateEnd(D0, INSERT_VALUES, SCATTER_FORWARD);
783 CHKERR DMoFEMMeshToLocalVector(dm, D0, INSERT_VALUES, SCATTER_REVERSE);
784 // Run dirichlet_bc, from that on the mesh set values in vector D0. Run
785 // implementation
786 // of particular dirichlet_bc.
787 CHKERR DMoFEMPreProcessFiniteElements(dm, dirichlet_bc_ptr.get());
788 // Set values from D0 on the field (on the mesh)
789
790 CHKERR VecGhostUpdateBegin(D0, INSERT_VALUES, SCATTER_FORWARD);
791 CHKERR VecGhostUpdateEnd(D0, INSERT_VALUES, SCATTER_FORWARD);
792 CHKERR DMoFEMMeshToLocalVector(dm, D0, INSERT_VALUES, SCATTER_REVERSE);
793
794 // Calculate residual forces as result of applied kinematic constrains. Run
795 // implementation
796 // of particular finite element implementation. Look how
797 // NonlinearElasticElement is implemented,
798 // in that case. We run NonlinearElasticElement with hook material.
799 // Calculate right hand side vector
800 fe_rhs_ptr->snes_f = F;
801 prism_fe_rhs_ptr->snes_f = F;
802 MOFEM_LOG("ELASTIC", Sev::inform) << "Assemble external force vector ...";
803 CHKERR DMoFEMLoopFiniteElements(dm, "ELASTIC", fe_rhs_ptr);
804 CHKERR DMoFEMLoopFiniteElements(dm, "ELASTIC", prism_fe_rhs_ptr);
805 MOFEM_LOG("ELASTIC", Sev::inform) << "done";
806 // Assemble matrix
807 fe_lhs_ptr->snes_B = Aij;
808 prism_fe_lhs_ptr->snes_B = Aij;
809 MOFEM_LOG("ELASTIC", Sev::inform) << "Calculate stiffness matrix ...";
810 CHKERR DMoFEMLoopFiniteElements(dm, "ELASTIC", fe_lhs_ptr);
811 CHKERR DMoFEMLoopFiniteElements(dm, "ELASTIC", prism_fe_lhs_ptr);
812 MOFEM_LOG("ELASTIC", Sev::inform) << "done";
813
814 // Assemble springs
815 CHKERR DMoFEMLoopFiniteElements(dm, "SPRING", fe_spring_lhs_ptr);
816 CHKERR DMoFEMLoopFiniteElements(dm, "SPRING", fe_spring_rhs_ptr);
817
818 // Assemble Simple Rod
819 CHKERR DMoFEMLoopFiniteElements(dm, "SIMPLE_ROD", fe_simple_rod_lhs_ptr);
820 CHKERR DMoFEMLoopFiniteElements(dm, "SIMPLE_ROD", fe_simple_rod_rhs_ptr);
821
822 if (is_calculating_frequency == PETSC_TRUE) {
823 // Assemble mass matrix
824 fe_mass_ptr->snes_B = Mij;
825 MOFEM_LOG("ELASTIC", Sev::inform) << "Calculate mass matrix ...";
826 CHKERR DMoFEMLoopFiniteElements(dm, "ELASTIC", fe_mass_ptr);
827 MOFEM_LOG("ELASTIC", Sev::inform) << "done";
828 }
829
830 // MatView(Aij, PETSC_VIEWER_STDOUT_SELF);
831
832 // Assemble pressure and traction forces. Run particular implemented for do
833 // this, see
834 // MetaNeumannForces how this is implemented.
835 boost::ptr_map<std::string, NeumannForcesSurface> neumann_forces;
837 F, "DISPLACEMENT");
838
839 {
840 boost::ptr_map<std::string, NeumannForcesSurface>::iterator mit =
841 neumann_forces.begin();
842 for (; mit != neumann_forces.end(); mit++) {
843 CHKERR DMoFEMLoopFiniteElements(dm, mit->first.c_str(),
844 &mit->second->getLoopFe());
845 }
846 }
847 // Assemble forces applied to nodes, see implementation in NodalForce
848 boost::ptr_map<std::string, NodalForce> nodal_forces;
849 CHKERR MetaNodalForces::setOperators(m_field, nodal_forces, F,
850 "DISPLACEMENT");
851
852 {
853 boost::ptr_map<std::string, NodalForce>::iterator fit =
854 nodal_forces.begin();
855 for (; fit != nodal_forces.end(); fit++) {
856 CHKERR DMoFEMLoopFiniteElements(dm, fit->first.c_str(),
857 &fit->second->getLoopFe());
858 }
859 }
860 // Assemble edge forces
861 boost::ptr_map<std::string, EdgeForce> edge_forces;
862 CHKERR MetaEdgeForces::setOperators(m_field, edge_forces, F,
863 "DISPLACEMENT");
864 {
865 auto fit = edge_forces.begin();
866 for (; fit != edge_forces.end(); fit++) {
867 auto &fe = fit->second->getLoopFe();
868 CHKERR DMoFEMLoopFiniteElements(dm, fit->first.c_str(), &fe);
869 }
870 }
871 // Assemble body forces, implemented in BodyForceConstantField
872 BodyForceConstantField body_forces_methods(m_field);
874 m_field, BLOCKSET | BODYFORCESSET, it)) {
875 CHKERR body_forces_methods.addBlock("DISPLACEMENT", F,
876 it->getMeshsetId());
877 }
878 CHKERR DMoFEMLoopFiniteElements(dm, "BODY_FORCE",
879 &body_forces_methods.getLoopFe());
880 // Assemble fluid pressure forces
882 fluid_pressure_fe.getLoopFe().getOpPtrVector(), {},
883 "MESH_NODE_POSITIONS");
884 CHKERR fluid_pressure_fe.setNeumannFluidPressureFiniteElementOperators(
885 "DISPLACEMENT", F, false, true);
886
887 CHKERR DMoFEMLoopFiniteElements(dm, "FLUID_PRESSURE_FE",
888 &fluid_pressure_fe.getLoopFe());
889 // Apply kinematic constrain to right hand side vector and matrix
890 CHKERR DMoFEMPostProcessFiniteElements(dm, dirichlet_bc_ptr.get());
891
892 // Matrix View
893 PetscViewerPushFormat(
894 PETSC_VIEWER_STDOUT_SELF,
895 PETSC_VIEWER_ASCII_MATLAB); /// PETSC_VIEWER_ASCII_DENSE,
896 /// PETSC_VIEWER_ASCII_MATLAB
897 // MatView(Aij, PETSC_VIEWER_STDOUT_SELF);
898 // MatView(Aij,PETSC_VIEWER_DRAW_WORLD);//PETSC_VIEWER_STDOUT_WORLD);
899 // std::string wait;
900 // std::cin >> wait;
901
902 if (is_calculating_frequency == PETSC_TRUE) {
903 CHKERR MatAssemblyBegin(Mij, MAT_FINAL_ASSEMBLY);
904 CHKERR MatAssemblyEnd(Mij, MAT_FINAL_ASSEMBLY);
905 }
906
907 // Set matrix positive defined and symmetric for Cholesky and icc
908 // pre-conditioner
909
910 CHKERR MatSetOption(Aij, MAT_SPD, PETSC_TRUE);
911 CHKERR VecGhostUpdateBegin(F, ADD_VALUES, SCATTER_REVERSE);
912 CHKERR VecGhostUpdateEnd(F, ADD_VALUES, SCATTER_REVERSE);
913 CHKERR VecAssemblyBegin(F);
914 CHKERR VecAssemblyEnd(F);
915 CHKERR VecScale(F, -1);
916
917 // Create solver
918 auto solver = createKSP(PETSC_COMM_WORLD);
919 CHKERR KSPSetDM(solver, dm);
920 CHKERR KSPSetFromOptions(solver);
921 CHKERR KSPSetOperators(solver, Aij, Aij);
922
923 // Setup multi-grid pre-conditioner if set from command line
924 {
925 // from PETSc example ex42.c
926 PetscBool same = PETSC_FALSE;
927 PC pc;
928 CHKERR KSPGetPC(solver, &pc);
929 PetscObjectTypeCompare((PetscObject)pc, PCMG, &same);
930 if (same) {
932 pc, createPCMGSetUpViaApproxOrdersCtx(dm, Aij, true));
933 CHKERR PCSetFromOptions(pc);
934 } else {
935 // Operators are already set, do not use DM for doing that
936 CHKERR KSPSetDMActive(solver, PETSC_FALSE);
937 }
938 }
939 CHKERR KSPSetInitialGuessKnoll(solver, PETSC_FALSE);
940 CHKERR KSPSetInitialGuessNonzero(solver, PETSC_TRUE);
941 // Set up solver
942 CHKERR KSPSetUp(solver);
943
945
946 auto set_post_proc_skin = [&](auto &post_proc_skin) {
948 CHKERR AddHOOps<2, 3, 3>::add(post_proc_skin.getOpPtrVector(), {},
949 "MESH_NODE_POSITIONS");
950 auto disp_ptr = boost::make_shared<MatrixDouble>();
951 auto mesh_pos_ptr = boost::make_shared<MatrixDouble>();
952 post_proc_skin.getOpPtrVector().push_back(
953 new OpCalculateVectorFieldValues<3>("DISPLACEMENT", disp_ptr));
954 post_proc_skin.getOpPtrVector().push_back(
955 new OpCalculateVectorFieldValues<3>("MESH_NODE_POSITIONS",
956 mesh_pos_ptr));
957
958 auto side_loop =
960 m_field, "ELASTIC", 3);
961 CHKERR AddHOOps<3, 3, 3>::add(side_loop->getOpPtrVector(), {H1},
962 "MESH_NODE_POSITIONS");
963 side_loop->getOpPtrVector().push_back(
964 new OpCalculateVectorFieldGradient<3, 3>("DISPLACEMENT",
965 data_at_pts->hMat));
966 side_loop->getOpPtrVector().push_back(
967 new OpCalculateVectorFieldGradient<3, 3>("MESH_NODE_POSITIONS",
968 data_at_pts->HMat));
969 post_proc_skin.getOpPtrVector().push_back(side_loop);
970
971 OpPPMap::DataMapVec scalar_map;
972 OpPPMap::DataMapMat vector_map{
973 {"DISPLACEMENT", disp_ptr},
974 {"MESH_NODE_POSITIONS", mesh_pos_ptr}};
975 OpPPMap::DataMapMat tensor_map{
976 {"DISPLACEMENT_GRAD", data_at_pts->hMat}};
977 if (m_field.check_field("TEMP")) {
978 auto temp_ptr = boost::make_shared<VectorDouble>();
979 auto temp_grad_ptr = boost::make_shared<MatrixDouble>();
980 post_proc_skin.getOpPtrVector().push_back(
981 new OpCalculateScalarFieldValues("TEMP", temp_ptr));
982 post_proc_skin.getOpPtrVector().push_back(
983 new OpCalculateScalarFieldGradient<3>("TEMP", temp_grad_ptr));
984 scalar_map["TEMP"] = temp_ptr;
985 vector_map["TEMP_GRAD"] = temp_grad_ptr;
986 }
987 post_proc_skin.getOpPtrVector().push_back(
988 new HookeElement::OpPostProcHookeElement<
990 "DISPLACEMENT", data_at_pts, *block_sets_ptr,
991 post_proc_skin.getPostProcMesh(),
992 post_proc_skin.getMapGaussPts(), true, true));
993 post_proc_skin.getOpPtrVector().push_back(new OpPPMap(
994 post_proc_skin.getPostProcMesh(), post_proc_skin.getMapGaussPts(),
995 scalar_map, vector_map, tensor_map, {}));
997 };
998
999 auto set_post_proc_tets = [&](auto &post_proc) {
1001 // Add operators to the elements, starting with some generic operators
1002 CHKERR AddHOOps<3, 3, 3>::add(post_proc.getOpPtrVector(), {H1},
1003 "MESH_NODE_POSITIONS");
1004 auto disp_ptr = boost::make_shared<MatrixDouble>();
1005 auto mesh_pos_ptr = boost::make_shared<MatrixDouble>();
1006 auto disp_grad_ptr = boost::make_shared<MatrixDouble>();
1007 post_proc.getOpPtrVector().push_back(
1008 new OpCalculateVectorFieldValues<3>("DISPLACEMENT", disp_ptr));
1009 post_proc.getOpPtrVector().push_back(
1010 new OpCalculateVectorFieldValues<3>("MESH_NODE_POSITIONS",
1011 mesh_pos_ptr));
1012 post_proc.getOpPtrVector().push_back(
1013 new OpCalculateVectorFieldGradient<3, 3>("DISPLACEMENT",
1014 disp_grad_ptr));
1015 OpPPMap::DataMapVec scalar_map;
1016 OpPPMap::DataMapMat vector_map{
1017 {"DISPLACEMENT", disp_ptr},
1018 {"MESH_NODE_POSITIONS", mesh_pos_ptr}};
1019 OpPPMap::DataMapMat tensor_map{
1020 {"DISPLACEMENT_GRAD", disp_grad_ptr}};
1021 if (m_field.check_field("TEMP")) {
1022 auto temp_ptr = boost::make_shared<VectorDouble>();
1023 auto temp_grad_ptr = boost::make_shared<MatrixDouble>();
1024 post_proc.getOpPtrVector().push_back(
1025 new OpCalculateScalarFieldValues("TEMP", temp_ptr));
1026 post_proc.getOpPtrVector().push_back(
1027 new OpCalculateScalarFieldGradient<3>("TEMP", temp_grad_ptr));
1028 scalar_map["TEMP"] = temp_ptr;
1029 vector_map["TEMP_GRAD"] = temp_grad_ptr;
1030 }
1031 // Add problem specific operator on element to post-process stresses
1032 post_proc.getOpPtrVector().push_back(new PostProcHookStress(
1033 m_field, post_proc.getPostProcMesh(), post_proc.getMapGaussPts(),
1034 post_proc.getPostProcElements(), "DISPLACEMENT", disp_grad_ptr,
1035 block_sets_ptr.get()));
1036 post_proc.getOpPtrVector().push_back(new OpPPMap(
1037 post_proc.getPostProcMesh(), post_proc.getMapGaussPts(), scalar_map,
1038 vector_map, tensor_map, {}));
1040 };
1041
1042 auto set_post_proc_edge = [&](auto &post_proc_edge) {
1044 auto disp_ptr = boost::make_shared<MatrixDouble>();
1045 post_proc_edge.getOpPtrVector().push_back(
1046 new OpCalculateVectorFieldValues<3>("DISPLACEMENT", disp_ptr));
1047 post_proc_edge.getOpPtrVector().push_back(new OpPPMap(
1048 post_proc_edge.getPostProcMesh(), post_proc_edge.getMapGaussPts(), {},
1049 {{"DISPLACEMENT", disp_ptr}}, {}, {}));
1051 };
1052
1053 auto set_post_proc_prisms = [&](auto &prism_post_proc) {
1055 boost::shared_ptr<MatrixDouble> inv_jac_ptr(new MatrixDouble);
1056 prism_post_proc.getOpPtrVector().push_back(
1057 new OpCalculateInvJacForFatPrism(inv_jac_ptr));
1058 prism_post_proc.getOpPtrVector().push_back(
1059 new OpSetInvJacH1ForFatPrism(inv_jac_ptr));
1060 auto disp_ptr = boost::make_shared<MatrixDouble>();
1061 auto mesh_pos_ptr = boost::make_shared<MatrixDouble>();
1062 auto disp_grad_ptr = boost::make_shared<MatrixDouble>();
1063 prism_post_proc.getOpPtrVector().push_back(
1064 new OpCalculateVectorFieldValues<3>("DISPLACEMENT", disp_ptr));
1065 prism_post_proc.getOpPtrVector().push_back(
1066 new OpCalculateVectorFieldValues<3>("MESH_NODE_POSITIONS",
1067 mesh_pos_ptr));
1068 prism_post_proc.getOpPtrVector().push_back(
1069 new OpCalculateVectorFieldGradient<3, 3>("DISPLACEMENT",
1070 disp_grad_ptr));
1071 prism_post_proc.getOpPtrVector().push_back(new PostProcHookStress(
1072 m_field, prism_post_proc.getPostProcMesh(),
1073 prism_post_proc.getMapGaussPts(),
1074 prism_post_proc.getPostProcElements(), "DISPLACEMENT",
1075 disp_grad_ptr, block_sets_ptr.get()));
1076 prism_post_proc.getOpPtrVector().push_back(new OpPPMap(
1077 prism_post_proc.getPostProcMesh(),
1078 prism_post_proc.getMapGaussPts(), {},
1079 {{"DISPLACEMENT", disp_ptr},
1080 {"MESH_NODE_POSITIONS", mesh_pos_ptr}},
1081 {{"DISPLACEMENT_GRAD", disp_grad_ptr}}, {}));
1083 };
1084
1086 m_field);
1087 BasicPostProcFatPrism prism_post_proc(m_field);
1089 m_field);
1091 m_field);
1092
1093 auto is_prism = [](FEMethod *fe_ptr) {
1094 return fe_ptr->numeredEntFiniteElementPtr->getEntType() == MBPRISM;
1095 };
1096 prism_post_proc.exeTestHook = is_prism;
1097 post_proc.exeTestHook = [is_prism](FEMethod *fe_ptr) {
1098 return !is_prism(fe_ptr);
1099 };
1100
1101 CHKERR set_post_proc_skin(post_proc_skin);
1102 CHKERR set_post_proc_tets(post_proc);
1103 CHKERR set_post_proc_prisms(prism_post_proc);
1104 CHKERR set_post_proc_edge(post_proc_edge);
1105
1106 PetscBool field_eval_flag = PETSC_FALSE;
1107 std::array<double, 3> field_eval_coords;
1108 boost::shared_ptr<FieldEvaluatorInterface::SetPtsData> field_eval_data;
1109 PetscInt coords_dim = 3;
1110 CHKERR PetscOptionsGetRealArray(NULL, NULL, "-field_eval_coords",
1111 field_eval_coords.data(), &coords_dim,
1112 &field_eval_flag);
1113
1114 auto scalar_field_ptr = boost::make_shared<VectorDouble>();
1115 auto vector_field_ptr = boost::make_shared<MatrixDouble>();
1116 auto tensor_field_ptr = boost::make_shared<MatrixDouble>();
1117
1118 if (field_eval_flag) {
1119 field_eval_data = m_field.getInterface<FieldEvaluatorInterface>()
1120 ->getData<VolumeElementForcesAndSourcesCore>();
1121 CHKERR m_field.getInterface<FieldEvaluatorInterface>()->buildTree<3>(
1122 field_eval_data, "ELASTIC");
1123
1124 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
1125 auto no_rule = [](int, int, int) { return -1; };
1126
1127 auto field_eval_fe_ptr = field_eval_data->feMethodPtr;
1128 field_eval_fe_ptr->getRuleHook = no_rule;
1129
1130 if (m_field.check_field("TEMP")) {
1131 field_eval_fe_ptr->getOpPtrVector().push_back(
1132 new OpCalculateScalarFieldValues("TEMP", scalar_field_ptr));
1133 }
1134 field_eval_fe_ptr->getOpPtrVector().push_back(
1135 new OpCalculateVectorFieldValues<3>("DISPLACEMENT", vector_field_ptr));
1136 field_eval_fe_ptr->getOpPtrVector().push_back(
1137 new OpCalculateVectorFieldGradient<3, 3>("DISPLACEMENT", tensor_field_ptr));
1138 }
1139
1140 // Temperature field is defined on the mesh
1141 if (m_field.check_field("TEMP")) {
1142
1143 // Create thermal vector
1144 Vec F_thermal;
1145 CHKERR VecDuplicate(F, &F_thermal);
1146
1147 // Set up implementation for calculation of thermal stress vector. Look
1148 // how thermal stresses and vector is assembled in ThermalStressElement.
1149 CHKERR thermal_stress_elem.setThermalStressRhsOperators(
1150 "DISPLACEMENT", "TEMP", F_thermal);
1151
1152 SeriesRecorder *recorder_ptr;
1153 CHKERR m_field.getInterface(recorder_ptr);
1154
1155 // Read time series and do thermo-elastic analysis, this is when time
1156 // dependent
1157 // temperature problem was run before on the mesh. It means that before
1158 // non-stationary
1159 // problem was solved for temperature and filed "TEMP" is stored for
1160 // subsequent time
1161 // steps in the recorder.
1162 if (recorder_ptr->check_series("THEMP_SERIES")) {
1163 // This is time dependent case, so loop of data series stored by tape
1164 // recorder.
1165 // Loop over time steps
1166 for (_IT_SERIES_STEPS_BY_NAME_FOR_LOOP_(recorder_ptr, "THEMP_SERIES",
1167 sit)) {
1168 MOFEM_LOG_C("ELASTIC", Sev::inform, "Process step %d",
1169 sit->get_step_number());
1170 // Load field data for this time step
1171 CHKERR recorder_ptr->load_series_data("THEMP_SERIES",
1172 sit->get_step_number());
1173
1174 CHKERR VecZeroEntries(F_thermal);
1175 CHKERR VecGhostUpdateBegin(F_thermal, INSERT_VALUES, SCATTER_FORWARD);
1176 CHKERR VecGhostUpdateEnd(F_thermal, INSERT_VALUES, SCATTER_FORWARD);
1177
1178 // Calculate the right-hand side vector as result of thermal stresses.
1179 // It MetaNodalForces
1180 // that on "ELASTIC" element data structure the element implementation
1181 // in thermal_stress_elem
1182 // is executed.
1184 dm, "ELASTIC", &thermal_stress_elem.getLoopThermalStressRhs());
1185
1186 // Assemble vector
1187 CHKERR VecAssemblyBegin(F_thermal);
1188 CHKERR VecAssemblyEnd(F_thermal);
1189 // Accumulate ghost dofs
1190 CHKERR VecGhostUpdateBegin(F_thermal, ADD_VALUES, SCATTER_REVERSE);
1191 CHKERR VecGhostUpdateEnd(F_thermal, ADD_VALUES, SCATTER_REVERSE);
1192
1193 // Calculate norm of vector and print values
1194 PetscReal nrm_F;
1195 CHKERR VecNorm(F, NORM_2, &nrm_F);
1196
1197 MOFEM_LOG_C("ELASTIC", Sev::inform, "norm2 F = %6.4e", nrm_F);
1198 PetscReal nrm_F_thermal;
1199 CHKERR VecNorm(F_thermal, NORM_2, &nrm_F_thermal);
1200 MOFEM_LOG_C("ELASTIC", Sev::inform, "norm2 F_thermal = %6.4e",
1201 nrm_F_thermal);
1202
1203 CHKERR VecScale(F_thermal, -1);
1204 // check this !!!
1205 CHKERR VecAXPY(F_thermal, 1, F);
1206
1207 // Set dirichlet boundary to thermal stresses vector
1208 dirichlet_bc_ptr->snes_x = D;
1209 dirichlet_bc_ptr->snes_f = F_thermal;
1210 CHKERR DMoFEMPostProcessFiniteElements(dm, dirichlet_bc_ptr.get());
1211
1212 // Solve problem
1213 CHKERR KSPSolve(solver, F_thermal, D);
1214 // Add boundary conditions vector
1215 CHKERR VecAXPY(D, 1., D0);
1216 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
1217 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
1218
1219 // Save data on the mesh
1220 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
1221
1222 // Save data on mesh
1223 CHKERR DMoFEMPreProcessFiniteElements(dm, dirichlet_bc_ptr.get());
1224
1225 if (field_eval_flag) {
1227 ->evalFEAtThePoint<3>(
1228 field_eval_coords.data(), 1e-12, "ELASTIC_PROB", "ELASTIC",
1229 field_eval_data, m_field.get_comm_rank(),
1230 m_field.get_comm_rank(), nullptr, MF_EXIST, QUIET);
1231 if (scalar_field_ptr->size()) {
1232 auto t_temp = getFTensor0FromVec(*scalar_field_ptr);
1233 MOFEM_LOG("ELASTIC_SYNC", Sev::inform)
1234 << "Eval point TEMP: " << t_temp;
1235 }
1236 if (vector_field_ptr->size1()) {
1237 FTensor::Index<'i', 3> i;
1238 auto t_disp = getFTensor1FromMat<3>(*vector_field_ptr);
1239 MOFEM_LOG("ELASTIC_SYNC", Sev::inform)
1240 << "Eval point DISPLACEMENT magnitude: "
1241 << sqrt(t_disp(i) * t_disp(i));
1242 }
1243 if (tensor_field_ptr->size1()) {
1244 FTensor::Index<'i', 3> i;
1245 auto t_disp_grad = getFTensor2FromMat<3, 3>(*tensor_field_ptr);
1246 MOFEM_LOG("ELASTIC_SYNC", Sev::inform)
1247 << "Eval point DISPLACEMENT_GRAD trace: " << t_disp_grad(i, i);
1248 }
1249
1251 }
1252
1253 // Post-process results
1254 if (is_post_proc_volume == PETSC_TRUE) {
1255 MOFEM_LOG("ELASTIC", Sev::inform) << "Write output file ...";
1256 CHKERR DMoFEMLoopFiniteElements(dm, "ELASTIC", &post_proc);
1257 std::ostringstream o1;
1258 o1 << "out_" << sit->step_number << ".h5m";
1259 if (!test_nb)
1260 CHKERR post_proc.writeFile(o1.str().c_str());
1261 MOFEM_LOG("ELASTIC", Sev::inform) << "done ...";
1262 }
1263
1264 MOFEM_LOG("ELASTIC", Sev::inform) << "Write output file skin ...";
1265 CHKERR DMoFEMLoopFiniteElements(dm, "POST_PROC_SKIN",
1266 &post_proc_skin);
1267 std::ostringstream o1_skin;
1268 o1_skin << "out_skin_" << sit->step_number << ".h5m";
1269 if (!test_nb)
1270 CHKERR post_proc_skin.writeFile(o1_skin.str().c_str());
1271 MOFEM_LOG("ELASTIC", Sev::inform) << "done ...";
1272 }
1273 } else {
1274
1275 // This is a case when stationary problem for temperature was solved.
1276 CHKERR VecZeroEntries(F_thermal);
1277 CHKERR VecGhostUpdateBegin(F_thermal, INSERT_VALUES, SCATTER_FORWARD);
1278 CHKERR VecGhostUpdateEnd(F_thermal, INSERT_VALUES, SCATTER_FORWARD);
1279
1280 // Calculate the right-hand side vector with thermal stresses
1282 dm, "ELASTIC", &thermal_stress_elem.getLoopThermalStressRhs());
1283
1284 // Assemble vector
1285 CHKERR VecAssemblyBegin(F_thermal);
1286 CHKERR VecAssemblyEnd(F_thermal);
1287
1288 // Accumulate ghost dofs
1289 CHKERR VecGhostUpdateBegin(F_thermal, ADD_VALUES, SCATTER_REVERSE);
1290 CHKERR VecGhostUpdateEnd(F_thermal, ADD_VALUES, SCATTER_REVERSE);
1291
1292 // Calculate norm
1293 PetscReal nrm_F;
1294 CHKERR VecNorm(F, NORM_2, &nrm_F);
1295
1296 MOFEM_LOG_C("ELASTIC", Sev::inform, "norm2 F = %6.4e", nrm_F);
1297 PetscReal nrm_F_thermal;
1298 CHKERR VecNorm(F_thermal, NORM_2, &nrm_F_thermal);
1299
1300 MOFEM_LOG_C("ELASTIC", Sev::inform, "norm2 F_thermal = %6.4e",
1301 nrm_F_thermal);
1302
1303 // Add thermal stress vector and other forces vector
1304 CHKERR VecScale(F_thermal, -1);
1305 CHKERR VecAXPY(F_thermal, 1, F);
1306
1307 // Apply kinetic boundary conditions
1308 dirichlet_bc_ptr->snes_x = D;
1309 dirichlet_bc_ptr->snes_f = F_thermal;
1310 CHKERR DMoFEMPostProcessFiniteElements(dm, dirichlet_bc_ptr.get());
1311
1312 // Solve problem
1313 CHKERR KSPSolve(solver, F_thermal, D);
1314 CHKERR VecAXPY(D, 1., D0);
1315
1316 // Update ghost values for solution vector
1317 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
1318 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
1319 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
1320
1321 // Save data on mesh
1322 if (is_post_proc_volume == PETSC_TRUE) {
1323 MOFEM_LOG("ELASTIC", Sev::inform) << "Write output file ...";
1324 CHKERR DMoFEMLoopFiniteElements(dm, "ELASTIC", &post_proc);
1325 // Save results to file
1326 if (!test_nb)
1327 CHKERR post_proc.writeFile("out.h5m");
1328 MOFEM_LOG("ELASTIC", Sev::inform) << "done";
1329 }
1330
1331 MOFEM_LOG("ELASTIC", Sev::inform) << "Write output file skin ...";
1332 CHKERR DMoFEMLoopFiniteElements(dm, "POST_PROC_SKIN", &post_proc_skin);
1333 if (!test_nb)
1334 CHKERR post_proc_skin.writeFile("out_skin.h5m");
1335 MOFEM_LOG("ELASTIC", Sev::inform) << "done";
1336 }
1337
1338 // Destroy vector, no needed any more
1339 CHKERR VecDestroy(&F_thermal);
1340 } else {
1341 // Elastic analysis no temperature field
1342 // VecView(F, PETSC_VIEWER_STDOUT_WORLD);
1343 // Solve for vector D
1344 CHKERR KSPSolve(solver, F, D);
1345
1346 // VecView(D, PETSC_VIEWER_STDOUT_WORLD);
1347 // cerr << F;
1348
1349 // Add kinetic boundary conditions
1350 CHKERR VecAXPY(D, 1., D0);
1351 // Update ghost values
1352 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
1353 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
1354 // Save data from vector on mesh
1355 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
1356 // Post-process results
1357 MOFEM_LOG("ELASTIC", Sev::inform) << "Post-process start ...";
1358 if (is_post_proc_volume == PETSC_TRUE) {
1359 CHKERR DMoFEMLoopFiniteElements(dm, "ELASTIC", &post_proc);
1360 }
1361 CHKERR DMoFEMLoopFiniteElements(dm, "ELASTIC", &prism_post_proc);
1362 CHKERR DMoFEMLoopFiniteElements(dm, "SIMPLE_ROD", &post_proc_edge);
1363 CHKERR DMoFEMLoopFiniteElements(dm, "POST_PROC_SKIN", &post_proc_skin);
1364 MOFEM_LOG("ELASTIC", Sev::inform) << "done";
1365
1366 // Write mesh in parallel (using h5m MOAB format, writing is in parallel)
1367 MOFEM_LOG("ELASTIC", Sev::inform) << "Write output file ...";
1368 if (mesh_has_tets) {
1369 if (is_post_proc_volume == PETSC_TRUE) {
1370 if (!test_nb)
1371 CHKERR post_proc.writeFile("out.h5m");
1372 }
1373 if (!test_nb)
1374 CHKERR post_proc_skin.writeFile("out_skin.h5m");
1375 }
1376 if (mesh_has_prisms) {
1377 if (!test_nb)
1378 CHKERR prism_post_proc.writeFile("prism_out.h5m");
1379 }
1380 if (!edges_in_simple_rod.empty())
1381 if (!test_nb)
1382 CHKERR post_proc_edge.writeFile("out_edge.h5m");
1383 MOFEM_LOG("ELASTIC", Sev::inform) << "done";
1384 }
1385
1386 if (is_calculating_frequency == PETSC_TRUE) {
1387 // Calculate mode mass, m = u^T * M * u
1388 Vec u1;
1389 VecDuplicate(D, &u1);
1390 CHKERR MatMult(Mij, D, u1);
1391 double mode_mass;
1392 CHKERR VecDot(u1, D, &mode_mass);
1393 MOFEM_LOG_C("ELASTIC", Sev::inform, "Mode mass %6.4e\n", mode_mass);
1394
1395 Vec v1;
1396 VecDuplicate(D, &v1);
1397 CHKERR MatMult(Aij, D, v1);
1398
1399 double mode_stiffness;
1400 CHKERR VecDot(v1, D, &mode_stiffness);
1401 MOFEM_LOG_C("ELASTIC", Sev::inform, "Mode stiffness %6.4e\n",
1402 mode_stiffness);
1403
1404 double frequency;
1405 double pi = 3.14159265359;
1406 frequency = std::sqrt(mode_stiffness / mode_mass) / (2 * pi);
1407 MOFEM_LOG_C("ELASTIC", Sev::inform, "Frequency %6.4e", frequency);
1408 }
1409
1410 // Calculate elastic energy
1411 auto calculate_strain_energy = [&]() {
1413
1414 SmartPetscObj<Vec> v_energy;
1415 CHKERR HookeElement::calculateEnergy(dm, block_sets_ptr, "DISPLACEMENT",
1416 "MESH_NODE_POSITIONS", false, true,
1417 v_energy);
1418
1419 // Print elastic energy
1420 double energy;
1421 CHKERR VecSum(v_energy, &energy);
1422 MOFEM_LOG_C("ELASTIC", Sev::inform, "Elastic energy %6.4e", energy);
1423
1424 switch (test_nb) {
1425 case 1:
1426 if (fabs(energy - 17.129) > 1e-3)
1427 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
1428 "atom test diverged!");
1429 break;
1430 case 2:
1431 if (fabs(energy - 5.6475e-03) > 1e-4)
1432 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
1433 "atom test diverged!");
1434 break;
1435 case 3:
1436 if (fabs(energy - 7.4679e-03) > 1e-4)
1437 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
1438 "atom test diverged!");
1439 break;
1440 case 4:
1441 if (fabs(energy - 2.4992e+00) > 1e-3)
1442 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
1443 "atom test diverged!");
1444 break;
1445 // FIXME: Here are missing regersion tests
1446 case 8: {
1447 double min;
1448 CHKERR VecMin(D, PETSC_NULLPTR, &min);
1449 constexpr double expected_val = 0.10001;
1450 if (fabs(min + expected_val) > 1e-10)
1451 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
1452 "atom test diverged! %3.4e != %3.4e", min, expected_val);
1453 } break;
1454 case 9: {
1455 if (fabs(energy - 4.7416e-04) > 1e-8)
1456 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
1457 "atom test diverged!");
1458 }
1459 default:
1460 break;
1461 }
1462
1464 };
1465 CHKERR calculate_strain_energy();
1466
1467 MPI_Comm_free(&moab_comm_world);
1468 }
1470
1472
1473 return 0;
1474}
#define MOFEM_LOG_SYNCHRONISE(comm)
Synchronise "SYNC" channel.
#define MOFEM_LOG_C(channel, severity, format,...)
Kronecker Delta class symmetric.
@ QUIET
#define CATCH_ERRORS
Catch errors.
@ MF_ZERO
@ MF_EXIST
FieldApproximationBase
approximation base
Definition definitions.h:58
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ AINSWORTH_LOBATTO_BASE
Definition definitions.h:62
@ NOBASE
Definition definitions.h:59
@ DEMKOWICZ_JACOBI_BASE
Definition definitions.h:66
@ AINSWORTH_BERNSTEIN_BEZIER_BASE
Definition definitions.h:64
@ H1
continuous field
Definition definitions.h:85
#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 ...
@ BODYFORCESSET
block name is "BODY_FORCES"
@ MAT_ELASTICSET
block name is "MAT_ELASTIC"
@ BLOCKSET
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
constexpr int order
MoFEM::EdgeElementForcesAndSourcesCore EdgeEle
static char help[]
@ F
constexpr auto t_kd
PetscErrorCode DMMoFEMSetIsPartitioned(DM dm, PetscBool is_partitioned)
Definition DMMoFEM.cpp:1113
PetscErrorCode DMMoFEMAddElement(DM dm, std::string fe_name)
add element to dm
Definition DMMoFEM.cpp:488
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 DMCreateMatrix_MoFEM(DM dm, Mat *M)
Definition DMMoFEM.cpp:1188
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:514
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
PetscErrorCode DMCreateGlobalVector_MoFEM(DM dm, Vec *g)
DMShellSetCreateGlobalVector.
Definition DMMoFEM.cpp:1157
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 get_finite_element_entities_by_dimension(const std::string name, int dim, Range &ents) const =0
get entities in the finite element by dimension
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.
virtual MoFEMErrorCode add_ents_to_field_by_type(const Range &ents, const EntityType type, const std::string &name, int verb=DEFAULT_VERBOSITY)=0
Add entities to field meshset.
virtual bool check_field(const std::string &name) const =0
check if field is in database
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.
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 printForceSet() const
Print meshsets with force boundary conditions.
#define _IT_CUBITMESHSETS_BY_BCDATA_TYPE_FOR_LOOP_(MESHSET_MANAGER, CUBITBCTYPE, IT)
Iterator that loops over a specific Cubit MeshSet in a moFEM field.
MoFEMErrorCode printMaterialsSet() const
Print meshsets with material properties.
MoFEMErrorCode printDisplacementSet() const
Print meshsets with displacement boundary conditions.
#define _IT_CUBITMESHSETS_BY_SET_TYPE_FOR_LOOP_(MESHSET_MANAGER, CUBITBCTYPE, IT)
Iterator that loops over a specific Cubit MeshSet having a particular BC meshset in a moFEM field.
virtual MoFEMErrorCode load_series_data(const std::string &serie_name, const int step_number)
virtual bool check_series(const std::string &name) const
check if series is in database
#define _IT_SERIES_STEPS_BY_NAME_FOR_LOOP_(RECORDER, NAME, IT)
loop over recorded series step
auto bit
set bit
FTensor::Index< 'i', SPACE_DIM > i
double D
FTensor::Index< 'j', 3 > j
const FTensor::Tensor2< T, Dim, Dim > Vec
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition Types.hpp:40
auto createKSP(MPI_Comm comm)
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
boost::shared_ptr< PCMGSetUpViaApproxOrdersCtx > createPCMGSetUpViaApproxOrdersCtx(DM dm, Mat A, bool use_shell_mat)
createPCMGSetUpViaApproxOrdersCtx
PetscErrorCode PetscOptionsGetRealArray(PetscOptions *, const char pre[], const char name[], PetscReal dval[], PetscInt *nmax, PetscBool *set)
MoFEMErrorCode PCMGSetUpViaApproxOrders(PC pc, boost::shared_ptr< PCMGSetUpViaApproxOrdersCtx > ctx, int verb)
Function build MG structure.
SmartPetscObj< Mat > matDuplicate(Mat mat, MatDuplicateOption op)
static auto getFTensor0FromVec(V &data)
Get tensor rank 0 (scalar) form data vector.
auto createDM(MPI_Comm comm, const std::string dm_type_name)
Creates smart DM object.
OpPostProcMapInMoab< SPACE_DIM, SPACE_DIM > OpPPMap
Core broken-mesh post-processor adapted to the fat-prism element.
Body forces elements.
Definition BodyForce.hpp:12
Fluid pressure forces.
static MoFEMErrorCode setOperators(MoFEM::Interface &m_field, boost::ptr_map< std::string, EdgeForce > &edge_forces, Vec F, const std::string field_name, std::string mesh_node_positions="MESH_NODE_POSITIONS")
Set integration point operators.
Definition EdgeForce.hpp:97
static MoFEMErrorCode addElement(MoFEM::Interface &m_field, const std::string field_name, Range *intersect_ptr=NULL)
Add element taking information from NODESET.
Definition EdgeForce.hpp:62
static MoFEMErrorCode addNeumannBCElements(MoFEM::Interface &m_field, const std::string field_name, const std::string mesh_nodals_positions="MESH_NODE_POSITIONS", Range *intersect_ptr=NULL)
Declare finite element.
static MoFEMErrorCode setMomentumFluxOperators(MoFEM::Interface &m_field, boost::ptr_map< std::string, NeumannForcesSurface > &neumann_forces, Vec F, const std::string field_name, const std::string mesh_nodals_positions="MESH_NODE_POSITIONS")
Set operators to finite elements calculating right hand side vector.
static MoFEMErrorCode setOperators(MoFEM::Interface &m_field, boost::ptr_map< std::string, NodalForce > &nodal_forces, Vec F, const std::string field_name)
Set integration point operators.
static MoFEMErrorCode addElement(MoFEM::Interface &m_field, const std::string field_name, Range *intersect_ptr=NULL)
Add element taking information from NODESET.
static MoFEMErrorCode addSimpleRodElements(MoFEM::Interface &m_field, const std::string field_name, const std::string mesh_nodals_positions="MESH_NODE_POSITIONS")
Declare SimpleRod element.
static MoFEMErrorCode setSimpleRodOperators(MoFEM::Interface &m_field, boost::shared_ptr< EdgeElementForcesAndSourcesCore > fe_simple_rod_lhs_ptr, boost::shared_ptr< EdgeElementForcesAndSourcesCore > fe_simple_rod_rhs_ptr, const std::string field_name, const std::string mesh_nodals_positions="MESH_NODE_POSITIONS")
Implementation of SimpleRod element. Set operators to calculate LHS and RHS.
static MoFEMErrorCode setSpringOperators(MoFEM::Interface &m_field, boost::shared_ptr< FaceElementForcesAndSourcesCore > fe_spring_lhs_ptr, boost::shared_ptr< FaceElementForcesAndSourcesCore > fe_spring_rhs_ptr, const std::string field_name, const std::string mesh_nodals_positions="MESH_NODE_POSITIONS", double stiffness_scale=1.)
Implementation of spring element. Set operators to calculate LHS and RHS.
static MoFEMErrorCode addSpringElements(MoFEM::Interface &m_field, const std::string field_name, const std::string mesh_nodals_positions="MESH_NODE_POSITIONS")
Declare spring element.
Add operators pushing bases from local to physical configuration.
Managing BitRefLevels.
Managing BitRefLevels.
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:83
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.
Structure for user loop methods on finite elements.
Basic algebra on fields.
Definition FieldBlas.hpp:21
Field evaluator interface.
Log manager is used to build and partition problems.
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.
Interface for managing meshsets containing materials and boundary conditions.
Calculate inverse of jacobian for face element.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Specialization for double precision scalar field values calculation.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Specialization for MatrixDouble vector field values calculation.
Element used to execute operators on side of the element.
Post post-proc data at points from hash maps.
std::map< std::string, ScalarDataPtr > DataMapVec
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
Transform local reference derivatives of shape functions to global derivatives.
Projection of edge entities with one mid-node on hierarchical basis.
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
Operator post-procesing stresses for Hook isotropic material.
Implentation of thermal stress element.
Set integration rule to volume elements.

Variable Documentation

◆ help

char help[]
static
Initial value:
= "-my_block_config set block data\n"
"-my_order approximation order\n"
"-my_is_partitioned set if mesh is partitioned\n"
"\n"

Definition at line 57 of file elasticity.cpp.