v0.9.0
FECore.cpp
Go to the documentation of this file.
1 /** \file FECore.cpp
2  * \brief Core interface methods for managing deletions and insertion dofs
3  */
4 
5 /* MoFEM is free software: you can redistribute it and/or modify it under
6  * the terms of the GNU Lesser General Public License as published by the
7  * Free Software Foundation, either version 3 of the License, or (at your
8  * option) any later version.
9  *
10  * MoFEM is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
13  * License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with MoFEM. If not, see <http://www.gnu.org/licenses/>
17  */
18 
19 namespace MoFEM {
20 
24  *fe_ptr = &finiteElements;
26 }
27 
29  const EntFiniteElement_multiIndex **fe_ent_ptr) const {
31  *fe_ent_ptr = &entsFiniteElements;
33 }
34 
35 bool Core::check_finite_element(const std::string &name) const {
36  typedef FiniteElement_multiIndex::index<FiniteElement_name_mi_tag>::type
37  FeSetByName;
38  const FeSetByName &set = finiteElements.get<FiniteElement_name_mi_tag>();
39  FeSetByName::iterator miit = set.find(name);
40  if (miit == set.end())
41  return false;
42  return true;
43 }
44 
45 MoFEMErrorCode Core::add_finite_element(const std::string &fe_name,
46  enum MoFEMTypes bh, int verb) {
48  *buildMoFEM &= 1 << 0;
49  if (verb == -1) {
50  verb = verbose;
51  }
52  typedef FiniteElement_multiIndex::index<FiniteElement_name_mi_tag>::type
53  FiniteElements_by_name;
54  FiniteElements_by_name &finite_element_name_set =
56  FiniteElements_by_name::iterator it_fe =
57  finite_element_name_set.find(fe_name);
58  if (bh == MF_EXCL) {
59  if (it_fe != finite_element_name_set.end()) {
60  SETERRQ1(cOmm, MOFEM_NOT_FOUND, "this < %s > is there", fe_name.c_str());
61  }
62  } else {
63  if (it_fe != finite_element_name_set.end())
65  }
66  EntityHandle meshset;
67  CHKERR get_moab().create_meshset(MESHSET_SET | MESHSET_TRACK_OWNER, meshset);
68 
69  // id
70  BitFEId id = getFEShift();
71  CHKERR get_moab().tag_set_data(th_FEId, &meshset, 1, &id);
72 
73  // id name
74  void const *tag_data[] = {fe_name.c_str()};
75  int tag_sizes[1];
76  tag_sizes[0] = fe_name.size();
77  CHKERR get_moab().tag_set_by_ptr(th_FEName, &meshset, 1, tag_data, tag_sizes);
78 
79  // add FiniteElement
80  std::pair<FiniteElement_multiIndex::iterator, bool> p = finiteElements.insert(
81  boost::shared_ptr<FiniteElement>(new FiniteElement(moab, meshset)));
82  if (!p.second)
83  SETERRQ(cOmm, MOFEM_OPERATION_UNSUCCESSFUL, "FiniteElement not inserted");
84  if (verb > 0) {
85  std::ostringstream ss;
86  ss << "add finite element: " << fe_name << std::endl;
87  PetscPrintf(cOmm, ss.str().c_str());
88  // list_finiteElements();
89  }
91 }
92 
95  const EntityType type,
96  ElementAdjacencyFunct function) {
98  *buildMoFEM &= 1 << 0;
99  typedef FiniteElement_multiIndex::index<FiniteElement_name_mi_tag>::type
100  FiniteElements_by_name;
101  FiniteElements_by_name &finite_element_name_set =
103  FiniteElements_by_name::iterator it_fe =
104  finite_element_name_set.find(fe_name);
105  if (it_fe == finite_element_name_set.end()) {
106  SETERRQ(cOmm, MOFEM_NOT_FOUND, "this FiniteElement is there");
107  }
108  boost::shared_ptr<FiniteElement> fe;
109  fe = *it_fe;
110  fe->elementAdjacencyTable[type] = function;
112 }
113 
116  const std::string &name_data) {
118  *buildMoFEM &= 1 << 0;
119  typedef FiniteElement_multiIndex::index<FiniteElement_name_mi_tag>::type
120  FiniteElements_by_name;
121  FiniteElements_by_name &finite_element_name_set =
123  FiniteElements_by_name::iterator it_fe =
124  finite_element_name_set.find(fe_name);
125  if (it_fe == finite_element_name_set.end())
126  SETERRQ(cOmm, MOFEM_NOT_FOUND, "this FiniteElement is there");
127  bool success = finite_element_name_set.modify(
128  it_fe, FiniteElement_change_bit_add(getBitFieldId(name_data)));
129  if (!success)
130  SETERRQ(cOmm, MOFEM_OPERATION_UNSUCCESSFUL, "modification unsuccessful");
132 }
133 
135 Core::modify_finite_element_add_field_row(const std::string &fe_name,
136  const std::string &name_row) {
138  *buildMoFEM &= 1 << 0;
139  typedef FiniteElement_multiIndex::index<FiniteElement_name_mi_tag>::type
140  FiniteElements_by_name;
141  FiniteElements_by_name &finite_element_name_set =
143  FiniteElements_by_name::iterator it_fe =
144  finite_element_name_set.find(fe_name);
145  if (it_fe == finite_element_name_set.end())
146  SETERRQ1(cOmm, MOFEM_NOT_FOUND, "this < %s > is not there",
147  fe_name.c_str());
148  bool success = finite_element_name_set.modify(
150  if (!success)
151  SETERRQ(cOmm, MOFEM_OPERATION_UNSUCCESSFUL, "modification unsuccessful");
153 }
154 
156 Core::modify_finite_element_add_field_col(const std::string &fe_name,
157  const std::string &name_col) {
159  *buildMoFEM &= 1 << 0;
160  typedef FiniteElement_multiIndex::index<FiniteElement_name_mi_tag>::type
161  FiniteElements_by_name;
162  FiniteElements_by_name &finite_element_name_set =
164  FiniteElements_by_name::iterator it_fe =
165  finite_element_name_set.find(fe_name);
166  if (it_fe == finite_element_name_set.end())
167  SETERRQ(cOmm, MOFEM_OPERATION_UNSUCCESSFUL, "this FiniteElement is there");
168  bool success = finite_element_name_set.modify(
170  if (!success)
171  SETERRQ(cOmm, MOFEM_OPERATION_UNSUCCESSFUL, "modification unsuccessful");
173 }
174 
177  const std::string &name_data) {
179  *buildMoFEM &= 1 << 0;
180  typedef FiniteElement_multiIndex::index<FiniteElement_name_mi_tag>::type
181  FiniteElements_by_name;
182  FiniteElements_by_name &finite_element_name_set =
184  FiniteElements_by_name::iterator it_fe =
185  finite_element_name_set.find(fe_name);
186  if (it_fe == finite_element_name_set.end())
187  SETERRQ(cOmm, MOFEM_NOT_FOUND, "this FiniteElement is there");
188  bool success = finite_element_name_set.modify(
189  it_fe, FiniteElement_change_bit_off(getBitFieldId(name_data)));
190  if (!success)
191  SETERRQ(cOmm, MOFEM_OPERATION_UNSUCCESSFUL, "modification unsuccessful");
193 }
194 
196 Core::modify_finite_element_off_field_row(const std::string &fe_name,
197  const std::string &name_row) {
199  *buildMoFEM &= 1 << 0;
200  typedef FiniteElement_multiIndex::index<FiniteElement_name_mi_tag>::type
201  FiniteElements_by_name;
202  FiniteElements_by_name &finite_element_name_set =
204  FiniteElements_by_name::iterator it_fe =
205  finite_element_name_set.find(fe_name);
206  if (it_fe == finite_element_name_set.end())
207  SETERRQ1(cOmm, MOFEM_NOT_FOUND, "this < %s > is not there",
208  fe_name.c_str());
209  bool success = finite_element_name_set.modify(
211  if (!success)
212  SETERRQ(cOmm, MOFEM_OPERATION_UNSUCCESSFUL, "modification unsuccessful");
214 }
215 
217 Core::modify_finite_element_off_field_col(const std::string &fe_name,
218  const std::string &name_col) {
220  *buildMoFEM &= 1 << 0;
221  typedef FiniteElement_multiIndex::index<FiniteElement_name_mi_tag>::type
222  FiniteElements_by_name;
223  FiniteElements_by_name &finite_element_name_set =
225  FiniteElements_by_name::iterator it_fe =
226  finite_element_name_set.find(fe_name);
227  if (it_fe == finite_element_name_set.end())
228  SETERRQ(cOmm, MOFEM_NOT_FOUND, "this FiniteElement is there");
229  try {
230  bool success = finite_element_name_set.modify(
232  if (!success)
233  SETERRQ(cOmm, MOFEM_OPERATION_UNSUCCESSFUL, "modification unsuccessful");
234  } catch (MoFEMException const &e) {
235  SETERRQ(cOmm, e.errorCode, e.errorMessage);
236  }
238 }
239 
240 BitFEId Core::getBitFEId(const std::string &name) const {
241  typedef FiniteElement_multiIndex::index<FiniteElement_name_mi_tag>::type
242  FiniteElements_by_name;
243  const FiniteElements_by_name &set =
245  FiniteElements_by_name::iterator miit = set.find(name);
246  if (miit == set.end())
248  ("finite element < " + name + " > not found (top tip: check spelling)")
249  .c_str());
250  return (*miit)->getId();
251 }
252 
253 std::string Core::getBitFEIdName(const BitFEId id) const {
254  typedef FiniteElement_multiIndex::index<BitFEId_mi_tag>::type
255  finiteElements_by_id;
256  const finiteElements_by_id &set = finiteElements.get<BitFEId_mi_tag>();
257  finiteElements_by_id::iterator miit = set.find(id);
258  assert(miit != set.end());
259  return (*miit)->getName();
260 }
261 
263  typedef FiniteElement_multiIndex::index<BitFEId_mi_tag>::type
264  finiteElements_by_id;
265  const finiteElements_by_id &set = finiteElements.get<BitFEId_mi_tag>();
266  finiteElements_by_id::iterator miit = set.find(id);
267  if (miit == set.end())
268  THROW_MESSAGE("finite element not found");
269  return (*miit)->meshset;
270 }
271 
272 EntityHandle Core::get_finite_element_meshset(const std::string &name) const {
274 }
275 
277 Core::get_finite_element_entities_by_dimension(const std::string name, int dim,
278  Range &ents) const {
279 
281 
283  CHKERR get_moab().get_entities_by_dimension(meshset, dim, ents, true);
285 }
286 
288  EntityType type,
289  Range &ents) const {
290 
292 
294  CHKERR get_moab().get_entities_by_type(meshset, type, ents, true);
295 
297 }
298 
301  Range &ents) const {
302 
304 
306  CHKERR get_moab().get_entities_by_handle(meshset, ents, true);
307 
309 }
310 
313  typedef FiniteElement_multiIndex::index<BitFEId_mi_tag>::type
314  finiteElements_by_id;
315  const finiteElements_by_id &BitFEId_set =
317  finiteElements_by_id::iterator miit = BitFEId_set.begin();
318  for (; miit != BitFEId_set.end(); miit++) {
319  std::ostringstream ss;
320  ss << *miit << std::endl;
321  PetscSynchronizedPrintf(cOmm, ss.str().c_str());
322  }
323  PetscSynchronizedFlush(cOmm, PETSC_STDOUT);
325 }
326 
328  const EntityHandle meshset, const EntityType type, const std::string &name,
329  const bool recursive) {
330  *buildMoFEM &= 1 << 0;
331  EntityHandle idm = no_handle;
333 
335  Range ents;
336  CHKERR get_moab().get_entities_by_type(meshset, type, ents, recursive);
337  CHKERR getInterface<BitRefManager>()->setElementsBitRefLevel(ents);
338  CHKERR get_moab().add_entities(idm, ents);
339 
341 }
342 
345  const int dim, const std::string &name,
346  const bool recursive) {
347  EntityHandle idm = no_handle;
348  *buildMoFEM &= 1 << 0;
351  Range ents;
352  CHKERR get_moab().get_entities_by_dimension(meshset, dim, ents, recursive);
353  CHKERR getInterface<BitRefManager>()->setElementsBitRefLevel(ents);
354  CHKERR get_moab().add_entities(idm, ents);
356 }
357 
359  const Range &ents, const EntityType type, const std::string &name) {
360  EntityHandle idm = no_handle;
361  *buildMoFEM &= 1 << 0;
364  CHKERR getInterface<BitRefManager>()->setElementsBitRefLevel(
365  ents.subset_by_type(type));
366  CHKERR get_moab().add_entities(idm, ents.subset_by_type(type));
368 } // namespace MoFEM
369 
371 Core::add_ents_to_finite_element_by_dim(const Range &ents, const int dim,
372  const std::string &name) {
373  EntityHandle idm = no_handle;
374  *buildMoFEM &= 1 << 0;
377  CHKERR getInterface<BitRefManager>()->setElementsBitRefLevel(
378  ents.subset_by_dimension(dim));
379  CHKERR get_moab().add_entities(idm, ents.subset_by_dimension(dim));
381 }
382 
384  const EntityHandle meshset, const std::string &name, const bool recursive) {
386  CHKERR add_ents_to_finite_element_by_type(meshset, MBEDGE, name, recursive);
388 }
391  const std::string &name) {
393  CHKERR add_ents_to_finite_element_by_type(edges, MBEDGE, name);
395 }
398  const std::string &name) {
400  CHKERR add_ents_to_finite_element_by_type(vert, MBVERTEX, name);
402 }
405  const std::string &name) {
407  CHKERR add_ents_to_finite_element_by_type(tris, MBTRI, name);
409 }
411  const EntityHandle meshset, const std::string &name, const bool recursive) {
413  CHKERR add_ents_to_finite_element_by_type(meshset, MBTRI, name, recursive);
415 }
418  const std::string &name) {
420  CHKERR add_ents_to_finite_element_by_type(tets, MBTET, name);
422 }
424  const EntityHandle meshset, const std::string &name, const bool recursive) {
426  CHKERR add_ents_to_finite_element_by_type(meshset, MBTET, name, recursive);
428 }
431  const std::string &name) {
433  CHKERR add_ents_to_finite_element_by_type(prims, MBPRISM, name);
435 }
437  const EntityHandle meshset, const std::string &name, const bool recursive) {
439  CHKERR add_ents_to_finite_element_by_type(meshset, MBPRISM, name, recursive);
441 }
442 
445  const std::string &name,
446  EntityType type, int verb) {
449  type, verb);
450 
452 }
453 
455  const BitRefLevel &bit, const BitRefLevel &mask, const std::string &name,
456  EntityType type, int verb) {
458  CHKERR add_ents_to_finite_element_by_bit_ref(bit, mask, name, type, verb);
459 
461 }
462 
464  const BitRefLevel &bit, const BitRefLevel &mask, const std::string &name,
465  EntityType type, int verb) {
467 
468  if (verb == -1)
469  verb = verbose;
470  *buildMoFEM &= 1 << 0;
471  const BitFEId id = getBitFEId(name);
473  typedef RefElement_multiIndex::index<EntType_mi_tag>::type refMoabFE_by_type;
474  refMoabFE_by_type &ref_MoFEMFiniteElement =
476  refMoabFE_by_type::iterator miit = ref_MoFEMFiniteElement.lower_bound(type);
477  refMoabFE_by_type::iterator hi_miit =
478  ref_MoFEMFiniteElement.upper_bound(type);
479  if (verb > 1) {
480  PetscSynchronizedPrintf(cOmm, "nb. ref elements in database %d\n",
481  std::distance(miit, hi_miit));
482  }
483  int nb_add_FEs = 0;
484  for (; miit != hi_miit; miit++) {
485  BitRefLevel bit2 = miit->get()->getBitRefLevel();
486  if ((bit2 & mask) != bit2)
487  continue;
488  if ((bit2 & bit).any()) {
489  EntityHandle ent = miit->get()->getRefEnt();
490  CHKERR get_moab().add_entities(idm, &ent, 1);
491  nb_add_FEs++;
492  }
493  }
494  if (verb > 0) {
495  std::ostringstream ss;
496  ss << "Add Nb. FEs " << nb_add_FEs << " form BitRef " << bit << std::endl;
497  PetscSynchronizedPrintf(cOmm, "%s", ss.str().c_str());
498  PetscSynchronizedFlush(cOmm, PETSC_STDOUT);
499  }
500 
502 }
503 
505  const EntityHandle meshset, const std::string &name, const bool recursive) {
507  *buildMoFEM &= 1 << 0;
508  const BitFEId id = getBitFEId(name);
510  if (recursive == false) {
511  CHKERR get_moab().add_entities(idm, &meshset, 1);
512  } else {
513  Range meshsets;
514  CHKERR get_moab().get_entities_by_type(meshset, MBENTITYSET, meshsets,
515  false);
516  CHKERR get_moab().add_entities(idm, meshsets);
517  }
519 }
520 
521 template <int I> struct BuildFiniteElements {
522 
523  template <typename T1, typename T2>
524  static inline void addToData(T1 &range_dit, T2 &fe_vec) {
525  static_assert(I == DATA, "t should be set to DATA");
526 
527  for (auto dit = range_dit.first; dit != range_dit.second; ++dit) {
528  const EntityHandle dof_ent = dit->get()->getEnt();
529  // Fill array
530  for (auto fe_it : fe_vec) {
531  if (auto fe_ptr = fe_it.lock()) {
532  // Add FEDofEntity, first create dofs, one by one, note that memory
533  // is already reserved. Then create shared pointers and finally add
534  // th_FEName to element multi-index
535  // There are data dofs on this element
536  auto &side_number_ptr = fe_ptr->getSideNumberPtr(dof_ent);
537  fe_ptr->getDofsSequence().lock()->emplace_back(side_number_ptr, *dit);
538  }
539  }
540  }
541  }
542 
543  template <typename T> static inline void emplaceHint(T &fe_vec) {
544  static_assert(I == DATA, "t should be set to DATA");
545 
546  // Add to data in FE
547  for (auto fe_it : fe_vec) {
548  if (auto fe_ptr = fe_it.lock()) {
549  // It is a but unsafe, since if one mess up something in
550  // buildFiniteElements, weak_ptr will not give pointer
551  auto data_dofs_array_vec = fe_ptr->getDofsSequence().lock();
552  // Create shared pointers vector
553  auto hint = fe_ptr->data_dofs->end();
554  for (auto &vit : *data_dofs_array_vec)
555  hint =
556  fe_ptr->data_dofs->emplace_hint(hint, data_dofs_array_vec, &vit);
557  }
558  }
559  }
560 };
561 
563 Core::buildFiniteElements(const boost::shared_ptr<FiniteElement> &fe,
564  const Range *ents_ptr, int verb) {
566  if (verb == DEFAULT_VERBOSITY)
567  verb = verbose;
568 
569  auto &fields_by_id = fIelds.get<BitFieldId_mi_tag>();
570 
571  // Get id of mofem fields for row, col and data
572  enum IntLoop { ROW = 0, COL, DATA, LAST };
573  std::array<BitFieldId, LAST> fe_fields = {fe.get()->getBitFieldIdRow(),
574  fe.get()->getBitFieldIdCol(),
575  fe.get()->getBitFieldIdData()};
576 
577  // Get finite element meshset
578  EntityHandle meshset = get_finite_element_meshset(fe.get()->getId());
579 
580  // Get entities from finite element meshset // if meshset
581  Range fe_ents;
582  CHKERR get_moab().get_entities_by_handle(meshset, fe_ents, false);
583 
584  if (ents_ptr)
585  fe_ents = intersect(fe_ents, *ents_ptr);
586 
587  // Map entity uid to pointers
588  typedef std::vector<boost::weak_ptr<EntFiniteElement>> VecOfWeakFEPtrs;
589  typedef std::map<const UId *, VecOfWeakFEPtrs> MapEntUIdAndVecOfWeakFEPtrs;
590  MapEntUIdAndVecOfWeakFEPtrs ent_uid_and_fe_vec;
591  std::map<EntityHandle, boost::shared_ptr<std::vector<FEDofEntity>>>
592  data_dofs_array;
593  VecOfWeakFEPtrs processed_fes;
594  processed_fes.reserve(fe_ents.size());
595 
596  int last_row_field_ents_view_size = 0;
597  int last_col_field_ents_view_size = 0;
598 
599  // View of field entities on element
600  FieldEntity_vector_view data_field_ents_view;
601 
602  // Loop meshset finite element ents and add finite elements
603  for (Range::const_pair_iterator peit = fe_ents.const_pair_begin();
604  peit != fe_ents.const_pair_end(); peit++) {
605 
606  EntityHandle first = peit->first;
607  EntityHandle second = peit->second;
608 
609  // Find range of ref entities that is sequence
610  // note: iterator is a wrapper
611  // check if is in refinedFiniteElements database
612  auto ref_fe_miit =
613  refinedFiniteElements.get<Ent_mi_tag>().lower_bound(first);
614  if (ref_fe_miit == refinedFiniteElements.get<Ent_mi_tag>().end()) {
615  std::ostringstream ss;
616  ss << "refinedFiniteElements not in database ent = " << first;
617  ss << " type " << get_moab().type_from_handle(first);
618  ss << " " << *fe;
619  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, ss.str().c_str());
620  }
621  auto hi_ref_fe_miit =
622  refinedFiniteElements.get<Ent_mi_tag>().upper_bound(second);
623 
624  EntFiniteElement_multiIndex::iterator hint_p = entsFiniteElements.end();
625  for (; ref_fe_miit != hi_ref_fe_miit; ref_fe_miit++) {
626 
627  // Add finite element to database
628  hint_p = entsFiniteElements.emplace_hint(
629  hint_p, boost::make_shared<EntFiniteElement>(*ref_fe_miit, fe));
630  processed_fes.emplace_back(*hint_p);
631  auto fe_raw_ptr = hint_p->get();
632 
633  // Allocate space for etities view
634  data_field_ents_view.clear();
635  fe_raw_ptr->row_field_ents_view->reserve(last_row_field_ents_view_size);
636  // Create shared pointer for entities view
637  if (fe_fields[ROW] == fe_fields[COL]) {
638  fe_raw_ptr->col_field_ents_view = fe_raw_ptr->row_field_ents_view;
639  } else {
640  // row and columns are diffent
641  if (fe_raw_ptr->col_field_ents_view ==
642  fe_raw_ptr->row_field_ents_view)
643  fe_raw_ptr->col_field_ents_view =
644  boost::make_shared<FieldEntity_vector_view>();
645  fe_raw_ptr->col_field_ents_view->reserve(last_col_field_ents_view_size);
646  }
647 
648  int nb_dofs_on_data = 0;
649 
650  // Iterate over all field and check which one is on the element
651  for (unsigned int ii = 0; ii != BitFieldId().size(); ++ii) {
652 
653  // Common field id for ROW, COL and DATA
654  BitFieldId id_common = 0;
655  // Check if the field (ii) is added to finite element
656  for (int ss = 0; ss < LAST; ss++) {
657  id_common |= fe_fields[ss] & BitFieldId().set(ii);
658  }
659  if (id_common.none())
660  continue;
661 
662  // Find in database data associated with the field (ii)
663  const BitFieldId field_id = BitFieldId().set(ii);
664  auto miit = fields_by_id.find(field_id);
665  if (miit == fields_by_id.end()) {
666  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
667  "Data inconsistency");
668  }
669 
670 
671  // Loop over adjacencies of element and find field entities on those
672  // adjacencies, that create hash map map_uid_fe which is used later
673  const std::string field_name = miit->get()->getName();
674  const bool add_to_data = (field_id & fe_fields[DATA]).any();
675  const bool add_to_row = (field_id & fe_fields[ROW]).any();
676  const bool add_to_col = (field_id & fe_fields[COL]).any();
677 
678  // Entities adjacent to entities
679  Range adj_ents;
680 
681  // Resolve entities on element, those entities are used to build tag
682  // with dof uids on finite element tag
683  CHKERR fe_raw_ptr->getElementAdjacency(*miit, adj_ents);
684 
685  for (Range::pair_iterator p_eit = adj_ents.pair_begin();
686  p_eit != adj_ents.pair_end(); ++p_eit) {
687 
688  const EntityHandle first = p_eit->first;
689  const EntityHandle second = p_eit->second;
690 
691  typedef FieldEntity_multiIndex::index<
692  Composite_Name_And_Ent_mi_tag>::type FieldEntityByComposite;
693  auto &field_ents_by_name_and_ent =
695  FieldEntityByComposite::iterator meit;
696 
697  // If one entity in the pair search for one, otherwise search for
698  // range
699  if (first == second)
700  meit = field_ents_by_name_and_ent.find(
701  boost::make_tuple(field_name, first));
702  else
703  meit = field_ents_by_name_and_ent.lower_bound(
704  boost::make_tuple(field_name, first));
705 
706  if (meit != field_ents_by_name_and_ent.end()) {
707 
708  decltype(meit) hi_meit;
709 
710  if (first == second) {
711  hi_meit = meit;
712  ++hi_meit;
713  } else
714  hi_meit = field_ents_by_name_and_ent.upper_bound(
715  boost::make_tuple(field_name, second));
716 
717  // Add to view and create list of finite elements with this dof UId
718  for (; meit != hi_meit; ++meit) {
719  // Add entity to map with key entity uids pointers and data
720  // finite elements weak ptrs. I using pointers to uids instead
721  // uids because this is faster.
722  const UId *uid_ptr = &(meit->get()->getGlobalUniqueId());
723  auto &fe_vec = ent_uid_and_fe_vec[uid_ptr];
724  // get number of dofs on entities to pre-allocate memory for
725  // element
726  const int nb_dofs_on_ent = meit->get()->getNbDofsOnEnt();
727  if (add_to_data) {
728  nb_dofs_on_data += nb_dofs_on_ent;
729  data_field_ents_view.emplace_back(*meit);
730  }
731  if (add_to_row) {
732  fe_raw_ptr->row_field_ents_view->emplace_back(*meit);
733  }
734  if (add_to_col) {
735  if (fe_raw_ptr->col_field_ents_view !=
736  fe_raw_ptr->row_field_ents_view)
737  fe_raw_ptr->col_field_ents_view->emplace_back(*meit);
738  }
739  // add finite element to processed list
740  fe_vec.emplace_back(*hint_p);
741  }
742  }
743  }
744  }
745 
746  // Sort field ents by uid
747  auto uid_comp = [](const auto &a, const auto &b) {
748  return a.lock()->getGlobalUniqueId() < b.lock()->getGlobalUniqueId();
749  };
750 
751  // Sort all views
752 
753  // Data
754  sort(data_field_ents_view.begin(), data_field_ents_view.end(), uid_comp);
755  for (auto e : data_field_ents_view)
756  fe_raw_ptr->data_field_ents_view->emplace_back(e);
757 
758  // Row
759  sort(fe_raw_ptr->row_field_ents_view->begin(),
760  fe_raw_ptr->row_field_ents_view->end(), uid_comp);
761  last_row_field_ents_view_size = fe_raw_ptr->row_field_ents_view->size();
762 
763  // Column
764  if (fe_raw_ptr->col_field_ents_view != fe_raw_ptr->row_field_ents_view) {
765  sort(fe_raw_ptr->col_field_ents_view->begin(),
766  fe_raw_ptr->col_field_ents_view->end(), uid_comp);
767  last_col_field_ents_view_size = fe_raw_ptr->col_field_ents_view->size();
768  }
769 
770  // Clear finite element data structures
771  fe_raw_ptr->data_dofs->clear();
772 
773  // Reserve memory for data FE Dofs
774  auto data_dofs_array_vec = boost::make_shared<std::vector<FEDofEntity>>();
775  data_dofs_array[fe_raw_ptr->getEnt()] = data_dofs_array_vec;
776  data_dofs_array_vec->reserve(nb_dofs_on_data);
777 
778  fe_raw_ptr->getDofsSequence() = data_dofs_array_vec;
779 
780 
781  }
782  }
783 
784  auto &dofs_by_ent_uid = dofsField.get<Unique_Ent_mi_tag>();
785 
786  // Loop over hash map, which has all entities on given elemnts
787  boost::shared_ptr<SideNumber> side_number_ptr;
788  for (auto &mit : ent_uid_and_fe_vec) {
789  auto range_dit = dofs_by_ent_uid.equal_range(*mit.first);
790  if (range_dit.first != range_dit.second) {
791  const BitFieldId field_id = range_dit.first->get()->getId();
792  if ((field_id & fe_fields[DATA]).any())
793  BuildFiniteElements<DATA>::addToData(range_dit, mit.second);
794  }
795  }
796 
798 
800 }
801 
804  if (verb == DEFAULT_VERBOSITY)
805  verb = verbose;
806 
807  // loop Finite Elements
808  for (auto &fe : finiteElements) {
809  if (verb >= VERBOSE)
810  PetscPrintf(cOmm, "Build Finite Elements %s\n", fe->getName().c_str());
811  CHKERR buildFiniteElements(fe, NULL, verb);
812  }
813 
814  if (verb >= VERBOSE) {
815  PetscSynchronizedPrintf(cOmm, "Nb. FEs %u\n", entsFiniteElements.size());
816  PetscSynchronizedFlush(cOmm, PETSC_STDOUT);
817  auto &finite_elements_by_id = entsFiniteElements.get<BitFEId_mi_tag>();
818  for (auto &fe : finiteElements) {
819  auto miit = finite_elements_by_id.lower_bound(fe->getId());
820  auto hi_miit = finite_elements_by_id.upper_bound(fe->getId());
821  int count = std::distance(miit, hi_miit);
822  std::ostringstream ss;
823  ss << *fe << " Nb. FEs " << count << std::endl;
824  PetscSynchronizedPrintf(cOmm, ss.str().c_str());
825  PetscSynchronizedFlush(cOmm, PETSC_STDOUT);
826  }
827  }
828 
829  *buildMoFEM |= 1 << 1;
831 }
832 
835  SETERRQ(cOmm, MOFEM_NOT_IMPLEMENTED, "Not yet implemented");
837 }
838 
840  const Range *const ents_ptr,
841  int verb) {
843  if (verb == -1)
844  verb = verbose;
845 
846  auto fe_miit = finiteElements.get<FiniteElement_name_mi_tag>().find(fe_name);
847  if (fe_miit == finiteElements.get<FiniteElement_name_mi_tag>().end())
848  SETERRQ1(cOmm, MOFEM_NOT_FOUND, "Finite element <%s> not found",
849  fe_name.c_str());
850 
851  if (verb >= VERBOSE)
852  PetscPrintf(cOmm, "Build Finite Elements %s\n", fe_name.c_str());
853  CHKERR buildFiniteElements(*fe_miit, ents_ptr, verb);
854 
855  if (verb >= VERBOSE) {
856  auto &finite_elements_by_id = entsFiniteElements.get<BitFEId_mi_tag>();
857  auto miit = finite_elements_by_id.lower_bound((*fe_miit)->getId());
858  auto hi_miit = finite_elements_by_id.upper_bound((*fe_miit)->getId());
859  int count = std::distance(miit, hi_miit);
860  std::ostringstream ss;
861  ss << *(*fe_miit) << " Nb. FEs " << count << std::endl;
862  PetscSynchronizedPrintf(cOmm, ss.str().c_str());
863  PetscSynchronizedFlush(cOmm, PETSC_STDOUT);
864  }
865 
866  *buildMoFEM |= 1 << 1;
868 }
869 
870 MoFEMErrorCode Core::build_adjacencies(const Range &ents, int verb) {
872  if (verb == DEFAULT_VERBOSITY)
873  verb = verbose;
874  if (!((*buildMoFEM) & BUILD_FIELD))
875  SETERRQ(cOmm, MOFEM_NOT_FOUND, "field not build");
876  if (!((*buildMoFEM) & BUILD_FE))
877  SETERRQ(cOmm, MOFEM_NOT_FOUND, "fe not build");
878  for (Range::const_pair_iterator peit = ents.pair_begin();
879  peit != ents.pair_end(); ++peit) {
880  EntFiniteElement_multiIndex::index<Ent_mi_tag>::type::iterator fit, hi_fit;
881  fit = entsFiniteElements.get<Ent_mi_tag>().lower_bound(peit->first);
882  hi_fit = entsFiniteElements.get<Ent_mi_tag>().upper_bound(peit->second);
883  for (; fit != hi_fit; ++fit) {
884  if ((*fit)->getBitFieldIdRow().none() &&
885  (*fit)->getBitFieldIdCol().none() &&
886  (*fit)->getBitFieldIdData().none())
887  continue;
888  int by = BYROW;
889  if ((*fit)->getBitFieldIdRow() != (*fit)->getBitFieldIdCol())
890  by |= BYCOL;
891  if ((*fit)->getBitFieldIdRow() != (*fit)->getBitFieldIdData())
892  by |= BYDATA;
894  auto hint = entFEAdjacencies.end();
895  for (auto e : *(*fit)->row_field_ents_view) {
896  hint = entFEAdjacencies.emplace_hint(hint, e.lock(), *fit);
897  bool success = entFEAdjacencies.modify(hint, modify_row);
898  if (!success)
899  SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
900  "modification unsuccessful");
901  }
902  if ((*fit)->getBitFieldIdRow() != (*fit)->getBitFieldIdCol()) {
903  int by = BYCOL;
904  if ((*fit)->getBitFieldIdCol() != (*fit)->getBitFieldIdData())
905  by |= BYDATA;
907  auto hint = entFEAdjacencies.end();
908  for (auto e : *(*fit)->col_field_ents_view) {
909  hint = entFEAdjacencies.emplace_hint(hint, e.lock(), *fit);
910  bool success = entFEAdjacencies.modify(hint, modify_col);
911  if (!success)
912  SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
913  "modification unsuccessful");
914  }
915  }
916  if ((*fit)->getBitFieldIdRow() != (*fit)->getBitFieldIdData() ||
917  (*fit)->getBitFieldIdCol() != (*fit)->getBitFieldIdData()) {
919  BYDATA);
920  auto hint = entFEAdjacencies.end();
921  for (auto &e : *(*fit)->data_field_ents_view) {
922  hint = entFEAdjacencies.emplace_hint(hint, e, *fit);
923  bool success = entFEAdjacencies.modify(hint, modify_data);
924  if (!success)
925  SETERRQ(PETSC_COMM_SELF, MOFEM_OPERATION_UNSUCCESSFUL,
926  "modification unsuccessful");
927  }
928  }
929  }
930  }
931  if (verb >= VERY_NOISY) {
933  }
934  if (verb >= VERBOSE) {
935  PetscSynchronizedPrintf(cOmm, "Nb. entFEAdjacencies %u\n",
936  entFEAdjacencies.size());
937  PetscSynchronizedFlush(cOmm, PETSC_STDOUT);
938  }
939  *buildMoFEM |= 1 << 2;
941 }
942 
944  const BitRefLevel &mask, int verb) {
946  if (verb == -1)
947  verb = verbose;
948  Range ents;
949  CHKERR BitRefManager(*this).getEntitiesByRefLevel(bit, mask, ents);
950 
951  CHKERR build_adjacencies(ents, verb);
952 
954 }
957  if (verb == -1)
958  verb = verbose;
959  CHKERR build_adjacencies(bit, BitRefLevel().set(), verb);
960 
962 }
963 
964 EntFiniteElementByName::iterator
965 Core::get_fe_by_name_begin(const std::string &fe_name) const {
966  return entsFiniteElements.get<FiniteElement_name_mi_tag>().lower_bound(
967  fe_name);
968 }
969 EntFiniteElementByName::iterator
970 Core::get_fe_by_name_end(const std::string &fe_name) const {
971  return entsFiniteElements.get<FiniteElement_name_mi_tag>().upper_bound(
972  fe_name);
973 }
974 
976  const std::string &name) const {
978  FiniteElement_multiIndex::index<FiniteElement_name_mi_tag>::type::iterator it;
979  it = finiteElements.get<FiniteElement_name_mi_tag>().find(name);
980  if (it == finiteElements.get<FiniteElement_name_mi_tag>().end()) {
981  SETERRQ1(cOmm, 1, "finite element not found < %s >", name.c_str());
982  }
983  EntityHandle meshset = (*it)->getMeshset();
984 
985  int num_entities;
986  CHKERR get_moab().get_number_entities_by_handle(meshset, num_entities);
987 
989  (*it)->getName().c_str()) != (unsigned int)num_entities) {
990  SETERRQ1(cOmm, 1,
991  "not equal number of entities in meshset and finite elements "
992  "multiindex < %s >",
993  (*it)->getName().c_str());
994  }
996 }
997 
1000  FiniteElement_multiIndex::index<FiniteElement_name_mi_tag>::type::iterator it;
1001  it = finiteElements.get<FiniteElement_name_mi_tag>().begin();
1002  for (; it != finiteElements.get<FiniteElement_name_mi_tag>().end(); it++) {
1003  EntityHandle meshset = (*it)->getMeshset();
1004 
1005  int num_entities;
1006  CHKERR get_moab().get_number_entities_by_handle(meshset, num_entities);
1007 
1009  (*it)->getName().c_str()) != (unsigned int)num_entities) {
1010  SETERRQ1(cOmm, 1,
1011  "not equal number of entities in meshset and finite elements "
1012  "multiindex < %s >",
1013  (*it)->getName().c_str());
1014  }
1015  }
1017 }
1018 } // namespace MoFEM
DofEntity_multiIndex dofsField
dofs on fields
Definition: Core.hpp:249
MoFEMErrorCode modify_finite_element_add_field_data(const std::string &fe_name, const std::string &name_filed)
set finite element field data
Definition: FECore.cpp:115
EntityHandle get_finite_element_meshset(const BitFEId id) const
Definition: FECore.cpp:262
MoFEMErrorCode check_number_of_ents_in_ents_finite_element() const
check data consistency in entsFiniteElements
Definition: FECore.cpp:998
MoFEMErrorCode add_ents_to_finite_element_by_MESHSET(const EntityHandle meshset, const std::string &name, const bool recursive=false)
add MESHSET element to finite element database given by name
Definition: FECore.cpp:504
MPI_Comm cOmm
MoFEM communicator.
Definition: Core.hpp:846
MoFEMErrorCode add_ents_to_finite_element_by_dim(const EntityHandle meshset, const int dim, const std::string &name, const bool recursive=true)
add entities to finite element
Definition: FECore.cpp:344
FieldEntity_multiIndex entsFields
entities on fields
Definition: Core.hpp:248
multi_index_container< boost::shared_ptr< FiniteElement >, indexed_by< hashed_unique< tag< FiniteElement_Meshset_mi_tag >, member< FiniteElement, EntityHandle, &FiniteElement::meshset > >, hashed_unique< tag< BitFEId_mi_tag >, const_mem_fun< FiniteElement, BitFEId, &FiniteElement::getId >, HashBit< BitFEId >, EqBit< BitFEId > >, ordered_unique< tag< FiniteElement_name_mi_tag >, const_mem_fun< FiniteElement, boost::string_ref, &FiniteElement::getNameRef > > > > FiniteElement_multiIndex
MultiIndex for entities for FiniteElement.
DEPRECATED MoFEMErrorCode add_ents_to_finite_element_by_VERTICEs(const Range &vert, const std::string &name)
add VERTICES entities from range to finite element database given by name
Definition: FECore.cpp:397
DEPRECATED MoFEMErrorCode add_ents_to_finite_element_by_EDGEs(const Range &vert, const std::string &name)
add EDGES entities from range to finite element database given by name
Definition: FECore.cpp:390
moab::Interface & get_moab()
Definition: Core.hpp:266
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:501
std::vector< boost::weak_ptr< FieldEntity > > FieldEntity_vector_view
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:477
MoFEMErrorCode get_finite_element_entities_by_dimension(const std::string name, int dim, Range &ents) const
get entities in the finite element by dimension
Definition: FECore.cpp:277
MoFEMErrorCode build_adjacencies(const Range &ents, int verb=DEFAULT_VERBOSITY)
build adjacencies
Definition: FECore.cpp:870
const EntityHandle no_handle
No entity handle is indicated by zero handle, i.e. root meshset.
Definition: Common.hpp:27
MoFEMErrorCode list_finite_elements() const
list finite elements in database
Definition: FECore.cpp:311
MoFEMErrorCode build_finite_elements(int verb=DEFAULT_VERBOSITY)
Build finite elementsBuild finite element data structures. Have to be run before problem and adjacenc...
Definition: FECore.cpp:802
#define THROW_MESSAGE(a)
Throw MoFEM exception.
Definition: definitions.h:620
Tag th_FEName
Definition: Core.hpp:206
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:508
std::reference_wrapper< moab::Interface > moab
moab database
Definition: Core.hpp:265
MoFEMErrorCode add_ents_to_finite_element_by_bit_ref(const BitRefLevel &bit, const BitRefLevel &mask, const std::string &name, EntityType type, int verb=DEFAULT_VERBOSITY)
add TET entities from given refinement level to finite element database given by name
Definition: FECore.cpp:463
MoFEMErrorCode modify_finite_element_off_field_data(const std::string &fe_name, const std::string &name_filed)
unset finite element field data
Definition: FECore.cpp:176
implementation of Data Operators for Forces and Sources
Definition: Common.hpp:21
MoFEMErrorCode get_finite_element_entities_by_type(const std::string name, EntityType type, Range &ents) const
get entities in the finite element by type
Definition: FECore.cpp:287
DEPRECATED MoFEMErrorCode add_ents_to_finite_element_by_PRISMs(const Range &prims, const BitFEId id)
DEPRECATED MoFEMErrorCode add_ents_to_finite_element_by_TRIs(const Range &tris, const std::string &name)
add TRI entities from range to finite element database given by name
Definition: FECore.cpp:404
BitFEId getBitFEId(const std::string &name) const
Get field Id.
Definition: FECore.cpp:240
std::bitset< BITFEID_SIZE > BitFEId
Finite element Id.
Definition: Types.hpp:54
std::string getBitFEIdName(const BitFEId id) const
Get field name.
Definition: FECore.cpp:253
EntFiniteElementByName::iterator get_fe_by_name_end(const std::string &fe_name) const
get end iterator of finite elements of given name (instead you can use IT_GET_FES_BY_NAME_FOR_LOOP(MF...
Definition: FECore.cpp:970
static void emplaceHint(T &fe_vec)
Definition: FECore.cpp:543
MoFEMErrorCode modify_finite_element_off_field_col(const std::string &fe_name, const std::string &name_col)
unset field col which finite element use
Definition: FECore.cpp:217
MoFEMErrorCode add_finite_element(const std::string &fe_name, enum MoFEMTypes bh=MF_EXCL, int verb=DEFAULT_VERBOSITY)
add finite element
Definition: FECore.cpp:45
BitFEId getFEShift()
Return unique finite element Id.
Definition: Core.cpp:237
bool check_finite_element(const std::string &name) const
Check if finite element is in database.
Definition: FECore.cpp:35
Finite element definition.
MoFEMErrorCode modify_finite_element_off_field_row(const std::string &fe_name, const std::string &name_row)
unset field row which finite element use
Definition: FECore.cpp:196
int * buildMoFEM
keeps flags/semaphores for different stages
Definition: Core.hpp:896
boost::function< MoFEMErrorCode(Interface &moab, const Field &field_ptr, const EntFiniteElement &fe_ptr, Range &adjacency)> ElementAdjacencyFunct
user adjacency function
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
Definition: Exceptions.hpp:66
FieldEntityEntFiniteElementAdjacencyMap_multiIndex entFEAdjacencies
adjacencies of elements to dofs
Definition: Core.hpp:255
Managing BitRefLevels.
RefElement_multiIndex refinedFiniteElements
refined elements
Definition: Core.hpp:245
FiniteElement_multiIndex finiteElements
finite elements
Definition: Core.hpp:251
std::bitset< BITFIELDID_SIZE > BitFieldId
Field Id.
Definition: Types.hpp:53
MoFEMErrorCode modify_finite_element_add_field_col(const std::string &fe_name, const std::string &name_col)
set field col which finite element use
Definition: FECore.cpp:156
#define CHKERR
Inline error check.
Definition: definitions.h:596
multi_index_container< boost::shared_ptr< EntFiniteElement >, indexed_by< ordered_unique< tag< Unique_mi_tag >, member< EntFiniteElement, UId, &EntFiniteElement::globalUId > >, ordered_non_unique< tag< Ent_mi_tag >, const_mem_fun< EntFiniteElement, EntityHandle, &EntFiniteElement::getEnt > >, ordered_non_unique< tag< FiniteElement_name_mi_tag >, const_mem_fun< EntFiniteElement::interface_type_FiniteElement, boost::string_ref, &EntFiniteElement::getNameRef > >, ordered_non_unique< tag< BitFEId_mi_tag >, const_mem_fun< EntFiniteElement::interface_type_FiniteElement, BitFEId, &EntFiniteElement::getId >, LtBit< BitFEId > >, ordered_non_unique< tag< EntType_mi_tag >, const_mem_fun< EntFiniteElement::interface_type_RefEntity, EntityType, &EntFiniteElement::getEntType > >, ordered_non_unique< tag< Composite_Name_And_Ent_mi_tag >, composite_key< EntFiniteElement, const_mem_fun< EntFiniteElement::interface_type_FiniteElement, boost::string_ref, &EntFiniteElement::getNameRef >, const_mem_fun< EntFiniteElement, EntityHandle, &EntFiniteElement::getEnt > > > > > EntFiniteElement_multiIndex
MultiIndex container for EntFiniteElement.
MoFEMErrorCode add_ents_to_finite_element_by_type(const EntityHandle meshset, const EntityType type, const std::string &name, const bool recursive=true)
add entities to finite element
Definition: FECore.cpp:327
Field_multiIndex fIelds
fields
Definition: Core.hpp:247
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition: Types.hpp:51
MoFEMErrorCode getEntitiesByRefLevel(const BitRefLevel bit, const BitRefLevel mask, const EntityHandle meshset, const int verb=QUIET) const
add all ents from ref level given by bit to meshset
BitFieldId getBitFieldId(const std::string &name) const
Definition: FieldCore.cpp:21
static void addToData(T1 &range_dit, T2 &fe_vec)
Definition: FECore.cpp:524
MoFEMErrorCode modify_finite_element_add_field_row(const std::string &fe_name, const std::string &name_row)
set field row which finite element use
Definition: FECore.cpp:135
DEPRECATED MoFEMErrorCode add_ents_to_finite_element_EntType_by_bit_ref(const BitRefLevel &bit, const std::string &name, EntityType type, int verb=DEFAULT_VERBOSITY)
add TET elements from given refinement level to finite element database given by name
Definition: FECore.cpp:444
MoFEMErrorCode modify_finite_element_adjacency_table(const std::string &fe_name, const EntityType type, ElementAdjacencyFunct function)
modify finite element table, only for advanced user
Definition: FECore.cpp:94
int verbose
Verbosity level.
Definition: Core.hpp:885
Tag th_FEId
Definition: Core.hpp:206
MoFEMErrorCode get_finite_elements(const FiniteElement_multiIndex **fe_ptr) const
Get finite elements multi-index.
Definition: FECore.cpp:22
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:407
MoFEMErrorCode buildFiniteElements(const boost::shared_ptr< FiniteElement > &fe, const Range *ents_ptr=NULL, int verb=DEFAULT_VERBOSITY)
Definition: FECore.cpp:563
MoFEMErrorCode get_ents_finite_elements(const EntFiniteElement_multiIndex **fe_ent_ptr) const
Get entities finite elements multi-index.
Definition: FECore.cpp:28
EntFiniteElement_multiIndex entsFiniteElements
finite element entities
Definition: Core.hpp:252
MoFEMErrorCode list_adjacencies() const
list adjacencies
Definition: FieldCore.cpp:1163
uint128_t UId
Unique Id.
Definition: Types.hpp:41
MoFEMErrorCode get_finite_element_entities_by_handle(const std::string name, Range &ents) const
get entities in the finite element by handle
Definition: FECore.cpp:300
MoFEMTypes
Those types control how functions respond on arguments, f.e. error handling.
Definition: definitions.h:183
EntFiniteElementByName::iterator get_fe_by_name_begin(const std::string &fe_name) const
get begin iterator of finite elements of given name (instead you can use IT_GET_FES_BY_NAME_FOR_LOOP(...
Definition: FECore.cpp:965
DEPRECATED MoFEMErrorCode add_ents_to_finite_element_by_TETs(const Range &tets, const std::string &name)
add TET entities from range to finite element database given by name
Definition: FECore.cpp:417