96int main(
int argc,
char *argv[]) {
98 const string default_options =
"-ksp_type gmres \n"
100 "-pc_factor_mat_solver_type mumps \n"
101 "-mat_mumps_icntl_20 0 \n"
103 "-snes_type newtonls \n"
104 "-snes_linesearch_type basic \n"
109 "-ts_type beuler \n";
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;
121 auto core_log = logging::core::get();
134 PetscBool flg_block_config, flg_file;
135 char mesh_file_name[255];
136 char block_config_file[255];
137 PetscInt test_nb = 0;
139 PetscBool is_partitioned = PETSC_FALSE;
140 PetscBool is_calculating_frequency = PETSC_FALSE;
141 PetscBool is_post_proc_volume = PETSC_TRUE;
144 enum bases { LEGENDRE, LOBATTO, BERNSTEIN_BEZIER, JACOBI, LASBASETOP };
145 const char *list_bases[] = {
"legendre",
"lobatto",
"bernstein_bezier",
147 PetscInt choice_base_value = LOBATTO;
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);
154 CHKERR PetscOptionsInt(
"-my_order",
"default approximation order",
"",
157 CHKERR PetscOptionsEList(
"-base",
"approximation base",
"", list_bases,
158 LASBASETOP, list_bases[choice_base_value],
159 &choice_base_value, PETSC_NULLPTR);
161 CHKERR PetscOptionsInt(
"-is_atom_test",
"ctest number",
"", test_nb,
162 &test_nb, PETSC_NULLPTR);
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);
169 CHKERR PetscOptionsString(
"-my_block_config",
"elastic configure file name",
170 "",
"block_conf.in", block_config_file, 255,
174 "-my_is_calculating_frequency",
"set if frequency will be calculated",
175 "", is_calculating_frequency, &is_calculating_frequency, PETSC_NULLPTR);
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);
184 if (flg_file != PETSC_TRUE) {
185 SETERRQ(PETSC_COMM_SELF, 1,
"*** ERROR -my_file (MESH FILE NEEDED)");
189 moab::Core mb_instance;
190 moab::Interface &moab = mb_instance;
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);
200 pcomm =
new ParallelComm(&moab, moab_comm_world);
203 if (is_partitioned == PETSC_TRUE) {
207 option =
"PARALLEL=READ_PART;"
208 "PARALLEL_RESOLVE_SHARED_ENTS;"
209 "PARTITION=PARALLEL_PARTITION;";
210 CHKERR moab.load_file(mesh_file_name, 0, option);
218 CHKERR moab.load_file(mesh_file_name, 0, option);
232 bool mesh_has_tets =
false;
233 bool mesh_has_prisms =
false;
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);
242 mesh_has_tets = (nb_tets + nb_hexs) > 0;
243 mesh_has_prisms = nb_prisms > 0;
257 if (
bit->getName().compare(0, 3,
"ROD") == 0) {
265 switch (choice_base_value) {
272 case BERNSTEIN_BEZIER:
297 CHKERR m_field.
get_moab().get_entities_by_type(0, MBEDGE, all_edges,
true);
300 Range edges_in_simple_rod;
302 if (
bit->getName().compare(0, 3,
"ROD") == 0) {
305 MBEDGE, edges,
true);
306 edges_in_simple_rod.merge(edges);
317 Range edges_to_set_order;
318 edges_to_set_order = subtract(all_edges, edges_in_simple_rod);
338 auto setting_second_order_geometry = [&m_field]() {
344 moab::Interface::UNION);
361 CHKERR setting_second_order_geometry();
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;
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));
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));
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));
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)
406 po::parsed_options parsed =
407 parse_config_file(ini_file, config_file_options,
true);
412 if (block_data[it->getMeshsetId()].oRder == -1)
414 if (block_data[it->getMeshsetId()].oRder ==
order)
416 MOFEM_LOG_C(
"ELASTIC", Sev::inform,
"Set block %d order to %d",
418 block_data[it->getMeshsetId()].oRder);
420 CHKERR moab.get_entities_by_handle(it->getMeshset(), block_ents,
422 Range ents_to_set_order;
423 CHKERR moab.get_adjacencies(block_ents, 3,
false,
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,
429 moab::Interface::UNION);
430 CHKERR moab.get_adjacencies(block_ents, 1,
false,
432 moab::Interface::UNION);
437 ents_to_set_order,
"DISPLACEMENT",
438 block_data[it->getMeshsetId()].oRder);
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",
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",
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);
477 boost::shared_ptr<std::map<int, MassBlockData>> mass_block_sets_ptr =
478 boost::make_shared<std::map<int, MassBlockData>>();
482 boost::make_shared<VolumeElementForcesAndSourcesCore>(m_field);
484 boost::make_shared<VolumeElementForcesAndSourcesCore>(m_field);
485 fe_lhs_ptr->getRuleHook =
VolRule();
486 fe_rhs_ptr->getRuleHook =
VolRule();
489 "MESH_NODE_POSITIONS");
491 "MESH_NODE_POSITIONS");
493 boost::shared_ptr<ForcesAndSourcesCore> prism_fe_lhs_ptr(
495 boost::shared_ptr<ForcesAndSourcesCore> prism_fe_rhs_ptr(
498 CHKERR HookeElement::addElasticElement(m_field, block_sets_ptr,
"ELASTIC",
500 "MESH_NODE_POSITIONS",
false);
502 auto add_skin_element_for_post_processing = [&]() {
504 Range elastic_element_ents;
506 "ELASTIC", 3, elastic_element_ents);
509 CHKERR skin.find_skin(0, elastic_element_ents,
false, skin_faces);
511 if (is_partitioned) {
512 CHKERR pcomm->filter_pstatus(skin_faces,
513 PSTATUS_SHARED | PSTATUS_MULTISHARED,
514 PSTATUS_NOT, -1, &proc_skin);
516 proc_skin = skin_faces;
534 "POST_PROC_SKIN",
"MESH_NODE_POSITIONS");
539 CHKERR add_skin_element_for_post_processing();
541 auto data_at_pts = boost::make_shared<HookeElement::DataAtIntegrationPts>();
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);
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);
555 auto thermal_strain =
558 constexpr double alpha = 1;
562 t_thermal_strain(
i,
j) = alpha * t_coords(2) *
t_kd(
i,
j);
563 return t_thermal_strain;
566 fe_rhs_ptr->getOpPtrVector().push_back(
567 new HookeElement::OpAnalyticalInternalStrain_dx<0>(
568 "DISPLACEMENT", data_at_pts, thermal_strain));
571 boost::shared_ptr<VolumeElementForcesAndSourcesCore> fe_mass_ptr(
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));
586 "MESH_NODE_POSITIONS");
590 boost::shared_ptr<FaceElementForcesAndSourcesCore> fe_spring_lhs_ptr(
592 boost::shared_ptr<FaceElementForcesAndSourcesCore> fe_spring_rhs_ptr(
596 fe_spring_rhs_ptr,
"DISPLACEMENT",
597 "MESH_NODE_POSITIONS");
602 "MESH_NODE_POSITIONS");
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));
614 m_field, fe_simple_rod_lhs_ptr, fe_simple_rod_rhs_ptr,
"DISPLACEMENT",
615 "MESH_NODE_POSITIONS");
627 "MESH_NODE_POSITIONS");
632 CHKERR m_field.
get_moab().get_entities_by_dimension(it->meshset, 3, tets,
655 bool add_temp_field =
false;
657 if (block_data[it->getMeshsetId()].initTemp != 0) {
658 add_temp_field =
true;
662 if (add_temp_field) {
672 "ELASTIC",
"DISPLACEMENT",
"TEMP");
681 "MESH_NODE_POSITIONS");
685 if (block_data[it->getMeshsetId()].initTemp != 0) {
687 "Set block %d temperature to %3.2g\n", it->getMeshsetId(),
688 block_data[it->getMeshsetId()].initTemp);
690 CHKERR moab.get_entities_by_handle(it->meshset, block_ents,
true);
692 CHKERR moab.get_connectivity(block_ents, vertices,
true);
694 block_data[it->getMeshsetId()].initTemp, MBVERTEX, vertices,
710 auto dm =
createDM(PETSC_COMM_WORLD,
"MOFEM");
712 CHKERR DMSetFromOptions(dm);
733 CHKERR MatSetOption(Aij, MAT_SPD, PETSC_TRUE);
737 if (is_calculating_frequency == PETSC_TRUE) {
739 CHKERR MatSetOption(Mij, MAT_SPD, PETSC_TRUE);
744 fe_spring_lhs_ptr->ksp_B = Aij;
745 fe_spring_rhs_ptr->ksp_f =
F;
748 fe_simple_rod_lhs_ptr->ksp_B = Aij;
749 fe_simple_rod_rhs_ptr->ksp_f =
F;
753 CHKERR VecGhostUpdateBegin(
F, INSERT_VALUES, SCATTER_FORWARD);
754 CHKERR VecGhostUpdateEnd(
F, INSERT_VALUES, SCATTER_FORWARD);
756 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
757 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
759 CHKERR MatZeroEntries(Aij);
771 auto dirichlet_bc_ptr = boost::make_shared<DirichletDisplacementBc>(
772 m_field,
"DISPLACEMENT", Aij, D0,
F);
776 dirichlet_bc_ptr->snes_ctx = FEMethod::CTX_SNESNONE;
777 dirichlet_bc_ptr->ts_ctx = FEMethod::CTX_TSNONE;
780 CHKERR VecZeroEntries(D0);
781 CHKERR VecGhostUpdateBegin(D0, INSERT_VALUES, SCATTER_FORWARD);
782 CHKERR VecGhostUpdateEnd(D0, INSERT_VALUES, SCATTER_FORWARD);
790 CHKERR VecGhostUpdateBegin(D0, INSERT_VALUES, SCATTER_FORWARD);
791 CHKERR VecGhostUpdateEnd(D0, INSERT_VALUES, SCATTER_FORWARD);
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 ...";
805 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"done";
807 fe_lhs_ptr->snes_B = Aij;
808 prism_fe_lhs_ptr->snes_B = Aij;
809 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"Calculate stiffness matrix ...";
812 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"done";
822 if (is_calculating_frequency == PETSC_TRUE) {
824 fe_mass_ptr->snes_B = Mij;
825 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"Calculate mass matrix ...";
827 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"done";
835 boost::ptr_map<std::string, NeumannForcesSurface> neumann_forces;
840 boost::ptr_map<std::string, NeumannForcesSurface>::iterator mit =
841 neumann_forces.begin();
842 for (; mit != neumann_forces.end(); mit++) {
844 &mit->second->getLoopFe());
848 boost::ptr_map<std::string, NodalForce> nodal_forces;
853 boost::ptr_map<std::string, NodalForce>::iterator fit =
854 nodal_forces.begin();
855 for (; fit != nodal_forces.end(); fit++) {
857 &fit->second->getLoopFe());
861 boost::ptr_map<std::string, EdgeForce> edge_forces;
865 auto fit = edge_forces.begin();
866 for (; fit != edge_forces.end(); fit++) {
867 auto &fe = fit->second->getLoopFe();
883 "MESH_NODE_POSITIONS");
885 "DISPLACEMENT",
F,
false,
true);
893 PetscViewerPushFormat(
894 PETSC_VIEWER_STDOUT_SELF,
895 PETSC_VIEWER_ASCII_MATLAB);
902 if (is_calculating_frequency == PETSC_TRUE) {
903 CHKERR MatAssemblyBegin(Mij, MAT_FINAL_ASSEMBLY);
904 CHKERR MatAssemblyEnd(Mij, MAT_FINAL_ASSEMBLY);
910 CHKERR MatSetOption(Aij, MAT_SPD, PETSC_TRUE);
911 CHKERR VecGhostUpdateBegin(
F, ADD_VALUES, SCATTER_REVERSE);
912 CHKERR VecGhostUpdateEnd(
F, ADD_VALUES, SCATTER_REVERSE);
918 auto solver =
createKSP(PETSC_COMM_WORLD);
919 CHKERR KSPSetDM(solver, dm);
920 CHKERR KSPSetFromOptions(solver);
921 CHKERR KSPSetOperators(solver, Aij, Aij);
926 PetscBool same = PETSC_FALSE;
928 CHKERR KSPGetPC(solver, &pc);
929 PetscObjectTypeCompare((PetscObject)pc, PCMG, &same);
933 CHKERR PCSetFromOptions(pc);
936 CHKERR KSPSetDMActive(solver, PETSC_FALSE);
939 CHKERR KSPSetInitialGuessKnoll(solver, PETSC_FALSE);
940 CHKERR KSPSetInitialGuessNonzero(solver, PETSC_TRUE);
946 auto set_post_proc_skin = [&](
auto &post_proc_skin) {
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(
954 post_proc_skin.getOpPtrVector().push_back(
960 m_field,
"ELASTIC", 3);
962 "MESH_NODE_POSITIONS");
963 side_loop->getOpPtrVector().push_back(
966 side_loop->getOpPtrVector().push_back(
969 post_proc_skin.getOpPtrVector().push_back(side_loop);
973 {
"DISPLACEMENT", disp_ptr},
974 {
"MESH_NODE_POSITIONS", mesh_pos_ptr}};
976 {
"DISPLACEMENT_GRAD", data_at_pts->hMat}};
978 auto temp_ptr = boost::make_shared<VectorDouble>();
979 auto temp_grad_ptr = boost::make_shared<MatrixDouble>();
980 post_proc_skin.getOpPtrVector().push_back(
982 post_proc_skin.getOpPtrVector().push_back(
984 scalar_map[
"TEMP"] = temp_ptr;
985 vector_map[
"TEMP_GRAD"] = temp_grad_ptr;
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, {}));
999 auto set_post_proc_tets = [&](
auto &post_proc) {
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(
1009 post_proc.getOpPtrVector().push_back(
1012 post_proc.getOpPtrVector().push_back(
1017 {
"DISPLACEMENT", disp_ptr},
1018 {
"MESH_NODE_POSITIONS", mesh_pos_ptr}};
1020 {
"DISPLACEMENT_GRAD", disp_grad_ptr}};
1022 auto temp_ptr = boost::make_shared<VectorDouble>();
1023 auto temp_grad_ptr = boost::make_shared<MatrixDouble>();
1024 post_proc.getOpPtrVector().push_back(
1026 post_proc.getOpPtrVector().push_back(
1028 scalar_map[
"TEMP"] = temp_ptr;
1029 vector_map[
"TEMP_GRAD"] = temp_grad_ptr;
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, {}));
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(
1047 post_proc_edge.getOpPtrVector().push_back(
new OpPPMap(
1048 post_proc_edge.getPostProcMesh(), post_proc_edge.getMapGaussPts(), {},
1049 {{
"DISPLACEMENT", disp_ptr}}, {}, {}));
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(
1058 prism_post_proc.getOpPtrVector().push_back(
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(
1065 prism_post_proc.getOpPtrVector().push_back(
1068 prism_post_proc.getOpPtrVector().push_back(
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}}, {}));
1093 auto is_prism = [](
FEMethod *fe_ptr) {
1094 return fe_ptr->numeredEntFiniteElementPtr->getEntType() == MBPRISM;
1096 prism_post_proc.exeTestHook = is_prism;
1097 post_proc.exeTestHook = [is_prism](
FEMethod *fe_ptr) {
1098 return !is_prism(fe_ptr);
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);
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;
1111 field_eval_coords.data(), &coords_dim,
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>();
1118 if (field_eval_flag) {
1120 ->getData<VolumeElementForcesAndSourcesCore>();
1122 field_eval_data,
"ELASTIC");
1124 field_eval_data->setEvalPoints(field_eval_coords.data(), 1);
1125 auto no_rule = [](
int,
int,
int) {
return -1; };
1127 auto field_eval_fe_ptr = field_eval_data->feMethodPtr;
1128 field_eval_fe_ptr->getRuleHook = no_rule;
1130 if (m_field.check_field(
"TEMP")) {
1131 field_eval_fe_ptr->getOpPtrVector().push_back(
1134 field_eval_fe_ptr->getOpPtrVector().push_back(
1136 field_eval_fe_ptr->getOpPtrVector().push_back(
1141 if (m_field.check_field(
"TEMP")) {
1145 CHKERR VecDuplicate(
F, &F_thermal);
1149 CHKERR thermal_stress_elem.setThermalStressRhsOperators(
1150 "DISPLACEMENT",
"TEMP", F_thermal);
1168 MOFEM_LOG_C(
"ELASTIC", Sev::inform,
"Process step %d",
1169 sit->get_step_number());
1172 sit->get_step_number());
1174 CHKERR VecZeroEntries(F_thermal);
1175 CHKERR VecGhostUpdateBegin(F_thermal, INSERT_VALUES, SCATTER_FORWARD);
1176 CHKERR VecGhostUpdateEnd(F_thermal, INSERT_VALUES, SCATTER_FORWARD);
1184 dm,
"ELASTIC", &thermal_stress_elem.getLoopThermalStressRhs());
1187 CHKERR VecAssemblyBegin(F_thermal);
1188 CHKERR VecAssemblyEnd(F_thermal);
1190 CHKERR VecGhostUpdateBegin(F_thermal, ADD_VALUES, SCATTER_REVERSE);
1191 CHKERR VecGhostUpdateEnd(F_thermal, ADD_VALUES, SCATTER_REVERSE);
1195 CHKERR VecNorm(
F, NORM_2, &nrm_F);
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",
1203 CHKERR VecScale(F_thermal, -1);
1205 CHKERR VecAXPY(F_thermal, 1,
F);
1208 dirichlet_bc_ptr->snes_x =
D;
1209 dirichlet_bc_ptr->snes_f = F_thermal;
1213 CHKERR KSPSolve(solver, F_thermal,
D);
1216 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
1217 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
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(),
1231 if (scalar_field_ptr->size()) {
1234 <<
"Eval point TEMP: " << t_temp;
1236 if (vector_field_ptr->size1()) {
1238 auto t_disp = getFTensor1FromMat<3>(*vector_field_ptr);
1240 <<
"Eval point DISPLACEMENT magnitude: "
1241 << sqrt(t_disp(
i) * t_disp(
i));
1243 if (tensor_field_ptr->size1()) {
1245 auto t_disp_grad = getFTensor2FromMat<3, 3>(*tensor_field_ptr);
1247 <<
"Eval point DISPLACEMENT_GRAD trace: " << t_disp_grad(
i,
i);
1254 if (is_post_proc_volume == PETSC_TRUE) {
1255 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"Write output file ...";
1257 std::ostringstream o1;
1258 o1 <<
"out_" << sit->step_number <<
".h5m";
1260 CHKERR post_proc.writeFile(o1.str().c_str());
1261 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"done ...";
1264 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"Write output file skin ...";
1267 std::ostringstream o1_skin;
1268 o1_skin <<
"out_skin_" << sit->step_number <<
".h5m";
1270 CHKERR post_proc_skin.writeFile(o1_skin.str().c_str());
1271 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"done ...";
1276 CHKERR VecZeroEntries(F_thermal);
1277 CHKERR VecGhostUpdateBegin(F_thermal, INSERT_VALUES, SCATTER_FORWARD);
1278 CHKERR VecGhostUpdateEnd(F_thermal, INSERT_VALUES, SCATTER_FORWARD);
1282 dm,
"ELASTIC", &thermal_stress_elem.getLoopThermalStressRhs());
1285 CHKERR VecAssemblyBegin(F_thermal);
1286 CHKERR VecAssemblyEnd(F_thermal);
1289 CHKERR VecGhostUpdateBegin(F_thermal, ADD_VALUES, SCATTER_REVERSE);
1290 CHKERR VecGhostUpdateEnd(F_thermal, ADD_VALUES, SCATTER_REVERSE);
1294 CHKERR VecNorm(
F, NORM_2, &nrm_F);
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);
1300 MOFEM_LOG_C(
"ELASTIC", Sev::inform,
"norm2 F_thermal = %6.4e",
1304 CHKERR VecScale(F_thermal, -1);
1305 CHKERR VecAXPY(F_thermal, 1,
F);
1308 dirichlet_bc_ptr->snes_x =
D;
1309 dirichlet_bc_ptr->snes_f = F_thermal;
1313 CHKERR KSPSolve(solver, F_thermal,
D);
1317 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
1318 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
1322 if (is_post_proc_volume == PETSC_TRUE) {
1323 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"Write output file ...";
1327 CHKERR post_proc.writeFile(
"out.h5m");
1328 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"done";
1331 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"Write output file skin ...";
1334 CHKERR post_proc_skin.writeFile(
"out_skin.h5m");
1335 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"done";
1339 CHKERR VecDestroy(&F_thermal);
1352 CHKERR VecGhostUpdateBegin(
D, INSERT_VALUES, SCATTER_FORWARD);
1353 CHKERR VecGhostUpdateEnd(
D, INSERT_VALUES, SCATTER_FORWARD);
1357 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"Post-process start ...";
1358 if (is_post_proc_volume == PETSC_TRUE) {
1364 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"done";
1367 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"Write output file ...";
1368 if (mesh_has_tets) {
1369 if (is_post_proc_volume == PETSC_TRUE) {
1371 CHKERR post_proc.writeFile(
"out.h5m");
1374 CHKERR post_proc_skin.writeFile(
"out_skin.h5m");
1376 if (mesh_has_prisms) {
1378 CHKERR prism_post_proc.writeFile(
"prism_out.h5m");
1380 if (!edges_in_simple_rod.empty())
1382 CHKERR post_proc_edge.writeFile(
"out_edge.h5m");
1383 MOFEM_LOG(
"ELASTIC", Sev::inform) <<
"done";
1386 if (is_calculating_frequency == PETSC_TRUE) {
1389 VecDuplicate(
D, &u1);
1392 CHKERR VecDot(u1,
D, &mode_mass);
1393 MOFEM_LOG_C(
"ELASTIC", Sev::inform,
"Mode mass %6.4e\n", mode_mass);
1396 VecDuplicate(
D, &v1);
1399 double mode_stiffness;
1400 CHKERR VecDot(v1,
D, &mode_stiffness);
1401 MOFEM_LOG_C(
"ELASTIC", Sev::inform,
"Mode stiffness %6.4e\n",
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);
1411 auto calculate_strain_energy = [&]() {
1415 CHKERR HookeElement::calculateEnergy(dm, block_sets_ptr,
"DISPLACEMENT",
1416 "MESH_NODE_POSITIONS",
false,
true,
1421 CHKERR VecSum(v_energy, &energy);
1422 MOFEM_LOG_C(
"ELASTIC", Sev::inform,
"Elastic energy %6.4e", energy);
1426 if (fabs(energy - 17.129) > 1e-3)
1428 "atom test diverged!");
1431 if (fabs(energy - 5.6475e-03) > 1e-4)
1433 "atom test diverged!");
1436 if (fabs(energy - 7.4679e-03) > 1e-4)
1438 "atom test diverged!");
1441 if (fabs(energy - 2.4992e+00) > 1e-3)
1443 "atom test diverged!");
1448 CHKERR VecMin(
D, PETSC_NULLPTR, &min);
1449 constexpr double expected_val = 0.10001;
1450 if (fabs(min + expected_val) > 1e-10)
1452 "atom test diverged! %3.4e != %3.4e", min, expected_val);
1455 if (fabs(energy - 4.7416e-04) > 1e-8)
1457 "atom test diverged!");
1465 CHKERR calculate_strain_energy();
1467 MPI_Comm_free(&moab_comm_world);