v0.16.0
Loading...
Searching...
No Matches
PostProcBrokenMeshInMoabBase.hpp
Go to the documentation of this file.
1/**
2 * @file PostProcBrokenMeshInMoabBase.hpp
3 * @author your name (you@domain.com)
4 * @brief
5 * @version 0.1
6 * @date 2022-09-14
7 *
8 * @copyright Copyright (c) 2022
9 *
10 */
11
12#ifndef __POSTPROCBROKENMESHINMOABBASE_HPP
13#define __POSTPROCBROKENMESHINMOABBASE_HPP
14
15namespace MoFEM {
16
17/**
18 * Each element is subdivided on smaller elements, i.e. a reference mesh on
19 * single element is created. Nodes of such reference mesh are used as
20 * integration points at which field values are calculated and to
21 * each node a "moab" tag is attached to store those values.
22 */
24
25 std::vector<MatrixDouble>
26 levelShapeFunctions; //< values of shape functions on refences element
27 // refinement levels
28 std::vector<MatrixDouble>
29 levelGaussPtsOnRefMesh; //< gauss points at refinement levels
30 std::vector<ublas::matrix<int>> levelRef; //< connectivity at refinement level
31
32 EntityHandle startingVertEleHandle; //< starting handle of first vertex
33 std::vector<double *> verticesOnEleArrays; //< array of vertices coordinate
34 EntityHandle startingEleHandle; //< starting handle of first element
35 EntityHandle *eleConn; //< array of elements connectivity
36
37 int countEle; //< count elements
38 int countVertEle; //< count vertices on the mesh
39
40 int nbVertices; //< numer of vertices on the mesh
41 int nbEles; //< number of elements on the mesh
42
44 virtual ~PostProcGenerateRefMeshBase() = default;
45
46 virtual MoFEMErrorCode getOptions(std::string prefix); //< get options from command
48
49 PetscBool hoNodes; //< if true mid nodes are added
50 int defMaxLevel; //< default max number of refinement levels
51};
52
54 boost::shared_ptr<PostProcGenerateRefMeshBase>;
55
56/**
57 * @brief Element for postprocessing. Uses MoAB to generate post-processing
58 * mesh.
59 *
60 * @tparam T Finite Element Implementation
61 */
62template <EntityType T> struct PostProcGenerateRefMesh;
63
64template <>
69
70template <>
75
76template <>
81
82template <>
87
88template <>
93
94template <>
99
100template <typename E> struct PostProcBrokenMeshInMoabBase : public E {
101
103 std::string opts_prefix = "");
105 boost::shared_ptr<moab::Core> core_mesh_ptr,
106 std::string opts_prefix = "");
107
109
110 /**
111 * @brief Get vector of vectors associated to integration points
112 *
113 * @return std::vector<EntityHandle>&
114 */
115 inline auto &getMapGaussPts();
116
117 /**
118 * @brief Get postprocessing mesh
119 *
120 * @return moab::Interface&
121 */
122 inline auto &getPostProcMesh();
123
124 /**
125 * @brief Get postprocessing elements
126 *
127 * @return auto&
128 */
129 inline auto &getPostProcElements();
130
131 /**
132 * \brief wrote results in (MOAB) format, use "file_name.h5m"
133 * @param file_name file name (should always end with .h5m)
134 * @return error code
135 * \ingroup mofem_fs_post_proc
136 */
137 MoFEMErrorCode writeFile(const std::string file_name);
138
139 /**
140 * @brief Set tags to be transferred to post-processing mesh
141 *
142 * @param tags_to_transfer
143 * @return MoFEMErrorCode
144 */
145 MoFEMErrorCode setTagsToTransfer(std::vector<Tag> tags_to_transfer);
146
147protected:
148
150
151 /**
152 * @brief Generate vertices and elements
153 *
154 * @return MoFEMErrorCode
155 */
157
159
160 int getRule(int order);
161
162 /**
163 * @brief Determine refinement level based on fields approx ordre.
164 *
165 * level = (order - 1) / 2
166 *
167 * @return int
168 */
169 virtual int getMaxLevel() const;
170
171 boost::shared_ptr<moab::Core> coreMeshPtr = boost::make_shared<moab::Core>();
172
173 std::vector<EntityHandle> mapGaussPts;
175
176 std::map<EntityType, PostProcGenerateRefMeshPtr>
177 refElementsMap; ///< Storing data about element types, and data for
178 ///< ReadUtilIface to create element entities on
179 ///< post-process mesh.
180 std::vector<Tag> tagsToTransfer; ///< Set of tags on mesh to transfer to
181 ///< postprocessing mesh
182 std::string optionsPrefix = ""; ///< Prefix for options
183
186
187 virtual MoFEMErrorCode transferTags(); ///< transfer tags from mesh to
188 ///< post-process mesh
189
193
194};
195
196template <typename E>
198 std::vector<Tag> tags_to_transfer) {
200 tagsToTransfer.swap(tags_to_transfer);
202}
203
204template <typename E> int PostProcBrokenMeshInMoabBase<E>::getMaxLevel() const {
205 auto get_element_max_dofs_order = [&]() {
206 int max_order = 0;
207 auto dofs_vec = E::getDataVectorDofsPtr();
208 for (auto &dof : *dofs_vec) {
209 const int dof_order = dof->getDofOrder();
210 max_order = (max_order < dof_order) ? dof_order : max_order;
211 };
212 return max_order;
213 };
214 const auto dof_max_order = get_element_max_dofs_order();
215 return (dof_max_order > 0) ? (dof_max_order - 1) / 2 : 0;
216};
217
218template <typename E>
221
222 auto &calc_mesh = this->mField.get_moab();
223
224 auto name = [&](auto tag) {
225 std::string name;
226 CHK_MOAB_THROW(calc_mesh.tag_get_name(tag, name), "get name");
227 return name;
228 };
229
230 auto data_type = [&](auto tag) {
231 moab::DataType data_type;
232 CHK_MOAB_THROW(calc_mesh.tag_get_data_type(tag, data_type),
233 "get data type");
234 return data_type;
235 };
236
237 auto type = [&](auto tag) {
238 moab::TagType type;
239 CHK_MOAB_THROW(calc_mesh.tag_get_type(tag, type), "get tag type");
240 return type;
241 };
242
243 auto length = [&](auto tag) {
244 int length;
245 CHK_MOAB_THROW(calc_mesh.tag_get_length(tag, length), "get length ");
246 return length;
247 };
248
249 auto default_value = [&](auto tag) {
250 const void *def_val;
251 int size;
252 CHK_MOAB_THROW(calc_mesh.tag_get_default_value(tag, def_val, size),
253 "get default tag value");
254 return def_val;
255 };
256
257 std::vector<double> tag_data_vec;
258 auto data_ptr = [&](auto tag) {
259 const void *tag_data;
260 auto core_ent = this->getFEEntityHandle();
261 CHK_MOAB_THROW(calc_mesh.tag_get_by_ptr(tag, &core_ent, 1, &tag_data),
262 "get tag data");
263 if (data_type(tag) == MB_TYPE_DOUBLE) {
264 tag_data_vec.resize(length(tag));
265 std::copy(static_cast<const double *>(tag_data),
266 static_cast<const double *>(tag_data) + length(tag),
267 tag_data_vec.begin());
268 for (auto &v : tag_data_vec)
269 v = std::abs(v) < std::numeric_limits<float>::min() ? 0. : v;
270 for (auto &v : tag_data_vec)
271 v = v > std::numeric_limits<float>::max()
272 ? std::numeric_limits<float>::max()
273 : v;
274 for (auto &v : tag_data_vec)
275 v = v < std::numeric_limits<float>::lowest()
276 ? std::numeric_limits<float>::lowest()
277 : v;
278 return static_cast<const void *>(tag_data_vec.data());
279 }
280 return tag_data;
281 };
282
283 for (auto tag : tagsToTransfer) {
284 Tag tag_postproc;
285 CHKERR getPostProcMesh().tag_get_handle(
286 name(tag).c_str(), length(tag), data_type(tag), tag_postproc,
287 type(tag) | MB_TAG_CREAT, default_value(tag));
288 CHKERR getPostProcMesh().tag_clear_data(tag_postproc, postProcElements,
289 data_ptr(tag));
290 }
291
293};
294
295template <typename E>
297 MoFEM::Interface &m_field, std::string opts_prefix)
298 : E(m_field), optionsPrefix(opts_prefix) {}
299
300template <typename E>
302 MoFEM::Interface &m_field, boost::shared_ptr<moab::Core> core_mesh_ptr,
303 std::string opts_prefix)
304 : PostProcBrokenMeshInMoabBase(m_field, opts_prefix) {
305 coreMeshPtr = core_mesh_ptr;
306}
307
308template <typename E>
312
313template <typename E> int PostProcBrokenMeshInMoabBase<E>::getRule(int order) {
314 return -1;
315};
316
317template <typename E>
320
321 auto type = type_from_handle(this->getFEEntityHandle());
322
324
325 try {
326 ref_ele = refElementsMap.at(type);
327 } catch (const out_of_range &e) {
328 SETERRQ(
329 PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
330 "Generation of reference elements for type <%s> is not implemented",
331 moab::CN::EntityTypeName(type));
332 }
333
334 auto set_gauss_pts = [&](auto &level_gauss_pts_on_ref_mesh, auto &level_ref,
335 auto &level_shape_functions,
336
337 auto start_vert_handle, auto start_ele_handle,
338 auto &verts_array, auto &conn, auto &ver_count,
339 auto &ele_count
340
341 ) {
343
344 size_t level = getMaxLevel();
345 level = std::min(level, level_gauss_pts_on_ref_mesh.size() - 1);
346
347 auto &level_ref_gauss_pts = level_gauss_pts_on_ref_mesh[level];
348 auto &level_ref_ele = level_ref[level];
349 auto &shape_functions = level_shape_functions[level];
350 E::gaussPts.resize(level_ref_gauss_pts.size1(), level_ref_gauss_pts.size2(),
351 false);
352 noalias(E::gaussPts) = level_ref_gauss_pts;
353
354 const auto fe_ent = E::numeredEntFiniteElementPtr->getEnt();
355 auto get_fe_coords = [&]() {
356 const EntityHandle *conn;
357 int num_nodes;
359 E::mField.get_moab().get_connectivity(fe_ent, conn, num_nodes, true),
360 "error get connectivity");
361 VectorDouble coords(num_nodes * 3);
363 E::mField.get_moab().get_coords(conn, num_nodes, &*coords.begin()),
364 "error get coordinates");
365 return coords;
366 };
367
368 auto coords = get_fe_coords();
369
370 const int num_nodes = level_ref_gauss_pts.size2();
371 mapGaussPts.resize(level_ref_gauss_pts.size2());
372
373 FTensor::Index<'i', 3> i;
375 &*shape_functions.data().begin());
377 &verts_array[0][ver_count], &verts_array[1][ver_count],
378 &verts_array[2][ver_count]);
379 for (int gg = 0; gg != num_nodes; ++gg, ++ver_count) {
380
381 mapGaussPts[gg] = start_vert_handle + ver_count;
382
383 auto set_float_precision = [](const double x) {
384 if (std::abs(x) < std::numeric_limits<float>::epsilon())
385 return 0.;
386 else
387 return x;
388 };
389
390 t_coords(i) = 0;
391 auto t_ele_coords = getFTensor1FromArray<3, 3>(coords);
392 for (int nn = 0; nn != CN::VerticesPerEntity(type); ++nn) {
393 t_coords(i) += t_n * t_ele_coords(i);
394 ++t_ele_coords;
395 ++t_n;
396 }
397
398 for (auto ii : {0, 1, 2})
399 t_coords(ii) = set_float_precision(t_coords(ii));
400
401 ++t_coords;
402 }
403
404 Tag th;
405 int def_in_the_loop = -1;
406 CHKERR getPostProcMesh().tag_get_handle(
407 "NB_IN_THE_LOOP", 1, MB_TYPE_INTEGER, th, MB_TAG_CREAT | MB_TAG_SPARSE,
408 &def_in_the_loop);
409
410 postProcElements.clear();
411 const int num_el = level_ref_ele.size1();
412 const int num_nodes_on_ele = level_ref_ele.size2();
413 auto start_e = start_ele_handle + ele_count;
414 postProcElements = Range(start_e, start_e + num_el - 1);
415 for (auto tt = 0; tt != level_ref_ele.size1(); ++tt, ++ele_count) {
416 for (int nn = 0; nn != num_nodes_on_ele; ++nn) {
417 conn[num_nodes_on_ele * ele_count + nn] =
418 mapGaussPts[level_ref_ele(tt, nn)];
419 }
420 }
421
422 const int n_in_the_loop = E::nInTheLoop;
423 CHKERR getPostProcMesh().tag_clear_data(th, postProcElements,
424 &n_in_the_loop);
425 CHKERR transferTags();
426
428 };
429
430 CHKERR set_gauss_pts(
431
432 ref_ele->levelGaussPtsOnRefMesh, ref_ele->levelRef,
433 ref_ele->levelShapeFunctions,
434
435 ref_ele->startingVertEleHandle, ref_ele->startingEleHandle,
436 ref_ele->verticesOnEleArrays, ref_ele->eleConn, ref_ele->countVertEle,
437 ref_ele->countEle
438
439 );
440
442};
443
444template <typename E>
447
448auto get_ref_ele = [&](const EntityType type) {
449 PostProcGenerateRefMeshPtr ref_ele_ptr;
450
451 auto it = refElementsMap.find(type);
452 if (it != refElementsMap.end()) {
453 ref_ele_ptr = it->second;
454 } else {
455 switch (type) {
456 case MBTET:
457 ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBTET>>();
458 break;
459 case MBHEX:
460 ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBHEX>>();
461 break;
462 case MBPRISM:
463 ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBPRISM>>();
464 break;
465 case MBTRI:
466 ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBTRI>>();
467 break;
468 case MBQUAD:
469 ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBQUAD>>();
470 break;
471 case MBEDGE:
472 ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBEDGE>>();
473 break;
474 default:
475 MOFEM_LOG("SELF", Sev::error)
476 << "Generation of reference elements for type < "
477 << moab::CN::EntityTypeName(type) << " > is not implemented";
478 CHK_THROW_MESSAGE(MOFEM_NOT_IMPLEMENTED, "Element not implemented");
479 }
480
481 CHK_THROW_MESSAGE(ref_ele_ptr->getOptions(optionsPrefix), "getOptions");
482 CHK_THROW_MESSAGE(ref_ele_ptr->generateReferenceElementMesh(),
483 "Error when generating reference element");
484
485 refElementsMap[type] = ref_ele_ptr;
486 }
487
488 return ref_ele_ptr;
489};
490
491 auto fe_ptr = this->problemPtr->numeredFiniteElementsPtr;
492
493 auto miit =
494 fe_ptr->template get<Composite_Name_And_Part_mi_tag>().lower_bound(
495 boost::make_tuple(this->getFEName(), this->getLoFERank()));
496 auto hi_miit =
497 fe_ptr->template get<Composite_Name_And_Part_mi_tag>().upper_bound(
498 boost::make_tuple(this->getFEName(), this->getHiFERank()));
499
500 const int number_of_ents_in_the_loop = this->getLoopSize();
501 if (std::distance(miit, hi_miit) != number_of_ents_in_the_loop) {
502 SETERRQ(E::mField.get_comm(), MOFEM_DATA_INCONSISTENCY,
503 "Wrong size of indicies. Inconsistent size number of iterated "
504 "elements iterated by problem and from range.");
505 }
506
507 for (auto &m : refElementsMap) {
508 m.second->nbVertices = 0;
509 m.second->nbEles = 0;
510 m.second->countEle = 0;
511 m.second->countVertEle = 0;
512 }
513
514 for (; miit != hi_miit; ++miit) {
515 auto type = (*miit)->getEntType();
516 auto ref_ele = get_ref_ele(type);
517
518 // Set pointer to element. So that getDataVectorDofsPtr in getMaxLevel
519 // can work
520 E::numeredEntFiniteElementPtr = *miit;
521 bool add = true;
522 if (E::exeTestHook) {
523 add = E::exeTestHook(this);
524 }
525
526 if (add) {
527 size_t level = getMaxLevel();
528 level = std::min(level, ref_ele->levelGaussPtsOnRefMesh.size() - 1);
529 ref_ele->nbVertices += ref_ele->levelGaussPtsOnRefMesh[level].size2();
530 ref_ele->nbEles += ref_ele->levelRef[level].size1();
531 }
532 }
533
534 auto alloc_vertices_and_elements_on_post_proc_mesh = [&]() {
536
537 ReadUtilIface *iface;
538 CHKERR getPostProcMesh().query_interface(iface);
539
540 for (auto &m : refElementsMap) {
541 if (m.second->nbEles) {
542 CHKERR iface->get_node_coords(3, m.second->nbVertices, 0,
543 m.second->startingVertEleHandle,
544 m.second->verticesOnEleArrays);
545 CHKERR iface->get_element_connect(
546 m.second->nbEles, m.second->levelRef[0].size2(), m.first, 0,
547 m.second->startingEleHandle, m.second->eleConn);
548
549 m.second->countEle = 0;
550 m.second->countVertEle = 0;
551 }
552 }
553
555 };
556
557 CHKERR alloc_vertices_and_elements_on_post_proc_mesh();
558
560}
561
562template <typename E>
565
566 auto update_elements = [&]() {
567 ReadUtilIface *iface;
568 CHKERR getPostProcMesh().query_interface(iface);
570
571 Range ents;
572 for (auto &m : refElementsMap) {
573 if (m.second->nbEles) {
574 MOFEM_TAG_AND_LOG("SELF", Sev::noisy, "PostProc")
575 << "Update < " << moab::CN::EntityTypeName(m.first)
576 << " number of processed " << m.second->countEle;
577 CHKERR iface->update_adjacencies(
578 m.second->startingEleHandle, m.second->countEle,
579 m.second->levelRef[0].size2(), m.second->eleConn);
580 ents.merge(Range(m.second->startingEleHandle,
581 m.second->startingEleHandle + m.second->countEle - 1));
582 }
583 }
584
586 };
587
588 auto remove_obsolete_entities = [&]() {
590 Range ents, adj;
591 for (auto &m : refElementsMap) {
592 if (m.second->nbEles) {
593 ents.merge(Range(m.second->startingEleHandle,
594 m.second->startingEleHandle + m.second->countEle - 1));
595 const int dim = moab::CN::Dimension(m.first);
596 for (auto d = 1; d != dim; ++d) {
597 CHKERR getPostProcMesh().get_adjacencies(ents, d, false, adj,
598 moab::Interface::UNION);
599 }
600 }
601 }
602 CHKERR getPostProcMesh().delete_entities(adj);
604 };
605
606 auto set_proc_tags = [&]() {
608 auto pcomm_post_proc_mesh = getPostProcMeshPcommPtr();
609 if (pcomm_post_proc_mesh) {
610 Range ents;
611 for (auto &m : refElementsMap) {
612 if (m.second->nbEles) {
613 ents.merge(
614 Range(m.second->startingEleHandle,
615 m.second->startingEleHandle + m.second->countEle - 1));
616 }
617 }
618 int rank = E::mField.get_comm_rank();
619 CHKERR getPostProcMesh().tag_clear_data(pcomm_post_proc_mesh->part_tag(),
620 ents, &rank);
621 }
623 };
624
625 CHKERR update_elements();
626 CHKERR remove_obsolete_entities();
627 CHKERR set_proc_tags();
628
630}
631
632template <typename E>
635
636 CHKERR getPostProcMesh().delete_mesh();
637
638
639 CHKERR preProcPostProc();
640
642}
643
644template <typename E>
647
648 auto pcomm_post_proc_mesh = getPostProcMeshPcommPtr();
649 if (!pcomm_post_proc_mesh)
650 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
651 "ParallelComm not allocated");
652
653 CHKERR postProcPostProc();
654 CHKERR pcomm_post_proc_mesh->resolve_shared_ents(0);
655
657}
658
660 return mapGaussPts;
661}
662
664 if (!coreMeshPtr)
665 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Core mesh not set");
666 moab::Interface &post_proc_mesh_interface = *coreMeshPtr;
667 return post_proc_mesh_interface;
668}
669
670template <typename E>
672 return postProcElements;
673}
674
675template <typename E>
677PostProcBrokenMeshInMoabBase<E>::writeFile(const std::string file_name) {
679 auto pcomm_post_proc_mesh = getPostProcMeshPcommPtr();
680 if (!pcomm_post_proc_mesh)
681 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
682 "ParallelComm not allocated");
683
684 auto &post_proc_mesh = getPostProcMesh();
685 Tag part_tag = pcomm_post_proc_mesh->part_tag();
686 Range tagged_sets;
687 CHK_MOAB_THROW(post_proc_mesh.get_entities_by_type_and_tag(
688 0, MBENTITYSET, &part_tag, NULL, 1, tagged_sets,
689 moab::Interface::UNION),
690 "get partition sets");
691 if (tagged_sets.empty()) {
692 EntityHandle part_set;
693 CHK_MOAB_THROW(post_proc_mesh.create_meshset(MESHSET_SET, part_set),
694 "create partition meshset");
695
696 Range ents;
697 CHK_MOAB_THROW(post_proc_mesh.get_entities_by_handle(0, ents, false),
698 "get post-process entities");
699 ents = subtract(ents, ents.subset_by_type(MBENTITYSET));
700 CHK_MOAB_THROW(post_proc_mesh.add_entities(part_set, ents),
701 "add entities to partition meshset");
702
703 int part = pcomm_post_proc_mesh->rank();
704 CHK_MOAB_THROW(post_proc_mesh.tag_set_data(part_tag, &part_set, 1, &part),
705 "tag partition meshset");
706 }
707
708 CHKERR getPostProcMesh().write_file(file_name.c_str(), "MOAB",
709 "PARALLEL=WRITE_PART");
711};
712
713template <typename E> struct PostProcBrokenMeshInMoab;
714
715template <>
717 : public PostProcBrokenMeshInMoabBase<VolumeElementForcesAndSourcesCore> {
719 VolumeElementForcesAndSourcesCore>::PostProcBrokenMeshInMoabBase;
720};
721
722template <>
724 : public PostProcBrokenMeshInMoabBase<FaceElementForcesAndSourcesCore> {
726 FaceElementForcesAndSourcesCore>::PostProcBrokenMeshInMoabBase;
727};
728
729template <>
731 : public PostProcBrokenMeshInMoabBase<EdgeElementForcesAndSourcesCore> {
733 EdgeElementForcesAndSourcesCore>::PostProcBrokenMeshInMoabBase;
734};
735
736/**
737 * @brief Post post-proc data at points from hash maps
738 *
739 * @tparam DIM1 dimension of vector in data_map_vec and first column of
740 * data_map_may
741 * @tparam DIM2 dimension of second column in data_map_mat
742 */
743template <int DIM1, int DIM2,
745struct OpPostProcMapInMoab : public O {
746
748 std::variant<boost::shared_ptr<VectorDouble>,
749 boost::shared_ptr<MatrixDouble>>;
750 using DataMapVec = std::map<std::string, ScalarDataPtr>;
751 using DataMapMat = std::map<std::string, boost::shared_ptr<MatrixDouble>>;
752
753 /**
754 * @brief Construct a new OpPostProcMapInMoab object
755 *
756 * @param post_proc_mesh postprocessing mesh
757 * @param map_gauss_pts map of gauss points to nodes of postprocessing mesh
758 * @param data_map_scalar hash map of scalar values (string is name of the
759 * tag)
760 * @param data_map_vec hash map of vector values
761 * @param data_map_mat hash map of second order tensor values
762 * @param data_symm_map_mat hash map of symmetric second order tensor values
763 */
764 OpPostProcMapInMoab(moab::Interface &post_proc_mesh,
765 std::vector<EntityHandle> &map_gauss_pts,
766 DataMapVec data_map_scalar, DataMapMat data_map_vec,
767 DataMapMat data_map_mat, DataMapMat data_symm_map_mat)
768 : O(NOSPACE, O::OPSPACE), postProcMesh(post_proc_mesh),
769 mapGaussPts(map_gauss_pts), dataMapScalar(data_map_scalar),
770 dataMapVec(data_map_vec), dataMapMat(data_map_mat),
771 dataMapSymmMat(data_symm_map_mat) {
772 // Operator is only executed for vertices
773 std::fill(&O::doEntities[MBEDGE], &O::doEntities[MBMAXTYPE], false);
774 }
775 MoFEMErrorCode doWork(int side, EntityType type,
777
778private:
779 moab::Interface &postProcMesh;
780 std::vector<EntityHandle> &mapGaussPts;
785};
786
787template <int DIM1, int DIM2, typename O>
792
793 std::array<double, 9> def;
794 std::fill(def.begin(), def.end(), 0);
795
796 auto get_tag = [&](const std::string name, size_t size) {
797 Tag th;
798 CHKERR postProcMesh.tag_get_handle(name.c_str(), size, MB_TYPE_DOUBLE, th,
799 MB_TAG_CREAT | MB_TAG_SPARSE,
800 def.data());
801 return th;
802 };
803
804 MatrixDouble3by3 mat(3, 3);
805
806 auto set_vector_3d = [&](auto &t) -> MatrixDouble3by3 & {
807 mat.clear();
808 for (size_t r = 0; r != DIM1; ++r)
809 mat(0, r) = t(r);
810 return mat;
811 };
812
813 auto set_matrix_3d = [&](auto &t) -> MatrixDouble3by3 & {
814 mat.clear();
815 for (size_t r = 0; r != DIM1; ++r)
816 for (size_t c = 0; c != DIM2; ++c)
817 mat(r, c) = t(r, c);
818 return mat;
819 };
820
821 auto set_matrix_symm_3d = [&](auto &t) -> MatrixDouble3by3 & {
822 mat.clear();
823 for (size_t r = 0; r != DIM1; ++r)
824 for (size_t c = 0; c != DIM1; ++c)
825 mat(r, c) = t(r, c);
826 return mat;
827 };
828
829 auto set_scalar = [&](auto t) -> MatrixDouble3by3 & {
830 mat.clear();
831 mat(0, 0) = t;
832 return mat;
833 };
834
835 auto set_float_precision = [](const double x) {
836 if (std::abs(x) < std::numeric_limits<float>::min())
837 return static_cast<float>(0.);
838 else
839 return static_cast<float>(x);
840 };
841
842 auto set_float_max = [](const double x) {
843 if (x > std::numeric_limits<float>::max())
844 return std::numeric_limits<float>::max();
845 else
846 return static_cast<float>(x);
847 };
848
849 auto set_float_lowest = [](const double x) {
850 if (x < std::numeric_limits<float>::lowest())
851 return std::numeric_limits<float>::lowest();
852 else
853 return static_cast<float>(x);
854 };
855
856 auto set_tag = [&](auto th, auto gg, MatrixDouble3by3 &mat) {
857 for (auto &v : mat.data())
858 v = set_float_max(set_float_lowest(set_float_precision(v)));
859 return postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1,
860 &*mat.data().begin());
861 };
862
863 for (auto &m : dataMapScalar) {
864 if (const auto *vec_ptr =
865 std::get_if<boost::shared_ptr<VectorDouble>>(&m.second);
866 vec_ptr && *vec_ptr) {
867 auto th = get_tag(m.first, 1);
868 auto t_scl = getFTensor0FromVec(**vec_ptr);
869 auto nb_integration_pts = O::getGaussPts().size2();
870 for (int gg = 0; gg != nb_integration_pts; ++gg) {
871 CHKERR set_tag(th, gg, set_scalar(t_scl));
872 ++t_scl;
873 }
874 } else if (const auto *mat_ptr =
875 std::get_if<boost::shared_ptr<MatrixDouble>>(&m.second);
876 mat_ptr && *mat_ptr) {
877 auto th = get_tag(m.first, 1);
878 auto nb_integration_pts = O::getGaussPts().size2();
879 for (int gg = 0; gg != nb_integration_pts; ++gg)
880 CHKERR set_tag(th, gg, set_scalar((**mat_ptr)(gg, 0)));
881 }
882 }
883
884 for (auto &m : dataMapVec) {
885 if (m.second) {
886 auto th = get_tag(m.first, 3);
887 auto nb_integration_pts = O::getGaussPts().size2();
888 auto t_vec = getFTensor1FromMat<DIM1>(m.second);
889 for (int gg = 0; gg != nb_integration_pts; ++gg) {
890 CHKERR set_tag(th, gg, set_vector_3d(t_vec));
891 ++t_vec;
892 }
893 }
894 }
895
896 for (auto &m : dataMapMat) {
897 if (m.second) {
898 auto th = get_tag(m.first, 9);
899 auto nb_integration_pts = O::getGaussPts().size2();
900 auto t_mat = getFTensor2FromMat<DIM1, DIM2>(m.second);
901 for (int gg = 0; gg != nb_integration_pts; ++gg) {
902 CHKERR set_tag(th, gg, set_matrix_3d(t_mat));
903 ++t_mat;
904 }
905 }
906 }
907
908 for (auto &m : dataMapSymmMat) {
909 if (m.second) {
910 auto th = get_tag(m.first, 9);
911 auto nb_integration_pts = O::getGaussPts().size2();
912 auto t_mat = getFTensor2SymmetricFromMat<DIM1>(m.second);
913 for (int gg = 0; gg != nb_integration_pts; ++gg) {
914 CHKERR set_tag(th, gg, set_matrix_symm_3d(t_mat));
915 ++t_mat;
916 }
917 }
918 }
919
921}
922
923// TagsRange value type is expected to decompose as:
924// std::tuple<std::string, Tag, int>
925template <int DIM1, int DIM2, typename TagsRange,
928 moab::Interface &mesh,
929 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &post_proc_pip,
930 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &physical_pip,
931 moab::Interface &post_proc_mesh, std::vector<EntityHandle> &map_gauss_pts,
932 const TagsRange &tags, int order,
934 const FieldSpace s = L2) {
936 using TagInfo = std::decay_t<decltype(*std::begin(tags))>;
938 using DataMapVec = typename MapOp::DataMapVec;
939 using DataMapMat = typename MapOp::DataMapMat;
940
941 struct OpReadTagData : public Op {
942 using MatrixPtr = boost::shared_ptr<MatrixDouble>;
943
944 OpReadTagData(moab::Interface &mesh,
945 boost::shared_ptr<std::vector<TagInfo>> tags_ptr,
946 boost::shared_ptr<std::vector<MatrixPtr>> mats_ptr)
947 : Op(NOSPACE, Op::OPSPACE), meshRef(mesh), tagsPtr(tags_ptr),
948 matsPtr(mats_ptr) {}
949
950 MoFEMErrorCode doWork(int side, EntityType type,
951 EntitiesFieldData::EntData &data) override {
953 (void)side;
954 (void)type;
955 (void)data;
956
957 const auto nb_gauss_pts = Op::getGaussPts().size2();
958 const auto ent = Op::getFEEntityHandle();
959
960 for (size_t ii = 0; ii != tagsPtr->size(); ++ii) {
961 const auto &[name, tag, num_components] = (*tagsPtr)[ii];
962 auto &mat = *(*matsPtr)[ii];
963 mat.resize(nb_gauss_pts, num_components, false);
964 std::fill(mat.data().begin(), mat.data().end(), 0.);
965
966 if (!tag || !ent)
967 continue;
968
969 double *tag_data = nullptr;
970 int tag_size = 0;
971 auto rval =
972 meshRef.tag_get_by_ptr(tag, &ent, 1, (const void **)&tag_data,
973 &tag_size);
974 if (rval != MB_SUCCESS || !tag_data || tag_size <= 0)
975 continue;
976
977 if (tag_size % num_components != 0) {
978 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
979 "Inconsistent tag size for %s", name.c_str());
980 }
981
982 const auto stored_nb_gauss_pts = tag_size / num_components;
983 const auto copy_nb_gauss_pts =
984 std::min<int>(nb_gauss_pts, stored_nb_gauss_pts);
985 for (int gg = 0; gg != copy_nb_gauss_pts; ++gg)
986 for (int cc = 0; cc != num_components; ++cc)
987 mat(gg, cc) = tag_data[gg * num_components + cc];
988 }
989
991 }
992
993 private:
994 moab::Interface &meshRef;
995 boost::shared_ptr<std::vector<TagInfo>> tagsPtr;
996 boost::shared_ptr<std::vector<MatrixPtr>> matsPtr;
997 };
998
999 auto tags_ptr = boost::make_shared<std::vector<TagInfo>>();
1000 for (const auto &tag_info : tags) {
1001 const auto &[name, tag, num_components] = tag_info;
1002 if (name.empty() || num_components <= 0 || !tag)
1003 continue;
1004 tags_ptr->push_back(tag_info);
1005 }
1006
1007 if (tags_ptr->empty())
1009
1010 auto entity_data_l2 = boost::make_shared<EntitiesFieldData>(MBENTITYSET);
1011 auto mass_ptr = boost::make_shared<MatrixDouble>();
1012 auto data_ptrs = boost::make_shared<std::vector<boost::shared_ptr<MatrixDouble>>>();
1013 DataMapVec scalar_data;
1014 DataMapMat vector_data;
1015 DataMapMat tensor_data;
1016 DataMapMat symm_tensor_data;
1017
1018 physical_pip.push_back(
1019 new OpDGProjectionMassMatrix(order, mass_ptr, entity_data_l2, b, s));
1020 physical_pip.push_back(new OpReadTagData(mesh, tags_ptr, data_ptrs));
1021
1022 for (const auto &tag_info : *tags_ptr) {
1023 const auto &[name, tag, num_components] = tag_info;
1024 auto data_ptr = boost::make_shared<MatrixDouble>();
1025 auto coeffs_ptr = boost::make_shared<MatrixDouble>();
1026 data_ptrs->push_back(data_ptr);
1027
1028 physical_pip.push_back(new OpDGProjectionCoefficients(
1029 data_ptr, coeffs_ptr, mass_ptr, entity_data_l2, b, s, Sev::noisy,
1031 post_proc_pip.push_back(new OpDGProjectionEvaluation(
1032 data_ptr, coeffs_ptr, entity_data_l2, b, s, Sev::noisy,
1034 switch (num_components) {
1035 case 1:
1036 scalar_data[name] = data_ptr;
1037 break;
1038 case 2:
1039 case 3:
1040 vector_data[name] = data_ptr;
1041 break;
1042 case 6:
1043 symm_tensor_data[name] = data_ptr;
1044 break;
1045 case 4:
1046 case 9:
1047 tensor_data[name] = data_ptr;
1048 break;
1049 default:
1050 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1051 "Tag postprocessing supports only 1, 2, 3, 4, 6 or 9 "
1052 "components");
1053 }
1054 }
1055
1056 post_proc_pip.push_back(new MapOp(post_proc_mesh, map_gauss_pts, scalar_data,
1057 vector_data, tensor_data,
1058 symm_tensor_data));
1059
1061}
1062
1063template <typename PostProcEle> struct PostProcBrokenMeshInMoabBaseBeginImpl;
1064
1065template <typename E>
1067 : protected PostProcBrokenMeshInMoabBase<E> {
1068
1070 MoFEM::Interface &m_field, boost::shared_ptr<moab::Core> core_mesh_ptr,
1071 std::string opts_prefix = "")
1072 : PostProcBrokenMeshInMoabBase<E>(m_field, core_mesh_ptr, opts_prefix) {}
1073
1076 CHKERR this->getPostProcMesh().delete_mesh();
1078 }
1079
1080 inline FEMethod *getFEMethod() { return this; }
1081
1084};
1085
1086template <typename PostProcEle> struct PostProcBrokenMeshInMoabBaseContImpl;
1087
1088template <typename E>
1090 : public PostProcBrokenMeshInMoabBase<E> {
1091
1093 MoFEM::Interface &m_field, boost::shared_ptr<moab::Core> core_mesh_ptr,
1094 std::string opts_prefix = "")
1095 : PostProcBrokenMeshInMoabBase<E>(m_field, core_mesh_ptr, opts_prefix) {}
1096
1099
1100protected:
1102};
1103
1104template <typename PostProcEle> struct PostProcBrokenMeshInMoabBaseEndImpl;
1105
1106template <typename E>
1108 : protected PostProcBrokenMeshInMoabBase<E> {
1109
1111 MoFEM::Interface &m_field, boost::shared_ptr<moab::Core> core_mesh_ptr,
1112 std::string opts_prefix = "")
1113 : PostProcBrokenMeshInMoabBase<E>(m_field, core_mesh_ptr, opts_prefix) {}
1114
1119 auto pcomm_post_proc_mesh = this->getPostProcMeshPcommPtr();
1120 if (!pcomm_post_proc_mesh)
1121 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1122 "ParallelComm not allocated");
1123 CHKERR pcomm_post_proc_mesh->resolve_shared_ents(0);
1125 }
1126
1127 inline FEMethod *getFEMethod() { return this; }
1128
1130};
1131
1132/**
1133 * @brief Enable to run stack of post-processing elements. Use this to begin stack.
1134 *
1135 * See @ref scalar_check_approximation.cpp
1136 *
1137 */
1140
1141/**
1142 * @brief Enable to run stack of post-processing elements.
1143 *
1144 * See @ref scalar_check_approximation.cpp
1145 *
1146 * @tparam E
1147 */
1148template <typename E>
1151
1152/**
1153 * @brief Enable to run stack of post-processing elements. Use this to end stack.
1154 *
1155 */
1158
1159
1160} // namespace MoFEM
1161
1162#endif //__POSTPROCBROKENMESHINMOABBASE_HPP
std::string type
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
FieldApproximationBase
approximation base
Definition definitions.h:58
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
FieldSpace
approximation spaces
Definition definitions.h:82
@ L2
field with C-1 continuity
Definition definitions.h:88
@ NOSPACE
Definition definitions.h:83
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHK_MOAB_THROW(err, msg)
Check error code of MoAB function and throw MoFEM exception.
@ MOFEM_OPERATION_UNSUCCESSFUL
Definition definitions.h:34
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
constexpr int order
MoFEMErrorCode writeFile(const std::string file_name)
wrote results in (MOAB) format, use "file_name.h5m"
#define MOFEM_LOG(channel, severity)
Log.
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
const double v
phase velocity of light in medium (cm/ns)
constexpr int DIM2
Definition level_set.cpp:22
constexpr int DIM1
Definition level_set.cpp:21
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto type_from_handle(const EntityHandle h)
get type from entity handle
boost::shared_ptr< PostProcGenerateRefMeshBase > PostProcGenerateRefMeshPtr
MoFEMErrorCode addTagDGProjectionOps(moab::Interface &mesh, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &post_proc_pip, boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &physical_pip, moab::Interface &post_proc_mesh, std::vector< EntityHandle > &map_gauss_pts, const TagsRange &tags, int order, const FieldApproximationBase b=AINSWORTH_LEGENDRE_BASE, const FieldSpace s=L2)
static auto getFTensor0FromVec(V &data)
Get tensor rank 0 (scalar) form data vector.
constexpr double t
plate stiffness
Definition plate.cpp:58
FTensor::Index< 'm', 3 > m
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
Structure for user loop methods on finite elements.
@ OPSPACE
operator do Work is execute on space data
static auto getOrCreate(moab::Core *core_mesh_ptr)
Evaluate field for given DG projection coefficients.
Evaluate right hand side for given data coefficients.
Post post-proc data at points from hash maps.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
std::variant< boost::shared_ptr< VectorDouble >, boost::shared_ptr< MatrixDouble > > ScalarDataPtr
std::map< std::string, ScalarDataPtr > DataMapVec
std::vector< EntityHandle > & mapGaussPts
std::map< std::string, boost::shared_ptr< MatrixDouble > > DataMapMat
OpPostProcMapInMoab(moab::Interface &post_proc_mesh, std::vector< EntityHandle > &map_gauss_pts, DataMapVec data_map_scalar, DataMapMat data_map_vec, DataMapMat data_map_mat, DataMapMat data_symm_map_mat)
Construct a new OpPostProcMapInMoab object.
PostProcBrokenMeshInMoabBaseBeginImpl(MoFEM::Interface &m_field, boost::shared_ptr< moab::Core > core_mesh_ptr, std::string opts_prefix="")
PostProcBrokenMeshInMoabBaseContImpl(MoFEM::Interface &m_field, boost::shared_ptr< moab::Core > core_mesh_ptr, std::string opts_prefix="")
PostProcBrokenMeshInMoabBaseEndImpl(MoFEM::Interface &m_field, boost::shared_ptr< moab::Core > core_mesh_ptr, std::string opts_prefix="")
auto & getPostProcElements()
Get postprocessing elements.
MoFEMErrorCode preProcess()
Generate vertices and elements.
PostProcBrokenMeshInMoabBase(MoFEM::Interface &m_field, boost::shared_ptr< moab::Core > core_mesh_ptr, std::string opts_prefix="")
PostProcBrokenMeshInMoabBase(MoFEM::Interface &m_field, std::string opts_prefix="")
auto & getMapGaussPts()
Get vector of vectors associated to integration points.
auto & getPostProcMesh()
Get postprocessing mesh.
virtual int getMaxLevel() const
Determine refinement level based on fields approx ordre.
MoFEMErrorCode setTagsToTransfer(std::vector< Tag > tags_to_transfer)
Set tags to be transferred to post-processing mesh.
std::map< EntityType, PostProcGenerateRefMeshPtr > refElementsMap
virtual MoFEMErrorCode generateReferenceElementMesh()=0
virtual ~PostProcGenerateRefMeshBase()=default
std::vector< ublas::matrix< int > > levelRef
virtual MoFEMErrorCode getOptions(std::string prefix)
Element for postprocessing. Uses MoAB to generate post-processing mesh.