v0.16.3
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 <typename E> struct PostProcBrokenMeshInMoabBase : public E {
95
97 std::string opts_prefix = "");
99 boost::shared_ptr<moab::Core> core_mesh_ptr,
100 std::string opts_prefix = "");
101
103
104 /**
105 * @brief Get vector of vectors associated to integration points
106 *
107 * @return std::vector<EntityHandle>&
108 */
109 inline auto &getMapGaussPts();
110
111 /**
112 * @brief Get postprocessing mesh
113 *
114 * @return moab::Interface&
115 */
116 inline auto &getPostProcMesh();
117
118 /**
119 * @brief Get postprocessing elements
120 *
121 * @return auto&
122 */
123 inline auto &getPostProcElements();
124
125 /**
126 * \brief wrote results in (MOAB) format, use "file_name.h5m"
127 * @param file_name file name (should always end with .h5m)
128 * @return error code
129 * \ingroup mofem_fs_post_proc
130 */
131 MoFEMErrorCode writeFile(const std::string file_name);
132
133 /**
134 * @brief Set tags to be transferred to post-processing mesh
135 *
136 * @param tags_to_transfer
137 * @return MoFEMErrorCode
138 */
139 MoFEMErrorCode setTagsToTransfer(std::vector<Tag> tags_to_transfer);
140
141protected:
142
144
145 /**
146 * @brief Generate vertices and elements
147 *
148 * @return MoFEMErrorCode
149 */
151
153
154 int getRule(int order);
155
156 /**
157 * @brief Determine refinement level based on fields approx ordre.
158 *
159 * level = (order - 1) / 2
160 *
161 * @return int
162 */
163 virtual int getMaxLevel() const;
164
165 boost::shared_ptr<moab::Core> coreMeshPtr = boost::make_shared<moab::Core>();
166
167 std::vector<EntityHandle> mapGaussPts;
169
170 std::map<EntityType, PostProcGenerateRefMeshPtr>
171 refElementsMap; ///< Storing data about element types, and data for
172 ///< ReadUtilIface to create element entities on
173 ///< post-process mesh.
174 std::vector<Tag> tagsToTransfer; ///< Set of tags on mesh to transfer to
175 ///< postprocessing mesh
176 std::string optionsPrefix = ""; ///< Prefix for options
177
180
181 virtual MoFEMErrorCode transferTags(); ///< transfer tags from mesh to
182 ///< post-process mesh
183
187
188};
189
190template <typename E>
192 std::vector<Tag> tags_to_transfer) {
194 tagsToTransfer.swap(tags_to_transfer);
196}
197
198template <typename E> int PostProcBrokenMeshInMoabBase<E>::getMaxLevel() const {
199 auto get_element_max_dofs_order = [&]() {
200 int max_order = 0;
201 auto dofs_vec = E::getDataVectorDofsPtr();
202 for (auto &dof : *dofs_vec) {
203 const int dof_order = dof->getDofOrder();
204 max_order = (max_order < dof_order) ? dof_order : max_order;
205 };
206 return max_order;
207 };
208 const auto dof_max_order = get_element_max_dofs_order();
209 return (dof_max_order > 0) ? (dof_max_order - 1) / 2 : 0;
210};
211
212template <typename E>
215
216 auto &calc_mesh = this->mField.get_moab();
217
218 auto name = [&](auto tag) {
219 std::string name;
220 CHK_MOAB_THROW(calc_mesh.tag_get_name(tag, name), "get name");
221 return name;
222 };
223
224 auto data_type = [&](auto tag) {
225 moab::DataType data_type;
226 CHK_MOAB_THROW(calc_mesh.tag_get_data_type(tag, data_type),
227 "get data type");
228 return data_type;
229 };
230
231 auto type = [&](auto tag) {
232 moab::TagType type;
233 CHK_MOAB_THROW(calc_mesh.tag_get_type(tag, type), "get tag type");
234 return type;
235 };
236
237 auto length = [&](auto tag) {
238 int length;
239 CHK_MOAB_THROW(calc_mesh.tag_get_length(tag, length), "get length ");
240 return length;
241 };
242
243 auto default_value = [&](auto tag) {
244 const void *def_val;
245 int size;
246 CHK_MOAB_THROW(calc_mesh.tag_get_default_value(tag, def_val, size),
247 "get default tag value");
248 return def_val;
249 };
250
251 std::vector<double> tag_data_vec;
252 auto data_ptr = [&](auto tag) {
253 const void *tag_data;
254 auto core_ent = this->getFEEntityHandle();
255 CHK_MOAB_THROW(calc_mesh.tag_get_by_ptr(tag, &core_ent, 1, &tag_data),
256 "get tag data");
257 if (data_type(tag) == MB_TYPE_DOUBLE) {
258 tag_data_vec.resize(length(tag));
259 std::copy(static_cast<const double *>(tag_data),
260 static_cast<const double *>(tag_data) + length(tag),
261 tag_data_vec.begin());
262 for (auto &v : tag_data_vec)
263 v = std::abs(v) < std::numeric_limits<float>::min() ? 0. : v;
264 for (auto &v : tag_data_vec)
265 v = v > std::numeric_limits<float>::max()
266 ? std::numeric_limits<float>::max()
267 : v;
268 for (auto &v : tag_data_vec)
269 v = v < std::numeric_limits<float>::lowest()
270 ? std::numeric_limits<float>::lowest()
271 : v;
272 return static_cast<const void *>(tag_data_vec.data());
273 }
274 return tag_data;
275 };
276
277 for (auto tag : tagsToTransfer) {
278 Tag tag_postproc;
279 CHKERR getPostProcMesh().tag_get_handle(
280 name(tag).c_str(), length(tag), data_type(tag), tag_postproc,
281 type(tag) | MB_TAG_CREAT, default_value(tag));
282 CHKERR getPostProcMesh().tag_clear_data(tag_postproc, postProcElements,
283 data_ptr(tag));
284 }
285
287};
288
289template <typename E>
291 MoFEM::Interface &m_field, std::string opts_prefix)
292 : E(m_field), optionsPrefix(opts_prefix) {}
293
294template <typename E>
296 MoFEM::Interface &m_field, boost::shared_ptr<moab::Core> core_mesh_ptr,
297 std::string opts_prefix)
298 : PostProcBrokenMeshInMoabBase(m_field, opts_prefix) {
299 coreMeshPtr = core_mesh_ptr;
300}
301
302template <typename E>
306
307template <typename E> int PostProcBrokenMeshInMoabBase<E>::getRule(int order) {
308 return -1;
309};
310
311template <typename E>
314
315 auto type = type_from_handle(this->getFEEntityHandle());
316
318
319 try {
320 ref_ele = refElementsMap.at(type);
321 } catch (const out_of_range &e) {
322 SETERRQ(
323 PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
324 "Generation of reference elements for type <%s> is not implemented",
325 moab::CN::EntityTypeName(type));
326 }
327
328 auto set_gauss_pts = [&](auto &level_gauss_pts_on_ref_mesh, auto &level_ref,
329 auto &level_shape_functions,
330
331 auto start_vert_handle, auto start_ele_handle,
332 auto &verts_array, auto &conn, auto &ver_count,
333 auto &ele_count
334
335 ) {
337
338 size_t level = getMaxLevel();
339 level = std::min(level, level_gauss_pts_on_ref_mesh.size() - 1);
340
341 auto &level_ref_gauss_pts = level_gauss_pts_on_ref_mesh[level];
342 auto &level_ref_ele = level_ref[level];
343 auto &shape_functions = level_shape_functions[level];
344 E::gaussPts.resize(level_ref_gauss_pts.size1(), level_ref_gauss_pts.size2(),
345 false);
346 noalias(E::gaussPts) = level_ref_gauss_pts;
347
348 const auto fe_ent = E::numeredEntFiniteElementPtr->getEnt();
349 auto get_fe_coords = [&]() {
350 const EntityHandle *conn;
351 int num_nodes;
353 E::mField.get_moab().get_connectivity(fe_ent, conn, num_nodes, true),
354 "error get connectivity");
355 VectorDouble coords(num_nodes * 3);
357 E::mField.get_moab().get_coords(conn, num_nodes, &*coords.begin()),
358 "error get coordinates");
359 return coords;
360 };
361
362 auto coords = get_fe_coords();
363
364 const int num_nodes = level_ref_gauss_pts.size2();
365 mapGaussPts.resize(level_ref_gauss_pts.size2());
366
367 FTensor::Index<'i', 3> i;
369 &*shape_functions.data().begin());
371 &verts_array[0][ver_count], &verts_array[1][ver_count],
372 &verts_array[2][ver_count]);
373 for (int gg = 0; gg != num_nodes; ++gg, ++ver_count) {
374
375 mapGaussPts[gg] = start_vert_handle + ver_count;
376
377 auto set_float_precision = [](const double x) {
378 if (std::abs(x) < std::numeric_limits<float>::epsilon())
379 return 0.;
380 else
381 return x;
382 };
383
384 t_coords(i) = 0;
385 auto t_ele_coords = getFTensor1FromArray<3, 3>(coords);
386 for (int nn = 0; nn != CN::VerticesPerEntity(type); ++nn) {
387 t_coords(i) += t_n * t_ele_coords(i);
388 ++t_ele_coords;
389 ++t_n;
390 }
391
392 for (auto ii : {0, 1, 2})
393 t_coords(ii) = set_float_precision(t_coords(ii));
394
395 ++t_coords;
396 }
397
398 Tag th;
399 int def_in_the_loop = -1;
400 CHKERR getPostProcMesh().tag_get_handle(
401 "NB_IN_THE_LOOP", 1, MB_TYPE_INTEGER, th, MB_TAG_CREAT | MB_TAG_SPARSE,
402 &def_in_the_loop);
403
404 postProcElements.clear();
405 const int num_el = level_ref_ele.size1();
406 const int num_nodes_on_ele = level_ref_ele.size2();
407 auto start_e = start_ele_handle + ele_count;
408 postProcElements = Range(start_e, start_e + num_el - 1);
409 for (auto tt = 0; tt != level_ref_ele.size1(); ++tt, ++ele_count) {
410 for (int nn = 0; nn != num_nodes_on_ele; ++nn) {
411 conn[num_nodes_on_ele * ele_count + nn] =
412 mapGaussPts[level_ref_ele(tt, nn)];
413 }
414 }
415
416 const int n_in_the_loop = E::nInTheLoop;
417 CHKERR getPostProcMesh().tag_clear_data(th, postProcElements,
418 &n_in_the_loop);
419 CHKERR transferTags();
420
422 };
423
424 CHKERR set_gauss_pts(
425
426 ref_ele->levelGaussPtsOnRefMesh, ref_ele->levelRef,
427 ref_ele->levelShapeFunctions,
428
429 ref_ele->startingVertEleHandle, ref_ele->startingEleHandle,
430 ref_ele->verticesOnEleArrays, ref_ele->eleConn, ref_ele->countVertEle,
431 ref_ele->countEle
432
433 );
434
436};
437
438template <typename E>
441
442auto get_ref_ele = [&](const EntityType type) {
443 PostProcGenerateRefMeshPtr ref_ele_ptr;
444
445 auto it = refElementsMap.find(type);
446 if (it != refElementsMap.end()) {
447 ref_ele_ptr = it->second;
448 } else {
449 switch (type) {
450 case MBTET:
451 ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBTET>>();
452 break;
453 case MBHEX:
454 ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBHEX>>();
455 break;
456 case MBTRI:
457 ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBTRI>>();
458 break;
459 case MBQUAD:
460 ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBQUAD>>();
461 break;
462 case MBEDGE:
463 ref_ele_ptr = boost::make_shared<PostProcGenerateRefMesh<MBEDGE>>();
464 break;
465 default:
466 MOFEM_LOG("SELF", Sev::error)
467 << "Generation of reference elements for type < "
468 << moab::CN::EntityTypeName(type) << " > is not implemented";
469 CHK_THROW_MESSAGE(MOFEM_NOT_IMPLEMENTED, "Element not implemented");
470 }
471
472 CHK_THROW_MESSAGE(ref_ele_ptr->getOptions(optionsPrefix), "getOptions");
473 CHK_THROW_MESSAGE(ref_ele_ptr->generateReferenceElementMesh(),
474 "Error when generating reference element");
475
476 refElementsMap[type] = ref_ele_ptr;
477 }
478
479 return ref_ele_ptr;
480};
481
482 auto fe_ptr = this->problemPtr->numeredFiniteElementsPtr;
483
484 auto miit =
485 fe_ptr->template get<Composite_Name_And_Part_mi_tag>().lower_bound(
486 boost::make_tuple(this->getFEName(), this->getLoFERank()));
487 auto hi_miit =
488 fe_ptr->template get<Composite_Name_And_Part_mi_tag>().upper_bound(
489 boost::make_tuple(this->getFEName(), this->getHiFERank()));
490
491 const int number_of_ents_in_the_loop = this->getLoopSize();
492 if (std::distance(miit, hi_miit) != number_of_ents_in_the_loop) {
493 SETERRQ(E::mField.get_comm(), MOFEM_DATA_INCONSISTENCY,
494 "Wrong size of indicies. Inconsistent size number of iterated "
495 "elements iterated by problem and from range.");
496 }
497
498 for (auto &m : refElementsMap) {
499 m.second->nbVertices = 0;
500 m.second->nbEles = 0;
501 m.second->countEle = 0;
502 m.second->countVertEle = 0;
503 }
504
505 for (; miit != hi_miit; ++miit) {
506 auto type = (*miit)->getEntType();
507 auto ref_ele = get_ref_ele(type);
508
509 // Set pointer to element. So that getDataVectorDofsPtr in getMaxLevel
510 // can work
511 E::numeredEntFiniteElementPtr = *miit;
512 bool add = true;
513 if (E::exeTestHook) {
514 add = E::exeTestHook(this);
515 }
516
517 if (add) {
518 size_t level = getMaxLevel();
519 level = std::min(level, ref_ele->levelGaussPtsOnRefMesh.size() - 1);
520 ref_ele->nbVertices += ref_ele->levelGaussPtsOnRefMesh[level].size2();
521 ref_ele->nbEles += ref_ele->levelRef[level].size1();
522 }
523 }
524
525 auto alloc_vertices_and_elements_on_post_proc_mesh = [&]() {
527
528 ReadUtilIface *iface;
529 CHKERR getPostProcMesh().query_interface(iface);
530
531 for (auto &m : refElementsMap) {
532 if (m.second->nbEles) {
533 CHKERR iface->get_node_coords(3, m.second->nbVertices, 0,
534 m.second->startingVertEleHandle,
535 m.second->verticesOnEleArrays);
536 CHKERR iface->get_element_connect(
537 m.second->nbEles, m.second->levelRef[0].size2(), m.first, 0,
538 m.second->startingEleHandle, m.second->eleConn);
539
540 m.second->countEle = 0;
541 m.second->countVertEle = 0;
542 }
543 }
544
546 };
547
548 CHKERR alloc_vertices_and_elements_on_post_proc_mesh();
549
551}
552
553template <typename E>
556
557 auto update_elements = [&]() {
558 ReadUtilIface *iface;
559 CHKERR getPostProcMesh().query_interface(iface);
561
562 Range ents;
563 for (auto &m : refElementsMap) {
564 if (m.second->nbEles) {
565 MOFEM_TAG_AND_LOG("SELF", Sev::noisy, "PostProc")
566 << "Update < " << moab::CN::EntityTypeName(m.first)
567 << " number of processed " << m.second->countEle;
568 CHKERR iface->update_adjacencies(
569 m.second->startingEleHandle, m.second->countEle,
570 m.second->levelRef[0].size2(), m.second->eleConn);
571 ents.merge(Range(m.second->startingEleHandle,
572 m.second->startingEleHandle + m.second->countEle - 1));
573 }
574 }
575
577 };
578
579 auto remove_obsolete_entities = [&]() {
581 Range ents, adj;
582 for (auto &m : refElementsMap) {
583 if (m.second->nbEles) {
584 ents.merge(Range(m.second->startingEleHandle,
585 m.second->startingEleHandle + m.second->countEle - 1));
586 const int dim = moab::CN::Dimension(m.first);
587 for (auto d = 1; d != dim; ++d) {
588 CHKERR getPostProcMesh().get_adjacencies(ents, d, false, adj,
589 moab::Interface::UNION);
590 }
591 }
592 }
593 CHKERR getPostProcMesh().delete_entities(adj);
595 };
596
597 auto set_proc_tags = [&]() {
599 auto pcomm_post_proc_mesh = getPostProcMeshPcommPtr();
600 if (pcomm_post_proc_mesh) {
601 Range ents;
602 for (auto &m : refElementsMap) {
603 if (m.second->nbEles) {
604 ents.merge(
605 Range(m.second->startingEleHandle,
606 m.second->startingEleHandle + m.second->countEle - 1));
607 }
608 }
609 int rank = E::mField.get_comm_rank();
610 CHKERR getPostProcMesh().tag_clear_data(pcomm_post_proc_mesh->part_tag(),
611 ents, &rank);
612 }
614 };
615
616 CHKERR update_elements();
617 CHKERR remove_obsolete_entities();
618 CHKERR set_proc_tags();
619
621}
622
623template <typename E>
626
627 CHKERR getPostProcMesh().delete_mesh();
628
629
630 CHKERR preProcPostProc();
631
633}
634
635template <typename E>
638
639 auto pcomm_post_proc_mesh = getPostProcMeshPcommPtr();
640 if (!pcomm_post_proc_mesh)
641 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
642 "ParallelComm not allocated");
643
644 CHKERR postProcPostProc();
645 CHKERR pcomm_post_proc_mesh->resolve_shared_ents(0);
646
648}
649
651 return mapGaussPts;
652}
653
655 if (!coreMeshPtr)
656 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Core mesh not set");
657 moab::Interface &post_proc_mesh_interface = *coreMeshPtr;
658 return post_proc_mesh_interface;
659}
660
661template <typename E>
663 return postProcElements;
664}
665
666template <typename E>
668PostProcBrokenMeshInMoabBase<E>::writeFile(const std::string file_name) {
670 auto pcomm_post_proc_mesh = getPostProcMeshPcommPtr();
671 if (!pcomm_post_proc_mesh)
672 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
673 "ParallelComm not allocated");
674 CHKERR getPostProcMesh().write_file(file_name.c_str(), "MOAB",
675 "PARALLEL=WRITE_PART");
677};
678
679template <typename E> struct PostProcBrokenMeshInMoab;
680
681template <>
687
688template <>
694
695template <>
701
702/**
703 * @brief Post post-proc data at points from hash maps
704 *
705 * @tparam DIM1 dimension of vector in data_map_vec and first column of
706 * data_map_may
707 * @tparam DIM2 dimension of second column in data_map_mat
708 */
709template <int DIM1, int DIM2,
711struct OpPostProcMapInMoab : public O {
712
714 std::variant<boost::shared_ptr<VectorDouble>,
715 boost::shared_ptr<MatrixDouble>>;
716 using DataMapVec = std::map<std::string, ScalarDataPtr>;
717 using DataMapMat = std::map<std::string, boost::shared_ptr<MatrixDouble>>;
718
719 /**
720 * @brief Construct a new OpPostProcMapInMoab object
721 *
722 * @param post_proc_mesh postprocessing mesh
723 * @param map_gauss_pts map of gauss points to nodes of postprocessing mesh
724 * @param data_map_scalar hash map of scalar values (string is name of the
725 * tag)
726 * @param data_map_vec hash map of vector values
727 * @param data_map_mat hash map of second order tensor values
728 * @param data_symm_map_mat hash map of symmetric second order tensor values
729 */
730 OpPostProcMapInMoab(moab::Interface &post_proc_mesh,
731 std::vector<EntityHandle> &map_gauss_pts,
732 DataMapVec data_map_scalar, DataMapMat data_map_vec,
733 DataMapMat data_map_mat, DataMapMat data_symm_map_mat)
734 : O(NOSPACE, O::OPSPACE), postProcMesh(post_proc_mesh),
735 mapGaussPts(map_gauss_pts), dataMapScalar(data_map_scalar),
736 dataMapVec(data_map_vec), dataMapMat(data_map_mat),
737 dataMapSymmMat(data_symm_map_mat) {
738 // Operator is only executed for vertices
739 std::fill(&O::doEntities[MBEDGE], &O::doEntities[MBMAXTYPE], false);
740 }
741 MoFEMErrorCode doWork(int side, EntityType type,
743
744private:
745 moab::Interface &postProcMesh;
746 std::vector<EntityHandle> &mapGaussPts;
751};
752
753template <int DIM1, int DIM2, typename O>
758
759 std::array<double, 9> def;
760 std::fill(def.begin(), def.end(), 0);
761
762 auto get_tag = [&](const std::string name, size_t size) {
763 Tag th;
764 CHKERR postProcMesh.tag_get_handle(name.c_str(), size, MB_TYPE_DOUBLE, th,
765 MB_TAG_CREAT | MB_TAG_SPARSE,
766 def.data());
767 return th;
768 };
769
770 MatrixDouble3by3 mat(3, 3);
771
772 auto set_vector_3d = [&](auto &t) -> MatrixDouble3by3 & {
773 mat.clear();
774 for (size_t r = 0; r != DIM1; ++r)
775 mat(0, r) = t(r);
776 return mat;
777 };
778
779 auto set_matrix_3d = [&](auto &t) -> MatrixDouble3by3 & {
780 mat.clear();
781 for (size_t r = 0; r != DIM1; ++r)
782 for (size_t c = 0; c != DIM2; ++c)
783 mat(r, c) = t(r, c);
784 return mat;
785 };
786
787 auto set_matrix_symm_3d = [&](auto &t) -> MatrixDouble3by3 & {
788 mat.clear();
789 for (size_t r = 0; r != DIM1; ++r)
790 for (size_t c = 0; c != DIM1; ++c)
791 mat(r, c) = t(r, c);
792 return mat;
793 };
794
795 auto set_scalar = [&](auto t) -> MatrixDouble3by3 & {
796 mat.clear();
797 mat(0, 0) = t;
798 return mat;
799 };
800
801 auto set_float_precision = [](const double x) {
802 if (std::abs(x) < std::numeric_limits<float>::min())
803 return static_cast<float>(0.);
804 else
805 return static_cast<float>(x);
806 };
807
808 auto set_float_max = [](const double x) {
809 if (x > std::numeric_limits<float>::max())
810 return std::numeric_limits<float>::max();
811 else
812 return static_cast<float>(x);
813 };
814
815 auto set_float_lowest = [](const double x) {
816 if (x < std::numeric_limits<float>::lowest())
817 return std::numeric_limits<float>::lowest();
818 else
819 return static_cast<float>(x);
820 };
821
822 auto set_tag = [&](auto th, auto gg, MatrixDouble3by3 &mat) {
823 for (auto &v : mat.data())
824 v = set_float_max(set_float_lowest(set_float_precision(v)));
825 return postProcMesh.tag_set_data(th, &mapGaussPts[gg], 1,
826 &*mat.data().begin());
827 };
828
829 for (auto &m : dataMapScalar) {
830 if (const auto *vec_ptr =
831 std::get_if<boost::shared_ptr<VectorDouble>>(&m.second);
832 vec_ptr && *vec_ptr) {
833 auto th = get_tag(m.first, 1);
834 auto t_scl = getFTensor0FromVec(**vec_ptr);
835 auto nb_integration_pts = O::getGaussPts().size2();
836 for (int gg = 0; gg != nb_integration_pts; ++gg) {
837 CHKERR set_tag(th, gg, set_scalar(t_scl));
838 ++t_scl;
839 }
840 } else if (const auto *mat_ptr =
841 std::get_if<boost::shared_ptr<MatrixDouble>>(&m.second);
842 mat_ptr && *mat_ptr) {
843 auto th = get_tag(m.first, 1);
844 auto nb_integration_pts = O::getGaussPts().size2();
845 for (int gg = 0; gg != nb_integration_pts; ++gg)
846 CHKERR set_tag(th, gg, set_scalar((**mat_ptr)(0, gg)));
847 }
848 }
849
850 for (auto &m : dataMapVec) {
851 if (m.second) {
852 auto th = get_tag(m.first, 3);
853 auto nb_integration_pts = O::getGaussPts().size2();
854 auto t_vec = getFTensor1FromMat<DIM1>(m.second);
855 for (int gg = 0; gg != nb_integration_pts; ++gg) {
856 CHKERR set_tag(th, gg, set_vector_3d(t_vec));
857 ++t_vec;
858 }
859 }
860 }
861
862 for (auto &m : dataMapMat) {
863 if (m.second) {
864 auto th = get_tag(m.first, 9);
865 auto nb_integration_pts = O::getGaussPts().size2();
866 auto t_mat = getFTensor2FromMat<DIM1, DIM2>(m.second);
867 for (int gg = 0; gg != nb_integration_pts; ++gg) {
868 CHKERR set_tag(th, gg, set_matrix_3d(t_mat));
869 ++t_mat;
870 }
871 }
872 }
873
874 for (auto &m : dataMapSymmMat) {
875 if (m.second) {
876 auto th = get_tag(m.first, 9);
877 auto nb_integration_pts = O::getGaussPts().size2();
878 auto t_mat = getFTensor2SymmetricFromMat<DIM1>(m.second);
879 for (int gg = 0; gg != nb_integration_pts; ++gg) {
880 CHKERR set_tag(th, gg, set_matrix_symm_3d(t_mat));
881 ++t_mat;
882 }
883 }
884 }
885
887}
888
889// TagsRange value type is expected to decompose as:
890// std::tuple<std::string, Tag, int>
891template <int DIM1, int DIM2, typename TagsRange,
894 moab::Interface &mesh,
895 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &post_proc_pip,
896 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &physical_pip,
897 moab::Interface &post_proc_mesh, std::vector<EntityHandle> &map_gauss_pts,
898 const TagsRange &tags, int order,
900 const FieldSpace s = L2) {
902 using TagInfo = std::decay_t<decltype(*std::begin(tags))>;
904 using DataMapVec = typename MapOp::DataMapVec;
905 using DataMapMat = typename MapOp::DataMapMat;
906
907 struct OpReadTagData : public Op {
908 using MatrixPtr = boost::shared_ptr<MatrixDouble>;
909 static DataLayout getLayout(const int num_components) {
910 return num_components == 1 ? DataLayout::CoeffsByGauss
911 : DataLayout::GaussByCoeffs;
912 }
913
914 OpReadTagData(moab::Interface &mesh,
915 boost::shared_ptr<std::vector<TagInfo>> tags_ptr,
916 boost::shared_ptr<std::vector<MatrixPtr>> mats_ptr)
917 : Op(NOSPACE, Op::OPSPACE), meshRef(mesh), tagsPtr(tags_ptr),
918 matsPtr(mats_ptr) {}
919
920 MoFEMErrorCode doWork(int side, EntityType type,
921 EntitiesFieldData::EntData &data) override {
923 (void)side;
924 (void)type;
925 (void)data;
926
927 const auto nb_gauss_pts = Op::getGaussPts().size2();
928 const auto ent = Op::getFEEntityHandle();
929
930 for (size_t ii = 0; ii != tagsPtr->size(); ++ii) {
931 const auto &[name, tag, num_components] = (*tagsPtr)[ii];
932 const auto data_layout = getLayout(num_components);
933 auto &mat = *(*matsPtr)[ii];
934 const auto nb_data_rows = data_layout == DataLayout::CoeffsByGauss
935 ? num_components
936 : nb_gauss_pts;
937 const auto nb_data_cols = data_layout == DataLayout::CoeffsByGauss
938 ? nb_gauss_pts
939 : num_components;
940 mat.resize(nb_data_rows, nb_data_cols, false);
941 std::fill(mat.data().begin(), mat.data().end(), 0.);
942
943 if (!tag || !ent)
944 continue;
945
946 double *tag_data = nullptr;
947 int tag_size = 0;
948 auto rval =
949 meshRef.tag_get_by_ptr(tag, &ent, 1, (const void **)&tag_data,
950 &tag_size);
951 if (rval != MB_SUCCESS || !tag_data || tag_size <= 0)
952 continue;
953
954 if (tag_size % num_components != 0) {
955 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
956 "Inconsistent tag size for %s", name.c_str());
957 }
958
959 const auto stored_nb_gauss_pts = tag_size / num_components;
960 const auto copy_nb_gauss_pts =
961 std::min<int>(nb_gauss_pts, stored_nb_gauss_pts);
962 for (int gg = 0; gg != copy_nb_gauss_pts; ++gg) {
963 for (int cc = 0; cc != num_components; ++cc) {
964 const auto r = data_layout == DataLayout::CoeffsByGauss ? cc : gg;
965 const auto c = data_layout == DataLayout::CoeffsByGauss ? gg : cc;
966 mat(r, c) = tag_data[gg * num_components + cc];
967 }
968 }
969 }
970
972 }
973
974 private:
975 moab::Interface &meshRef;
976 boost::shared_ptr<std::vector<TagInfo>> tagsPtr;
977 boost::shared_ptr<std::vector<MatrixPtr>> matsPtr;
978 };
979
980 auto tags_ptr = boost::make_shared<std::vector<TagInfo>>();
981 for (const auto &tag_info : tags) {
982 const auto &[name, tag, num_components] = tag_info;
983 if (name.empty() || num_components <= 0 || !tag)
984 continue;
985 tags_ptr->push_back(tag_info);
986 }
987
988 if (tags_ptr->empty())
990
991 auto entity_data_l2 = boost::make_shared<EntitiesFieldData>(MBENTITYSET);
992 auto mass_ptr = boost::make_shared<MatrixDouble>();
993 auto data_ptrs = boost::make_shared<std::vector<boost::shared_ptr<MatrixDouble>>>();
994 DataMapVec scalar_data;
995 DataMapMat vector_data;
996 DataMapMat tensor_data;
997 DataMapMat symm_tensor_data;
998
999 physical_pip.push_back(
1000 new OpDGProjectionMassMatrix(order, mass_ptr, entity_data_l2, b, s));
1001 physical_pip.push_back(new OpReadTagData(mesh, tags_ptr, data_ptrs));
1002
1003 for (const auto &tag_info : *tags_ptr) {
1004 const auto &[name, tag, num_components] = tag_info;
1005 auto data_ptr = boost::make_shared<MatrixDouble>();
1006 auto coeffs_ptr = boost::make_shared<MatrixDouble>();
1007 data_ptrs->push_back(data_ptr);
1008 const auto data_layout = OpReadTagData::getLayout(num_components);
1009
1010 physical_pip.push_back(new OpDGProjectionCoefficients(
1011 data_ptr, coeffs_ptr, mass_ptr, entity_data_l2, b, s, Sev::noisy,
1012 data_layout));
1013 post_proc_pip.push_back(new OpDGProjectionEvaluation(
1014 data_ptr, coeffs_ptr, entity_data_l2, b, s, Sev::noisy, data_layout));
1015 switch (num_components) {
1016 case 1:
1017 scalar_data[name] = data_ptr;
1018 break;
1019 case 2:
1020 case 3:
1021 vector_data[name] = data_ptr;
1022 break;
1023 case 6:
1024 symm_tensor_data[name] = data_ptr;
1025 break;
1026 case 4:
1027 case 9:
1028 tensor_data[name] = data_ptr;
1029 break;
1030 default:
1031 SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
1032 "Tag postprocessing supports only 1, 2, 3, 4, 6 or 9 "
1033 "components");
1034 }
1035 }
1036
1037 post_proc_pip.push_back(new MapOp(post_proc_mesh, map_gauss_pts, scalar_data,
1038 vector_data, tensor_data,
1039 symm_tensor_data));
1040
1042}
1043
1044template <typename PostProcEle> struct PostProcBrokenMeshInMoabBaseBeginImpl;
1045
1046template <typename E>
1048 : protected PostProcBrokenMeshInMoabBase<E> {
1049
1051 MoFEM::Interface &m_field, boost::shared_ptr<moab::Core> core_mesh_ptr,
1052 std::string opts_prefix = "")
1053 : PostProcBrokenMeshInMoabBase<E>(m_field, core_mesh_ptr, opts_prefix) {}
1054
1057 CHKERR this->getPostProcMesh().delete_mesh();
1059 }
1060
1061 inline FEMethod *getFEMethod() { return this; }
1062
1065};
1066
1067template <typename PostProcEle> struct PostProcBrokenMeshInMoabBaseContImpl;
1068
1069template <typename E>
1071 : public PostProcBrokenMeshInMoabBase<E> {
1072
1074 MoFEM::Interface &m_field, boost::shared_ptr<moab::Core> core_mesh_ptr,
1075 std::string opts_prefix = "")
1076 : PostProcBrokenMeshInMoabBase<E>(m_field, core_mesh_ptr, opts_prefix) {}
1077
1080
1081protected:
1083};
1084
1085template <typename PostProcEle> struct PostProcBrokenMeshInMoabBaseEndImpl;
1086
1087template <typename E>
1089 : protected PostProcBrokenMeshInMoabBase<E> {
1090
1092 MoFEM::Interface &m_field, boost::shared_ptr<moab::Core> core_mesh_ptr,
1093 std::string opts_prefix = "")
1094 : PostProcBrokenMeshInMoabBase<E>(m_field, core_mesh_ptr, opts_prefix) {}
1095
1100 auto pcomm_post_proc_mesh = this->getPostProcMeshPcommPtr();
1101 if (!pcomm_post_proc_mesh)
1102 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1103 "ParallelComm not allocated");
1104 CHKERR pcomm_post_proc_mesh->resolve_shared_ents(0);
1106 }
1107
1108 inline FEMethod *getFEMethod() { return this; }
1109
1111};
1112
1113/**
1114 * @brief Enable to run stack of post-processing elements. Use this to begin stack.
1115 *
1116 * See @ref scalar_check_approximation.cpp
1117 *
1118 */
1121
1122/**
1123 * @brief Enable to run stack of post-processing elements.
1124 *
1125 * See @ref scalar_check_approximation.cpp
1126 *
1127 * @tparam E
1128 */
1129template <typename E>
1132
1133/**
1134 * @brief Enable to run stack of post-processing elements. Use this to end stack.
1135 *
1136 */
1139
1140
1141} // namespace MoFEM
1142
1143#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
#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="")
PostProcBrokenMeshInMoabBase(MoFEM::Interface &m_field, std::string opts_prefix="")
auto & getMapGaussPts()
Get vector of vectors associated to integration points.
MoFEMErrorCode writeFile(const std::string file_name)
wrote results in (MOAB) format, use "file_name.h5m"
MoFEMErrorCode setTagsToTransfer(std::vector< Tag > tags_to_transfer)
Set tags to be transferred to post-processing mesh.
PostProcBrokenMeshInMoabBase(MoFEM::Interface &m_field, boost::shared_ptr< moab::Core > core_mesh_ptr, std::string opts_prefix="")
auto & getPostProcMesh()
Get postprocessing mesh.
std::map< EntityType, PostProcGenerateRefMeshPtr > refElementsMap
auto & getPostProcElements()
Get postprocessing elements.
virtual int getMaxLevel() const
Determine refinement level based on fields approx ordre.
MoFEMErrorCode preProcess()
Generate vertices and elements.
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.