v0.15.0
Loading...
Searching...
No Matches
ForcesAndSourcesCore.cpp
Go to the documentation of this file.
1/** \file ForcesAndSourcesCore.cpp
2
3\brief Implementation of Elements on Entities for Forces and Sources
4*/
5
6#ifdef __cplusplus
7extern "C" {
8#endif
9#include <cblas.h>
10#include <lapack_wrap.h>
11// #include <gm_rule.h>
12#ifdef __cplusplus
13}
14#endif
15
16namespace MoFEM {
17
18static auto cmp_uid_lo(const boost::weak_ptr<FieldEntity> &a, const UId &b) {
19 if (auto a_ptr = a.lock()) {
20 if (a_ptr->getLocalUniqueId() < b)
21 return true;
22 else
23 return false;
24 } else {
25 return false;
26 }
27}
28
29static auto cmp_uid_hi(const UId &b, const boost::weak_ptr<FieldEntity> &a) {
30 if (auto a_ptr = a.lock()) {
31 if (b < a_ptr->getLocalUniqueId())
32 return true;
33 else
34 return false;
35 } else {
36 return true;
37 }
38}
39
41 :
42
43 mField(m_field), getRuleHook(0), setRuleHook(0),
44 dataOnElement{
45
46 boost::make_shared<EntitiesFieldData>(MBENTITYSET), // NOSPACE,
47 boost::make_shared<EntitiesFieldData>(MBENTITYSET), // NOFIELD
48 boost::make_shared<EntitiesFieldData>(MBENTITYSET), // H1
49 boost::make_shared<EntitiesFieldData>(MBENTITYSET), // HCURL
50 boost::make_shared<EntitiesFieldData>(MBENTITYSET), // HDIV
51 boost::make_shared<EntitiesFieldData>(MBENTITYSET) // L2
52
53 },
54 derivedDataOnElement{
55
56 nullptr,
57 boost::make_shared<DerivedEntitiesFieldData>(
58 dataOnElement[NOFIELD]), // NOFIELD
59 boost::make_shared<DerivedEntitiesFieldData>(dataOnElement[H1]), // H1
60 boost::make_shared<DerivedEntitiesFieldData>(
61 dataOnElement[HCURL]), // HCURL
62 boost::make_shared<DerivedEntitiesFieldData>(
63 dataOnElement[HDIV]), // HDIV
64 boost::make_shared<DerivedEntitiesFieldData>(dataOnElement[L2]) // L2
65
66 },
67 dataNoField(*dataOnElement[NOFIELD].get()),
68 dataH1(*dataOnElement[H1].get()), dataHcurl(*dataOnElement[HCURL].get()),
69 dataHdiv(*dataOnElement[HDIV].get()), dataL2(*dataOnElement[L2].get()),
70 lastEvaluatedElementEntityType(MBMAXTYPE), sidePtrFE(nullptr),
71 refinePtrFE(nullptr) {
72
73 dataOnElement[NOSPACE]->dataOnEntities[MBENTITYSET].push_back(
75
76 dataOnElement[NOFIELD]->dataOnEntities[MBENTITYSET].push_back(
78 derivedDataOnElement[NOFIELD]->dataOnEntities[MBENTITYSET].push_back(
80}
81
82// ** Sense **
83
85 const EntityType type,
86 boost::ptr_vector<EntitiesFieldData::EntData> &data) const {
88
89 auto &side_table = numeredEntFiniteElementPtr->getSideNumberTable().get<0>();
90 auto sit = side_table.lower_bound(get_id_for_min_type(type));
91 if (sit != side_table.end()) {
92 auto hi_sit = side_table.upper_bound(get_id_for_max_type(type));
93 for (; sit != hi_sit; ++sit) {
94 if (const auto side_number = (*sit)->side_number; side_number >= 0) {
95 const int brother_side_number = (*sit)->brother_side_number;
96 const int sense = (*sit)->sense;
97
98 data[side_number].getSense() = sense;
99 if (brother_side_number != -1)
100 data[brother_side_number].getSense() = sense;
101 }
102 }
103 }
105}
106
107// ** Order **
108
109template <typename ENTMULTIINDEX>
110static inline int getMaxOrder(const ENTMULTIINDEX &multi_index) {
111 int max_order = 0;
112 for (auto ent_field_weak_ptr : multi_index)
113 if (auto e = ent_field_weak_ptr.lock()) {
114 const int order = e->getMaxOrder();
115 max_order = (max_order < order) ? order : max_order;
116 }
117 return max_order;
118}
119
121 int max_order = 0;
122 for (auto e : getDataFieldEnts()) {
123 if (auto ptr = e.lock()) {
124 const int order = ptr->getMaxOrder();
125 max_order = (max_order < order) ? order : max_order;
126 }
127 }
128 return max_order;
129}
130
134
138
140 const EntityType type, const FieldSpace space,
141 boost::ptr_vector<EntitiesFieldData::EntData> &data) const {
143
144 auto set_order = [&]() {
146 auto &side_table = numeredEntFiniteElementPtr->getSideNumberTable();
147
148 for (unsigned int s = 0; s != data.size(); ++s)
149 data[s].getOrder() = 0;
150
151 const FieldEntity_vector_view &data_field_ent = getDataFieldEnts();
152
153 for (auto r = fieldsPtr->get<BitFieldId_space_mi_tag>().equal_range(space);
154 r.first != r.second; ++r.first) {
155
156 const auto field_bit_number = (*r.first)->getBitNumber();
157 const auto lo_uid = FieldEntity::getLocalUniqueIdCalculate(
158 field_bit_number, get_id_for_min_type(type));
159 auto lo = std::lower_bound(data_field_ent.begin(), data_field_ent.end(),
160 lo_uid, cmp_uid_lo);
161 if (lo != data_field_ent.end()) {
162 const auto hi_uid = FieldEntity::getLocalUniqueIdCalculate(
163 field_bit_number, get_id_for_max_type(type));
164 auto hi =
165 std::upper_bound(lo, data_field_ent.end(), hi_uid, cmp_uid_hi);
166 for (; lo != hi; ++lo) {
167
168 if (auto ptr = lo->lock()) {
169
170 auto &e = *ptr;
171 auto sit = side_table.find(e.getEnt());
172 if (sit != side_table.end()) {
173 auto &side = *sit;
174 if (const auto side_number = side->side_number;
175 side_number >= 0) {
176 ApproximationOrder ent_order = e.getMaxOrder();
177 auto &dat = data[side_number];
178 dat.getOrder() =
179 dat.getOrder() > ent_order ? dat.getOrder() : ent_order;
180 }
181 } else
182 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
183 "Entity on side of the element not found");
184 }
185 }
186 }
187 }
188
190 };
191
192 auto set_order_on_brother = [&]() {
194 auto &side_table =
195 numeredEntFiniteElementPtr->getSideNumberTable().get<0>();
196 auto sit = side_table.lower_bound(get_id_for_min_type(type));
197 if (sit != side_table.end()) {
198 auto hi_sit = side_table.upper_bound(get_id_for_max_type(type));
199 for (; sit != hi_sit; ++sit) {
200 const int brother_side_number = (*sit)->brother_side_number;
201 if (brother_side_number != -1) {
202 const int side_number = (*sit)->side_number;
203 data[brother_side_number].getOrder() = data[side_number].getOrder();
204 }
205 }
206 }
208 };
209
210 CHKERR set_order();
211 CHKERR set_order_on_brother();
212
214}
215
216// ** Indices **
217
218template <typename EXTRACTOR>
220 const int bit_number, FieldEntity_vector_view &ents_field,
221 VectorInt &nodes_indices, VectorInt &local_nodes_indices,
222 EXTRACTOR &&extractor) const {
224
225 auto field_it = fieldsPtr->get<BitFieldId_mi_tag>().find(
226 BitFieldId().set(bit_number - 1));
227 if (field_it != fieldsPtr->get<BitFieldId_mi_tag>().end()) {
228
229#ifndef NDEBUG
230 if ((*field_it)->getBitNumber() != bit_number)
231 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Wrong bit number");
232#endif
233 const auto lo_uid = FieldEntity::getLocalUniqueIdCalculate(
234 bit_number, get_id_for_min_type<MBVERTEX>());
235 auto lo = std::lower_bound(ents_field.begin(), ents_field.end(), lo_uid,
236 cmp_uid_lo);
237 if (lo != ents_field.end()) {
238 const auto hi_uid = FieldEntity::getLocalUniqueIdCalculate(
239 bit_number, get_id_for_max_type<MBVERTEX>());
240 auto hi = std::upper_bound(lo, ents_field.end(), hi_uid, cmp_uid_hi);
241
242 const int num_nodes = getNumberOfNodes();
243 const int nb_dofs_on_vert = (*field_it)->getNbOfCoeffs();
244 const int max_nb_dofs = nb_dofs_on_vert * num_nodes;
245
246 int nb_dofs = 0;
247 for (auto it = lo; it != hi; ++it) {
248 if (auto e = it->lock()) {
249 if (auto cache = extractor(e).lock()) {
250 if (cache->loHi[0] != cache->loHi[1]) {
251 nb_dofs += std::distance(cache->loHi[0], cache->loHi[1]);
252 break;
253 }
254 }
255 }
256 }
257
258 if (nb_dofs) {
259 nodes_indices.resize(max_nb_dofs, false);
260 local_nodes_indices.resize(max_nb_dofs, false);
261 } else {
262 nodes_indices.resize(0, false);
263 local_nodes_indices.resize(0, false);
264 }
265
266 if (nb_dofs != max_nb_dofs) {
267 std::fill(nodes_indices.begin(), nodes_indices.end(), -1);
268 std::fill(local_nodes_indices.begin(), local_nodes_indices.end(), -1);
269 }
270
271 for (auto it = lo; it != hi; ++it) {
272 if (auto e = it->lock()) {
273 auto side_ptr = e->getSideNumberPtr();
274 if (const auto side_number = side_ptr->side_number;
275 side_number >= 0) {
276 const auto brother_side_number = side_ptr->brother_side_number;
277 if (auto cache = extractor(e).lock()) {
278 for (auto dit = cache->loHi[0]; dit != cache->loHi[1]; ++dit) {
279 auto &dof = **dit;
280 const int idx = dof.getPetscGlobalDofIdx();
281 const int local_idx = dof.getPetscLocalDofIdx();
282 const int pos =
283 side_number * nb_dofs_on_vert + dof.getDofCoeffIdx();
284 nodes_indices[pos] = idx;
285 local_nodes_indices[pos] = local_idx;
286 if (brother_side_number != -1) {
287 const int elem_idx = brother_side_number * nb_dofs_on_vert +
288 (*dit)->getDofCoeffIdx();
289 nodes_indices[elem_idx] = idx;
290 local_nodes_indices[elem_idx] = local_idx;
291 }
292 }
293 }
294 }
295 }
296 }
297 } else {
298 nodes_indices.resize(0, false);
299 local_nodes_indices.resize(0, false);
300 }
301
302 } else {
303 nodes_indices.resize(0, false);
304 local_nodes_indices.resize(0, false);
305 }
306
308}
309
312 const int bit_number) const {
313
314 struct Extractor {
315 boost::weak_ptr<EntityCacheNumeredDofs>
316 operator()(boost::shared_ptr<FieldEntity> &e) {
317 return e->entityCacheRowDofs;
318 }
319 };
320
321 return getNodesIndices(bit_number, getRowFieldEnts(),
322 data.dataOnEntities[MBVERTEX][0].getIndices(),
323 data.dataOnEntities[MBVERTEX][0].getLocalIndices(),
324 Extractor());
325}
326
329 const int bit_number) const {
330
331 struct Extractor {
332 boost::weak_ptr<EntityCacheNumeredDofs>
333 operator()(boost::shared_ptr<FieldEntity> &e) {
334 return e->entityCacheColDofs;
335 }
336 };
337
338 return getNodesIndices(bit_number, getColFieldEnts(),
339 data.dataOnEntities[MBVERTEX][0].getIndices(),
340 data.dataOnEntities[MBVERTEX][0].getLocalIndices(),
341 Extractor());
342}
343
344template <typename EXTRACTOR>
346 EntitiesFieldData &data, const int bit_number,
347 FieldEntity_vector_view &ents_field, const EntityType type_lo,
348 const EntityType type_hi, EXTRACTOR &&extractor) const {
350
351 for (EntityType t = type_lo; t != type_hi; ++t) {
352 for (auto &dat : data.dataOnEntities[t]) {
353 dat.getIndices().resize(0, false);
354 dat.getLocalIndices().resize(0, false);
355 }
356 }
357
358 const auto lo_uid = FieldEntity::getLocalUniqueIdCalculate(
359 bit_number, get_id_for_min_type(type_lo));
360 auto lo = std::lower_bound(ents_field.begin(), ents_field.end(), lo_uid,
361 cmp_uid_lo);
362 if (lo != ents_field.end()) {
363 const auto hi_uid = FieldEntity::getLocalUniqueIdCalculate(
364 bit_number, get_id_for_max_type(type_hi));
365 auto hi = std::upper_bound(lo, ents_field.end(), hi_uid, cmp_uid_hi);
366 if (lo != hi) {
367
368 std::vector<boost::weak_ptr<FieldEntity>> brother_ents_vec;
369
370 for (auto it = lo; it != hi; ++it)
371 if (auto e = it->lock()) {
372
373 const EntityType type = e->getEntType();
374 auto side_ptr = e->getSideNumberPtr();
375 if (const auto side = side_ptr->side_number; side >= 0) {
376 const auto nb_dofs_on_ent = e->getNbDofsOnEnt();
377 const auto brother_side = side_ptr->brother_side_number;
378 auto &dat = data.dataOnEntities[type][side];
379 auto &ent_field_indices = dat.getIndices();
380 auto &ent_field_local_indices = dat.getLocalIndices();
381
382 ent_field_indices.resize(nb_dofs_on_ent, false);
383 ent_field_local_indices.resize(nb_dofs_on_ent, false);
384 std::fill(ent_field_indices.data().begin(),
385 ent_field_indices.data().end(), -1);
386 std::fill(ent_field_local_indices.data().begin(),
387 ent_field_local_indices.data().end(), -1);
388
389 if (auto cache = extractor(e).lock()) {
390 for (auto dit = cache->loHi[0]; dit != cache->loHi[1]; ++dit) {
391 const int idx = (*dit)->getEntDofIdx();
392 ent_field_indices[idx] = (*dit)->getPetscGlobalDofIdx();
393 ent_field_local_indices[idx] = (*dit)->getPetscLocalDofIdx();
394 }
395 }
396
397 if (brother_side != -1) {
398 auto &dat_brother = data.dataOnEntities[type][brother_side];
399 dat_brother.getIndices().resize(nb_dofs_on_ent, false);
400 dat_brother.getLocalIndices().resize(nb_dofs_on_ent, false);
401 noalias(dat_brother.getIndices()) = dat.getIndices();
402 noalias(dat_brother.getLocalIndices()) = dat.getLocalIndices();
403 }
404 }
405 }
406 }
407 }
408
410}
411
413 EntitiesFieldData &data, const int bit_number, const EntityType type_lo,
414 const EntityType type_hi) const {
415
416 struct Extractor {
417 boost::weak_ptr<EntityCacheNumeredDofs>
418 operator()(boost::shared_ptr<FieldEntity> &e) {
419 return e->entityCacheRowDofs;
420 }
421 };
422
423 return getEntityIndices(data, bit_number, getRowFieldEnts(), type_lo, type_hi,
424 Extractor());
425}
426
428 EntitiesFieldData &data, const int bit_number, const EntityType type_lo,
429 const EntityType type_hi) const {
430
431 struct Extractor {
432 boost::weak_ptr<EntityCacheNumeredDofs>
433 operator()(boost::shared_ptr<FieldEntity> &e) {
434 return e->entityCacheColDofs;
435 }
436 };
437
438 return getEntityIndices(data, bit_number, getColFieldEnts(), type_lo, type_hi,
439 Extractor());
440}
441
442// ** Indices from problem **
443
445 const std::string &field_name, const NumeredDofEntity_multiIndex &dofs,
446 VectorInt &nodes_indices) const {
448
449 const Field *field_struture = mField.get_field_structure(field_name);
450 if (field_struture->getSpace() == H1) {
451
452 const int num_nodes = getNumberOfNodes();
453 nodes_indices.resize(field_struture->getNbOfCoeffs() * num_nodes, false);
454 std::fill(nodes_indices.begin(), nodes_indices.end(), -1);
455
456 auto &side_table = const_cast<SideNumber_multiIndex &>(
457 numeredEntFiniteElementPtr->getSideNumberTable());
458 auto siit = side_table.get<1>().lower_bound(boost::make_tuple(MBVERTEX, 0));
459 auto hi_siit =
460 side_table.get<1>().lower_bound(boost::make_tuple(MBVERTEX, 10000));
461
462 int nn = 0;
463 for (; siit != hi_siit; siit++, nn++) {
464 if (siit->get()->side_number >= 0) {
465 auto bit_number = mField.get_field_bit_number(field_name);
466 const EntityHandle ent = siit->get()->ent;
467 auto dit = dofs.get<Unique_mi_tag>().lower_bound(
469 auto hi_dit = dofs.get<Unique_mi_tag>().upper_bound(
471 for (; dit != hi_dit; dit++) {
472 nodes_indices[siit->get()->side_number * (*dit)->getNbOfCoeffs() +
473 (*dit)->getDofCoeffIdx()] =
474 (*dit)->getPetscGlobalDofIdx();
475 }
476 }
477 }
478 } else {
479 nodes_indices.resize(0, false);
480 }
481
483}
484
486 const std::string &field_name, const NumeredDofEntity_multiIndex &dofs,
487 EntityType type, int side_number, VectorInt &indices) const {
489
490 indices.resize(0);
491
492 auto &side_table = const_cast<SideNumber_multiIndex &>(
493 numeredEntFiniteElementPtr->getSideNumberTable());
494 auto siit =
495 side_table.get<1>().lower_bound(boost::make_tuple(type, side_number));
496 auto hi_siit =
497 side_table.get<1>().upper_bound(boost::make_tuple(type, side_number));
498
499 for (; siit != hi_siit; siit++) {
500 if (siit->get()->side_number >= 0) {
501
502 const EntityHandle ent = siit->get()->ent;
503 auto bit_number = mField.get_field_bit_number(field_name);
504 auto dit = dofs.get<Unique_mi_tag>().lower_bound(
506 auto hi_dit = dofs.get<Unique_mi_tag>().upper_bound(
508 indices.resize(std::distance(dit, hi_dit));
509 for (; dit != hi_dit; dit++) {
510
511 indices[(*dit)->getEntDofIdx()] = (*dit)->getPetscGlobalDofIdx();
512 }
513 }
514 }
515
517}
518
520 const std::string &field_name, VectorInt &nodes_indices) const {
522 nodes_indices);
523}
524
527 EntityType type, int side_number,
528 VectorInt &indices) const {
530 type, side_number, indices);
531}
532
534 const std::string &field_name, VectorInt &nodes_indices) const {
536 nodes_indices);
537}
538
541 EntityType type, int side_number,
542 VectorInt &indices) const {
544 type, side_number, indices);
545}
546
547// ** Data **
548
551
552 for (auto &data : dataOnElement) {
553 if (data) {
554 for (auto &dat : data->dataOnEntities) {
555 for (auto &ent_dat : dat) {
556 ent_dat.getEntDataBitRefLevel().clear();
557 }
558 }
559 }
560 }
561
562 auto &field_ents = getDataFieldEnts();
563 for (auto it : field_ents) {
564 if (auto e = it.lock()) {
565 const FieldSpace space = e->getSpace();
566 if (space > NOFIELD) {
567 const EntityType type = e->getEntType();
568 const signed char side = e->getSideNumberPtr()->side_number;
569 if (side >= 0) {
570 if (auto &data = dataOnElement[space]) {
571 if (type == MBVERTEX) {
572 auto &dat = data->dataOnEntities[type][0];
573 dat.getEntDataBitRefLevel().resize(getNumberOfNodes(), false);
574 dat.getEntDataBitRefLevel()[side] = e->getBitRefLevel();
575 } else {
576 auto &dat = data->dataOnEntities[type][side];
577 dat.getEntDataBitRefLevel().resize(1,
578 false); // one entity per sie
579 dat.getEntDataBitRefLevel()[0] = e->getBitRefLevel();
580 }
581 }
582 }
583 }
584 }
585 }
586
588};
589
592 const int bit_number) const {
593
594 auto get_nodes_field_data = [&](VectorDouble &nodes_data,
595 VectorFieldEntities &field_entities,
596 VectorDofs &nodes_dofs, FieldSpace &space,
598 VectorInt &bb_node_order) {
600
601 nodes_data.resize(0, false);
602 nodes_dofs.resize(0, false);
603 field_entities.resize(0, false);
604
605 auto field_it =
606 fieldsPtr->get<BitFieldId_mi_tag>().find(BitFEId().set(bit_number - 1));
607 if (field_it != fieldsPtr->get<BitFieldId_mi_tag>().end()) {
608
609#ifndef NDEBUG
610 if ((*field_it)->getBitNumber() != bit_number)
611 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Wrong bit number");
612#endif
613 const int nb_dofs_on_vert = (*field_it)->getNbOfCoeffs();
614 space = (*field_it)->getSpace();
615 base = (*field_it)->getApproxBase();
616
617 auto &field_ents = getDataFieldEnts();
618 const auto lo_uid = FieldEntity::getLocalUniqueIdCalculate(
619 bit_number, get_id_for_min_type<MBVERTEX>());
620 auto lo = std::lower_bound(field_ents.begin(), field_ents.end(), lo_uid,
621 cmp_uid_lo);
622 if (lo != field_ents.end()) {
623 const auto hi_uid = FieldEntity::getLocalUniqueIdCalculate(
624 bit_number, get_id_for_max_type<MBVERTEX>());
625 auto hi = std::upper_bound(lo, field_ents.end(), hi_uid, cmp_uid_hi);
626 if (lo != hi) {
627
628 int nb_dofs = 0;
629 for (auto it = lo; it != hi; ++it) {
630 if (auto e = it->lock()) {
631 if (auto cache = e->entityCacheDataDofs.lock()) {
632 if (cache->loHi[0] != cache->loHi[1]) {
633 nb_dofs += std::distance(cache->loHi[0], cache->loHi[1]);
634 break;
635 }
636 }
637 }
638 }
639
640 if (nb_dofs) {
641
642 const int num_nodes = getNumberOfNodes();
643 bb_node_order.resize(num_nodes, false);
644 bb_node_order.clear();
645 const int max_nb_dofs = nb_dofs_on_vert * num_nodes;
646 nodes_data.resize(max_nb_dofs, false);
647 nodes_dofs.resize(max_nb_dofs, false);
648 field_entities.resize(num_nodes, false);
649 std::fill(nodes_data.begin(), nodes_data.end(), 0);
650 std::fill(nodes_dofs.begin(), nodes_dofs.end(), nullptr);
651 std::fill(field_entities.begin(), field_entities.end(), nullptr);
652
653 std::vector<boost::weak_ptr<FieldEntity>> brother_ents_vec;
654
655 for (auto it = lo; it != hi; ++it) {
656 if (auto e = it->lock()) {
657 const auto &sn = e->getSideNumberPtr();
658 // Some field entities on skeleton can have negative side
659 // number
660 if (const auto side_number = sn->side_number;
661 side_number >= 0) {
662 const int brother_side_number = sn->brother_side_number;
663
664 field_entities[side_number] = e.get();
665 if (brother_side_number != -1) {
666 brother_ents_vec.emplace_back(e);
667 field_entities[side_number] = field_entities[side_number];
668 }
669
670 bb_node_order[side_number] = e->getMaxOrder();
671 int pos = side_number * nb_dofs_on_vert;
672 auto ent_filed_data_vec = e->getEntFieldData();
673 if (auto cache = e->entityCacheDataDofs.lock()) {
674 for (auto dit = cache->loHi[0]; dit != cache->loHi[1];
675 ++dit) {
676 const auto dof_idx = (*dit)->getEntDofIdx();
677 nodes_data[pos + dof_idx] = ent_filed_data_vec[dof_idx];
678 nodes_dofs[pos + dof_idx] =
679 reinterpret_cast<FEDofEntity *>((*dit).get());
680 }
681 }
682 }
683 }
684 }
685
686 for (auto &it : brother_ents_vec) {
687 if (const auto e = it.lock()) {
688 const auto &sn = e->getSideNumberPtr();
689 const int side_number = sn->side_number;
690 const int brother_side_number = sn->brother_side_number;
691 bb_node_order[brother_side_number] = bb_node_order[side_number];
692 int pos = side_number * nb_dofs_on_vert;
693 int brother_pos = brother_side_number * nb_dofs_on_vert;
694 for (int ii = 0; ii != nb_dofs_on_vert; ++ii) {
695 nodes_data[brother_pos] = nodes_data[pos];
696 nodes_dofs[brother_pos] = nodes_dofs[pos];
697 ++pos;
698 ++brother_pos;
699 }
700 }
701 }
702 }
703 }
704 }
705 }
706
708 };
709
710 return get_nodes_field_data(
711 data.dataOnEntities[MBVERTEX][0].getFieldData(),
712 data.dataOnEntities[MBVERTEX][0].getFieldEntities(),
713 data.dataOnEntities[MBVERTEX][0].getFieldDofs(),
714 data.dataOnEntities[MBVERTEX][0].getSpace(),
715 data.dataOnEntities[MBVERTEX][0].getBase(),
716 data.dataOnEntities[MBVERTEX][0].getBBNodeOrder());
717}
718
720 EntitiesFieldData &data, const int bit_number, const EntityType type_lo,
721 const EntityType type_hi) const {
723 for (EntityType t = type_lo; t != type_hi; ++t) {
724 for (auto &dat : data.dataOnEntities[t]) {
725 dat.getOrder() = 0;
726 dat.getBase() = NOBASE;
727 dat.getSpace() = NOSPACE;
728 dat.getFieldData().resize(0, false);
729 dat.getFieldDofs().resize(0, false);
730 dat.getFieldEntities().resize(0, false);
731 }
732 }
733
734 auto &field_ents = getDataFieldEnts();
735 const auto lo_uid = FieldEntity::getLocalUniqueIdCalculate(
736 bit_number, get_id_for_min_type(type_lo));
737 auto lo = std::lower_bound(field_ents.begin(), field_ents.end(), lo_uid,
738 cmp_uid_lo);
739 if (lo != field_ents.end()) {
740 const auto hi_uid = FieldEntity::getLocalUniqueIdCalculate(
741 bit_number, get_id_for_max_type(type_hi));
742 auto hi = std::upper_bound(lo, field_ents.end(), hi_uid, cmp_uid_hi);
743 if (lo != hi) {
744
745 std::vector<boost::weak_ptr<FieldEntity>> brother_ents_vec;
746
747 for (auto it = lo; it != hi; ++it)
748 if (auto e = it->lock()) {
749 auto side_ptr = e->getSideNumberPtr();
750 if (const auto side = side_ptr->side_number; side >= 0) {
751 const EntityType type = e->getEntType();
752 auto &dat = data.dataOnEntities[type][side];
753 auto &ent_field = dat.getFieldEntities();
754 auto &ent_field_dofs = dat.getFieldDofs();
755 auto &ent_field_data = dat.getFieldData();
756
757 const int brother_side = side_ptr->brother_side_number;
758 if (brother_side != -1)
759 brother_ents_vec.emplace_back(e);
760
761 dat.getBase() = e->getApproxBase();
762 dat.getSpace() = e->getSpace();
763 const int ent_order = e->getMaxOrder();
764 dat.getOrder() =
765 dat.getOrder() > ent_order ? dat.getOrder() : ent_order;
766
767 auto ent_data = e->getEntFieldData();
768 ent_field_data.resize(ent_data.size(), false);
769 noalias(ent_field_data) = ent_data;
770 ent_field_dofs.resize(ent_data.size(), false);
771 std::fill(ent_field_dofs.begin(), ent_field_dofs.end(), nullptr);
772 ent_field.resize(1, false);
773 ent_field[0] = e.get();
774 if (auto cache = e->entityCacheDataDofs.lock()) {
775 for (auto dit = cache->loHi[0]; dit != cache->loHi[1]; ++dit) {
776 ent_field_dofs[(*dit)->getEntDofIdx()] =
777 reinterpret_cast<FEDofEntity *>((*dit).get());
778 }
779 }
780 }
781 }
782
783 for (auto &it : brother_ents_vec) {
784 if (const auto e = it.lock()) {
785 const EntityType type = e->getEntType();
786 const int side = e->getSideNumberPtr()->side_number;
787 const int brother_side = e->getSideNumberPtr()->brother_side_number;
788 auto &dat = data.dataOnEntities[type][side];
789 auto &dat_brother = data.dataOnEntities[type][brother_side];
790 dat_brother.getBase() = dat.getBase();
791 dat_brother.getSpace() = dat.getSpace();
792 dat_brother.getOrder() = dat.getOrder();
793 dat_brother.getFieldData() = dat.getFieldData();
794 dat_brother.getFieldDofs() = dat.getFieldDofs();
795 dat_brother.getFieldEntities() = dat.getFieldEntities();
796 }
797 }
798 }
799 }
800
802}
803
804template <typename EXTRACTOR>
807 const int bit_number,
808 EXTRACTOR &&extractor) const {
810
811 // resize data on entities
812 std::array<FieldEntity_vector_view, MBMAXTYPE> field_ents_by_type;
813 for (auto it : getDataFieldEnts())
814 if (auto e = it.lock())
815 if (e->getBitNumber() == bit_number) {
816 field_ents_by_type[e->getEntType()].emplace_back(e);
817 }
818
819 auto set_entity_data = [&](auto &data_on_element) {
821
822 // resize data containers
823 for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t) {
824 auto &data = data_on_element.dataOnEntities[t];
825 data.resize(field_ents_by_type[t].size());
826 }
827
828 // reset data
829 for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t) {
830 auto &data = data_on_element.dataOnEntities[t];
831 for (auto &d : data) {
832 d.getEntDataBitRefLevel().clear();
833 d.getOrder() = 0;
834 d.getBase() = NOBASE;
835 d.getSpace() = NOSPACE;
836 d.getFieldData().resize(0, false);
837 d.getFieldDofs().resize(0, false);
838 d.getFieldEntities().resize(0, false);
839 d.getIndices().resize(0, false);
840 d.getLocalIndices().resize(0, false);
841 }
842 }
843
844 // set bit ref level on entities
845 for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t) {
846 int side = 0;
847 for (auto it : field_ents_by_type[t]) {
848 if (auto e = it.lock()) {
849 auto &data = data_on_element.dataOnEntities[t][side];
850 data.getEntDataBitRefLevel().resize(1, false);
851 data.getEntDataBitRefLevel()[0] = e->getBitRefLevel();
852 ++side;
853 }
854 }
855 }
856
857 // set field data on entities
858 for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t) {
859 int side = 0;
860 for (auto it : field_ents_by_type[t]) {
861 if (auto e = it.lock()) {
862 auto &data = data_on_element.dataOnEntities[t][side];
863 data.getBase() = e->getApproxBase();
864 data.getSpace() = e->getSpace();
865 data.getFieldData() = e->getEntFieldData();
866 data.getFieldEntities().resize(1, false);
867 data.getFieldEntities()[0] = e.get();
868 auto &ent_field_dofs = data.getFieldDofs();
869 ent_field_dofs.resize(data.getFieldData().size(), false);
870 std::fill(ent_field_dofs.begin(), ent_field_dofs.end(), nullptr);
871 if (auto cache = e->entityCacheDataDofs.lock()) {
872 for (auto dit = cache->loHi[0]; dit != cache->loHi[1]; ++dit) {
873 ent_field_dofs[(*dit)->getEntDofIdx()] =
874 reinterpret_cast<FEDofEntity *>((*dit).get());
875 }
876 }
877 ++side;
878 }
879 }
880 }
881
882 // set indices on entities
883 for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t) {
884 int side = 0;
885 for (auto it : field_ents_by_type[t]) {
886 if (auto e = it.lock()) {
887 auto &data = data_on_element.dataOnEntities[t][side];
888 auto &indices = data.getIndices();
889 auto &local_indices = data.getLocalIndices();
890 indices.resize(data.getFieldData().size(), false);
891 local_indices.resize(data.getFieldData().size(), false);
892 std::fill(indices.begin(), indices.end(), -1);
893 std::fill(local_indices.begin(), local_indices.end(), -1);
894
895 if (auto cache = extractor(e).lock()) {
896 for (auto dit = cache->loHi[0]; dit != cache->loHi[1]; ++dit) {
897 indices[(*dit)->getEntDofIdx()] = (*dit)->getPetscGlobalDofIdx();
898 local_indices[(*dit)->getEntDofIdx()] =
899 (*dit)->getPetscLocalDofIdx();
900 }
901 }
902
903 ++side;
904 }
905 }
906 }
908 };
909
910 CHKERR set_entity_data(data);
911
913}
914
915// ** Face **
916
920 auto &face_nodes = data.facesNodes;
921 auto &face_nodes_order = data.facesNodesOrder;
922 auto &side_table = const_cast<SideNumber_multiIndex &>(
923 numeredEntFiniteElementPtr->getSideNumberTable());
924 const auto ent = numeredEntFiniteElementPtr->getEnt();
925 const auto type = numeredEntFiniteElementPtr->getEntType();
926 const auto nb_faces = CN::NumSubEntities(type, 2);
927 const EntityHandle *conn_ele;
928 int num_nodes_ele;
929 CHKERR mField.get_moab().get_connectivity(ent, conn_ele, num_nodes_ele, true);
930 auto side_ptr_it = side_table.get<1>().lower_bound(
931 boost::make_tuple(CN::TypeDimensionMap[2].first, 0));
932 auto hi_side_ptr_it = side_table.get<1>().upper_bound(boost::make_tuple(
933 CN::TypeDimensionMap[2].second, std::numeric_limits<signed char>::max()));
934
935 for (; side_ptr_it != hi_side_ptr_it; ++side_ptr_it) {
936 const auto side = (*side_ptr_it)->side_number;
937 if (side < 0)
938 continue;
939 const auto sense = (*side_ptr_it)->sense;
940 const auto offset = (*side_ptr_it)->offset;
941
942 EntityType face_type;
943 int nb_nodes_face;
944 auto face_indices =
945 CN::SubEntityVertexIndices(type, 2, side, face_type, nb_nodes_face);
946 face_nodes.resize(nb_faces, nb_nodes_face);
947 face_nodes_order.resize(nb_faces, nb_nodes_face);
948
949 if (sense == 1)
950 for (int n = 0; n != nb_nodes_face; ++n)
951 face_nodes_order(side, n) = (n + offset) % nb_nodes_face;
952 else
953 for (int n = 0; n != nb_nodes_face; ++n)
954 face_nodes_order(side, n) =
955 (nb_nodes_face - (n - offset) % nb_nodes_face) % nb_nodes_face;
956
957 for (int n = 0; n != nb_nodes_face; ++n)
958 face_nodes(side, n) = face_indices[face_nodes_order(side, n)];
959
960#ifndef NDEBUG
961 const auto face_ent = (*side_ptr_it)->ent;
962 auto check = [&]() {
964 const EntityHandle *conn_face;
965 // int nb_nodes_face;
966 CHKERR mField.get_moab().get_connectivity(face_ent, conn_face,
967 nb_nodes_face, true);
968 face_nodes.resize(nb_faces, nb_nodes_face);
969 for (int nn = 0; nn != nb_nodes_face; ++nn) {
970 if (face_nodes(side, nn) !=
971 std::distance(
972 conn_ele,
973 std::find(conn_ele, &conn_ele[num_nodes_ele], conn_face[nn]))) {
974 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
975 "Wrong face numeration");
976 }
977 }
979 };
980 CHKERR check();
981#endif
982 }
983
985}
986
987// ** Space and Base **
988
990 EntitiesFieldData &data) const {
992
993 if (nInTheLoop == 0) {
994 data.bAse.reset();
995 for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t) {
996 data.spacesOnEntities[t].reset();
997 data.basesOnEntities[t].reset();
998 }
999 for (int s = 0; s != LASTSPACE; ++s) {
1000 data.basesOnSpaces[s].reset();
1001 data.brokenBasesOnSpaces[s].reset();
1002 }
1003 }
1004
1005 auto fe_type = numeredEntFiniteElementPtr->getEntType();
1006
1007 if (getDataFieldEntsPtr())
1008 for (auto e : getDataFieldEnts()) {
1009 if (auto ptr = e.lock()) {
1010 // get data from entity
1011 const EntityType type = ptr->getEntType();
1012 if (DefaultElementAdjacency::getDefTypeMap(fe_type, type)) {
1013 const FieldSpace space = ptr->getSpace();
1014 const FieldContinuity continuity = ptr->getContinuity();
1015 const FieldApproximationBase approx = ptr->getApproxBase();
1016
1017 // set data
1018 switch (continuity) {
1019 case CONTINUOUS:
1020 data.basesOnSpaces[space].set(approx);
1021 break;
1022 case DISCONTINUOUS:
1023 data.brokenBasesOnSpaces[space].set(approx);
1024 break;
1025 default:
1026 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1027 "Continuity not defined");
1028 }
1029
1030 data.bAse.set(approx);
1031 data.spacesOnEntities[type].set(space);
1032 data.basesOnEntities[type].set(approx);
1033 }
1034 }
1035 }
1036 else
1037 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1038 "data fields ents not allocated on element");
1039
1040 for (auto space = 0; space != LASTSPACE; ++space)
1041 if ((data.brokenBasesOnSpaces[space] & data.basesOnSpaces[space]).any())
1042 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1043 "Discontinuous and continuous bases on the same space");
1044
1046}
1047
1049 const FieldApproximationBase b) {
1051 if (dataOnElement[H1]->bAse.test(b)) {
1052
1053 switch (static_cast<FieldApproximationBase>(b)) {
1054 case NOBASE:
1056 // BERNSTEIN_BEZIER_BASE is not hierarchical base
1058 }
1059 default:
1060 break;
1061 }
1062
1063 auto get_elem_base = [&](auto base) {
1064 if (b != USER_BASE) {
1068 "Functions generating approximation base not defined");
1069 return getElementPolynomialBase();
1070 } else {
1071 if (!getUserPolynomialBase())
1074 "Functions generating user approximation base not defined");
1075 return getUserPolynomialBase();
1076 }
1077 };
1078
1079 auto get_ctx = [&](auto space, auto base, auto continuity) {
1080 return boost::make_shared<EntPolynomialBaseCtx>(
1081 *dataOnElement[space], static_cast<FieldSpace>(space), continuity,
1082 static_cast<FieldApproximationBase>(base), NOBASE);
1083 };
1084
1085 auto get_value = [&](auto elem_base, auto &gaussPts, auto &&ctx) {
1086 return elem_base->getValue(gaussPts, ctx);
1087 };
1088
1089 for (int space = H1; space != LASTSPACE; ++space) {
1090
1091#ifndef NDEBUG
1092 if (dataOnElement[H1]->basesOnSpaces[space].test(b) &&
1093 dataOnElement[H1]->brokenBasesOnSpaces[space].test(b)) {
1094 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1095 "Discontinuous and continuous bases on the same space");
1096 }
1097#endif // NDEBUG
1098
1099 if (dataOnElement[H1]->basesOnSpaces[space].test(b))
1100 CHKERR get_value(get_elem_base(b), gaussPts,
1101 get_ctx(space, b, CONTINUOUS));
1102 else if (dataOnElement[H1]->brokenBasesOnSpaces[space].test(b))
1103 CHKERR get_value(get_elem_base(b), gaussPts,
1104 get_ctx(space, b, DISCONTINUOUS));
1105 }
1106
1107 }
1109}
1110
1113 /// Use the some node base. Node base is usually used for construction other
1114 /// bases.
1115 for (int space = HCURL; space != LASTSPACE; ++space) {
1116 dataOnElement[space]->dataOnEntities[MBVERTEX][0].getNSharedPtr(NOBASE) =
1117 dataOnElement[H1]->dataOnEntities[MBVERTEX][0].getNSharedPtr(NOBASE);
1118 dataOnElement[space]->dataOnEntities[MBVERTEX][0].getDiffNSharedPtr(
1119 NOBASE) =
1120 dataOnElement[H1]->dataOnEntities[MBVERTEX][0].getDiffNSharedPtr(
1121 NOBASE);
1122 }
1123 for (int b = AINSWORTH_LEGENDRE_BASE; b != LASTBASE; b++) {
1125 static_cast<FieldApproximationBase>(b));
1126 }
1128}
1129
1133
1134 const auto ele_type = numeredEntFiniteElementPtr->getEntType();
1135
1136 auto get_nodal_base_data = [&](EntitiesFieldData &data, auto field_ptr) {
1138 auto &space = data.dataOnEntities[MBVERTEX][0].getSpace();
1139 auto &base = data.dataOnEntities[MBVERTEX][0].getBase();
1140 auto &bb_node_order = data.dataOnEntities[MBVERTEX][0].getBBNodeOrder();
1141
1142 auto &field_ents = getDataFieldEnts();
1143 auto bit_number = field_ptr->getBitNumber();
1144 const auto lo_uid = FieldEntity::getLocalUniqueIdCalculate(
1145 bit_number, get_id_for_min_type<MBVERTEX>());
1146 auto lo = std::lower_bound(field_ents.begin(), field_ents.end(), lo_uid,
1147 cmp_uid_lo);
1148 if (lo != field_ents.end()) {
1149 const auto hi_uid = FieldEntity::getLocalUniqueIdCalculate(
1150 bit_number, get_id_for_max_type<MBVERTEX>());
1151 auto hi = std::upper_bound(lo, field_ents.end(), hi_uid, cmp_uid_hi);
1152 if (lo != hi) {
1153
1154 for (auto it = lo; it != hi; ++it)
1155 if (auto first_e = it->lock()) {
1156 space = first_e->getSpace();
1157 base = first_e->getApproxBase();
1158 const int num_nodes = getNumberOfNodes();
1159 bb_node_order.resize(num_nodes, false);
1160 bb_node_order.clear();
1161
1162 std::vector<boost::weak_ptr<FieldEntity>> brother_ents_vec;
1163
1164 for (; it != hi; ++it) {
1165 if (auto e = it->lock()) {
1166 const auto &sn = e->getSideNumberPtr();
1167 const int side_number = sn->side_number;
1168 const int brother_side_number = sn->brother_side_number;
1169 if (brother_side_number != -1)
1170 brother_ents_vec.emplace_back(e);
1171 bb_node_order[side_number] = e->getMaxOrder();
1172 }
1173 }
1174
1175 for (auto &it : brother_ents_vec) {
1176 if (const auto e = it.lock()) {
1177 const auto &sn = e->getSideNumberPtr();
1178 const int side_number = sn->side_number;
1179 const int brother_side_number = sn->brother_side_number;
1180 bb_node_order[brother_side_number] = bb_node_order[side_number];
1181 }
1182 }
1183
1184 break;
1185 }
1186 }
1187 }
1188
1190 };
1191
1192 auto get_entity_base_data = [&](EntitiesFieldData &data, auto field_ptr,
1193 const EntityType type_lo,
1194 const EntityType type_hi) {
1196 for (EntityType t = MBEDGE; t != MBPOLYHEDRON; ++t) {
1197 for (auto &dat : data.dataOnEntities[t]) {
1198 dat.getOrder() = 0;
1199 dat.getBase() = NOBASE;
1200 dat.getSpace() = NOSPACE;
1201 dat.getFieldData().resize(0, false);
1202 dat.getFieldDofs().resize(0, false);
1203 }
1204 }
1205
1206 auto &field_ents = getDataFieldEnts();
1207 auto bit_number = field_ptr->getBitNumber();
1208 const auto lo_uid = FieldEntity::getLocalUniqueIdCalculate(
1209 bit_number, get_id_for_min_type(type_lo));
1210 auto lo = std::lower_bound(field_ents.begin(), field_ents.end(), lo_uid,
1211 cmp_uid_lo);
1212 if (lo != field_ents.end()) {
1213 const auto hi_uid = FieldEntity::getLocalUniqueIdCalculate(
1214 bit_number, get_id_for_max_type(type_hi));
1215 auto hi = std::upper_bound(lo, field_ents.end(), hi_uid, cmp_uid_hi);
1216
1217 std::vector<boost::weak_ptr<FieldEntity>> brother_ents_vec;
1218 for (; lo != hi; ++lo) {
1219 if (auto e = lo->lock()) {
1220 if (auto cache = e->entityCacheDataDofs.lock()) {
1221 if (cache->loHi[0] != cache->loHi[1]) {
1222 if (const auto side = e->getSideNumberPtr()->side_number;
1223 side >= 0) {
1224 const EntityType type = e->getEntType();
1225 auto &dat = data.dataOnEntities[type][side];
1226 const int brother_side =
1227 e->getSideNumberPtr()->brother_side_number;
1228 if (brother_side != -1)
1229 brother_ents_vec.emplace_back(e);
1230 dat.getBase() = e->getApproxBase();
1231 dat.getSpace() = e->getSpace();
1232 const auto ent_order = e->getMaxOrder();
1233 dat.getOrder() =
1234 dat.getOrder() > ent_order ? dat.getOrder() : ent_order;
1235 }
1236 }
1237 }
1238 }
1239 }
1240
1241 for (auto &ent_ptr : brother_ents_vec) {
1242 if (auto e = ent_ptr.lock()) {
1243 const EntityType type = e->getEntType();
1244 const int side = e->getSideNumberPtr()->side_number;
1245 const int brother_side = e->getSideNumberPtr()->brother_side_number;
1246 auto &dat = data.dataOnEntities[type][side];
1247 auto &dat_brother = data.dataOnEntities[type][brother_side];
1248 dat_brother.getBase() = dat.getBase();
1249 dat_brother.getSpace() = dat.getSpace();
1250 dat_brother.getOrder() = dat.getOrder();
1251 }
1252 }
1253 }
1255 };
1256
1257 for (auto &e : getDataFieldEnts()) {
1258 if (auto ent_data_ptr = e.lock()) {
1259 if (ent_data_ptr->getApproxBase() == AINSWORTH_BERNSTEIN_BEZIER_BASE) {
1260 auto space = ent_data_ptr->getSpace();
1261 for (EntityType t = MBVERTEX; t != MBPOLYHEDRON; ++t) {
1262 for (auto &dat : (*dataOnElement[space]).dataOnEntities[t]) {
1263 for (auto &ptr : dat.getBBAlphaIndicesByOrderArray())
1264 ptr.reset();
1265 for (auto &ptr : dat.getBBNByOrderArray())
1266 ptr.reset();
1267 for (auto &ptr : dat.getBBDiffNByOrderArray())
1268 ptr.reset();
1269 }
1270 }
1271 }
1272 }
1273 }
1274
1275 auto check_space = [&](const auto space) {
1276 switch (space) {
1277 case H1:
1278 for (auto t = MBVERTEX; t <= ele_type; ++t) {
1279 if (dataOnElement[H1]->spacesOnEntities[t].test(H1))
1280 return true;
1281 }
1282 return false;
1283 case HCURL:
1284 for (auto t = MBEDGE; t <= ele_type; ++t) {
1285 if (dataOnElement[HCURL]->spacesOnEntities[t].test(HCURL))
1286 return true;
1287 }
1288 return false;
1289 case HDIV:
1290 for (auto t = MBTRI; t <= ele_type; ++t) {
1291 if (dataOnElement[HDIV]->spacesOnEntities[t].test(HDIV))
1292 return true;
1293 }
1294 return false;
1295 case L2:
1296 return dataOnElement[L2]->spacesOnEntities[ele_type].test(L2);
1297 break;
1298 default:
1299 THROW_MESSAGE("Not implemented");
1300 }
1301 };
1302
1303 std::set<string> fields_list;
1304 for (auto &e : getDataFieldEnts()) {
1305 if (auto ent_data_ptr = e.lock()) {
1306 if (ent_data_ptr->getApproxBase() == AINSWORTH_BERNSTEIN_BEZIER_BASE) {
1307 auto field_name = ent_data_ptr->getName();
1308 if (fields_list.find(field_name) == fields_list.end()) {
1309 auto field_ptr = ent_data_ptr->getFieldRawPtr();
1310 auto space = ent_data_ptr->getSpace();
1311 CHKERR get_nodal_base_data(*dataOnElement[space], field_ptr);
1312 CHKERR get_entity_base_data(*dataOnElement[space], field_ptr, MBEDGE,
1313 ele_type);
1314 if (check_space(space)) {
1315#ifndef NDEBUG
1316 if (ent_data_ptr->getContinuity() != CONTINUOUS)
1317 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1318 "Broken space not implemented");
1319#endif // NDEBUG
1321 -> getValue(gaussPts,
1322 boost::make_shared<EntPolynomialBaseCtx>(
1323 *dataOnElement[space], field_name,
1324 static_cast<FieldSpace>(space), CONTINUOUS,
1326 fields_list.insert(field_name);
1327 }
1328 }
1329 }
1330 }
1331 }
1332
1334};
1335
1338
1339 // Data on elements for proper spaces
1340 for (int space = H1; space != LASTSPACE; ++space) {
1341 dataOnElement[space]->setElementType(type);
1342 derivedDataOnElement[space]->setElementType(type);
1343 }
1344
1346}
1347
1348#define LOG_FUNCTION_NAME_WITH_OP_NAME(OP, CHANNEL, SEV) \
1349 MOFEM_LOG(CHANNEL, SEV) \
1350 << "(Calling user data operator " \
1351 << boost::typeindex::type_id_runtime(OP).pretty_name() << " rowField " \
1352 << (OP).rowFieldName << " colField " << (OP).colFieldName << ") "
1353
1354#define CATCH_OP_ERRORS(OP) \
1355 catch (MoFEMExceptionInitial const &ex) { \
1356 LOG_FUNCTION_NAME_WITH_OP_NAME(OP, "SELF", Sev::error) \
1357 << "in " << PETSC_FUNCTION_NAME; \
1358 return PetscError(PETSC_COMM_SELF, ex.lINE, PETSC_FUNCTION_NAME, __FILE__, \
1359 ex.errorCode, PETSC_ERROR_INITIAL, "%s", ex.what()); \
1360 } \
1361 catch (MoFEMExceptionRepeat const &ex) { \
1362 LOG_FUNCTION_NAME_WITH_OP_NAME(OP, "SELF", Sev::error) \
1363 << "in " << PETSC_FUNCTION_NAME; \
1364 return PetscError(PETSC_COMM_SELF, ex.lINE, PETSC_FUNCTION_NAME, __FILE__, \
1365 ex.errorCode, PETSC_ERROR_REPEAT, " "); \
1366 } \
1367 catch (MoFEMException const &ex) { \
1368 LOG_FUNCTION_NAME_WITH_OP_NAME(OP, "SELF", Sev::error) \
1369 << "in " << PETSC_FUNCTION_NAME; \
1370 SETERRQ(PETSC_COMM_SELF, ex.errorCode, "%s", ex.errorMessage); \
1371 } \
1372 catch (std::exception const &ex) { \
1373 LOG_FUNCTION_NAME_WITH_OP_NAME(OP, "SELF", Sev::error) \
1374 << "\nError: " << ex.what() << " at " << __LINE__ << " : " __FILE__ \
1375 << " in " << PETSC_FUNCTION_NAME; \
1376 SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW, "%s", \
1377 "std::exception"); \
1378 }
1379
1380#ifndef NDEBUG
1381 #define LOG_OP(OP) \
1382 LOG_FUNCTION_NAME_WITH_OP_NAME(OP, "WORLD", Sev::noisy) \
1383 << "\nLocation: at " << __LINE__ << " : " __FILE__ << " in " \
1384 << PETSC_FUNCTION_NAME;
1385#else
1386 #define LOG_OP(OP)
1387#endif
1388
1391
1392 using UDO = UserDataOperator;
1393
1394 std::array<std::string, 2> field_name;
1395 std::array<const Field *, 3> field_struture;
1396 std::array<int, 2>
1397 field_id; // note the this is field bit number (nor field bit)
1398 std::array<FieldSpace, 2> space;
1399 std::array<FieldApproximationBase, 2> base;
1400
1401 constexpr std::array<UDO::OpType, 2> types = {UDO::OPROW, UDO::OPCOL};
1402 std::array<int, 2> last_eval_field_id = {0, 0};
1403
1404 std::array<boost::shared_ptr<EntitiesFieldData>, 2> op_data;
1405
1406 auto swap_bases = [&](auto &op) {
1408 for (size_t ss = 0; ss != 2; ++ss) {
1409 if (op.getOpType() & types[ss] || op.getOpType() & UDO::OPROWCOL) {
1410 switch (base[ss]) {
1412 CHKERR op_data[ss]->baseSwap(field_name[ss],
1414 default:
1415 break;
1416 }
1417 }
1418 }
1419
1421 };
1422
1423 const EntityType type = numeredEntFiniteElementPtr->getEntType();
1424
1425 // evaluate entity data only, no field specific data provided or known
1426 auto evaluate_op_space = [&](auto &op) {
1428
1429 // reseat all data which all field dependent
1430 dataOnElement[op.sPace]->resetFieldDependentData();
1431 std::fill(last_eval_field_id.begin(), last_eval_field_id.end(), 0);
1432
1433 switch (op.sPace) {
1434 case NOSPACE:
1435 LOG_OP(op);
1436 try {
1437 CHKERR op.doWork(
1438 0, MBENTITYSET,
1439 dataOnElement[NOSPACE]->dataOnEntities[MBENTITYSET][0]);
1440 }
1441 CATCH_OP_ERRORS(op);
1442 break;
1443 case NOFIELD:
1444 case H1:
1445 case HCURL:
1446 case HDIV:
1447 case L2:
1448 LOG_OP(op);
1449 try {
1450
1451 for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t) {
1452 for (auto &e : dataOnElement[op.sPace]->dataOnEntities[t]) {
1453 e.getSpace() = op.sPace;
1454 }
1455 }
1456
1457 CHKERR op.opRhs(*dataOnElement[op.sPace], false);
1458 }
1459 CATCH_OP_ERRORS(op);
1460 break;
1461 default:
1462 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
1463 "Not implemented for this space <%s>", FieldSpaceNames[op.sPace]);
1464 }
1465
1467 };
1468
1469 // set entity data
1470 auto set_op_entities_data = [&](auto ss, auto &op) {
1472
1473#ifndef NDEBUG
1474 if ((op.getNumeredEntFiniteElementPtr()->getBitFieldIdData() &
1476 .none()) {
1477 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1478 "no data field < %s > on finite element < %s >",
1479 field_name[ss].c_str(), getFEName().c_str());
1480 }
1481#endif
1482
1483 op_data[ss] =
1484 !ss ? dataOnElement[space[ss]] : derivedDataOnElement[space[ss]];
1485
1486 for (auto &data : op_data[ss]->dataOnEntities[MBENTITYSET]) {
1487 CHKERR data.resetFieldDependentData();
1488 }
1489
1490 auto get_data_for_nodes = [&]() {
1492 if (!ss)
1493 CHKERR getRowNodesIndices(*op_data[ss], field_id[ss]);
1494 else
1495 CHKERR getColNodesIndices(*op_data[ss], field_id[ss]);
1496 CHKERR getNodesFieldData(*op_data[ss], field_id[ss]);
1498 };
1499
1500 // get data on entities but not nodes
1501 auto get_data_for_entities = [&]() {
1503 CHKERR getEntityFieldData(*op_data[ss], field_id[ss], MBEDGE);
1504 if (!ss)
1505 CHKERR getEntityRowIndices(*op_data[ss], field_id[ss], MBEDGE);
1506 else
1507 CHKERR getEntityColIndices(*op_data[ss], field_id[ss], MBEDGE);
1509 };
1510
1511 auto get_data_for_meshset = [&]() {
1513
1514 if (!ss) {
1515
1516 struct Extractor {
1517 boost::weak_ptr<EntityCacheNumeredDofs>
1518 operator()(boost::shared_ptr<FieldEntity> &e) {
1519 return e->entityCacheRowDofs;
1520 }
1521 };
1522
1523 CHKERR getNoFieldEntityFieldData(*op_data[ss], field_id[ss],
1524 Extractor());
1525 } else {
1526
1527 struct Extractor {
1528 boost::weak_ptr<EntityCacheNumeredDofs>
1529 operator()(boost::shared_ptr<FieldEntity> &e) {
1530 return e->entityCacheColDofs;
1531 }
1532 };
1533
1534 CHKERR getNoFieldEntityFieldData(*op_data[ss], field_id[ss],
1535 Extractor());
1536 }
1537
1539 };
1540
1541 switch (space[ss]) {
1542 case H1:
1543 CHKERR get_data_for_nodes();
1544 case HCURL:
1545 case HDIV:
1546 CHKERR get_data_for_entities();
1547 break;
1548 case L2:
1549 switch (type) {
1550 case MBVERTEX:
1551 CHKERR get_data_for_nodes();
1552 break;
1553 default:
1554 CHKERR get_data_for_entities();
1555 }
1556 break;
1557 case NOFIELD:
1558 CHKERR get_data_for_meshset();
1559 break;
1560 default:
1561 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
1562 "not implemented for this space < %s >",
1563 FieldSpaceNames[space[ss]]);
1564 }
1566 };
1567
1568 // evaluate operators with field data
1569 auto evaluate_op_for_fields = [&](auto &op) {
1571
1572 if (op.getOpType() & UDO::OPROW) {
1573 LOG_OP(op);
1574 try {
1575 CHKERR op.opRhs(*op_data[0], false);
1576 }
1577 CATCH_OP_ERRORS(op);
1578 }
1579
1580 if (op.getOpType() & UDO::OPCOL) {
1581 LOG_OP(op);
1582 try {
1583 CHKERR op.opRhs(*op_data[1], false);
1584 }
1585 CATCH_OP_ERRORS(op);
1586 }
1587
1588 if (op.getOpType() & UDO::OPROWCOL) {
1589 LOG_OP(op);
1590 try {
1591 CHKERR op.opLhs(*op_data[0], *op_data[1]);
1592 }
1593 CATCH_OP_ERRORS(op);
1594 }
1596 };
1597
1598 // collect bit ref level on all entities, fields and spaces
1600
1601 auto oit = opPtrVector.begin();
1602 auto hi_oit = opPtrVector.end();
1603
1604 // iterate over all operators on element
1605 for (; oit != hi_oit; oit++) {
1606
1607 LOG_OP(*oit);
1608 try {
1609
1610 CHKERR oit->setPtrFE(this);
1611
1612 if ((oit->opType & UDO::OPSPACE) == UDO::OPSPACE) {
1613
1614 // run operator for space but not specific field, thus inices of fild
1615 // values are not resolved, howvere bases for given space are accessible
1616 CHKERR evaluate_op_space(*oit);
1617
1618 } else if (
1619
1620 (oit->opType & (UDO::OPROW | UDO::OPCOL | UDO::OPROWCOL)) ==
1621 oit->opType
1622
1623 ) {
1624
1625 field_name[0] = oit->rowFieldName;
1626 field_name[1] = oit->colFieldName;
1627
1628 for (size_t ss = 0; ss != 2; ss++) {
1629
1630#ifndef NDEBUG
1631 if (field_name[ss].empty()) {
1632 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1633 "Not set Field name in operator %ld (0-row, 1-column) in "
1634 "operator %s",
1635 ss,
1636 (boost::typeindex::type_id_runtime(*oit).pretty_name())
1637 .c_str());
1638 }
1639#endif
1640
1641 field_struture[ss] = mField.get_field_structure(field_name[ss]);
1642 field_id[ss] = field_struture[ss]->getBitNumber();
1643 space[ss] = field_struture[ss]->getSpace();
1644 base[ss] = field_struture[ss]->getApproxBase();
1645 }
1646
1647 // not that if field name do not change between operators, entity field
1648 // data are nor rebuild
1649 for (size_t ss = 0; ss != 2; ss++) {
1650
1651 if (oit->getOpType() & types[ss] ||
1652 oit->getOpType() & UDO::OPROWCOL) {
1653 if (last_eval_field_id[ss] != field_id[ss]) {
1654 CHKERR set_op_entities_data(ss, *oit);
1655 last_eval_field_id[ss] = field_id[ss];
1656 }
1657 }
1658 }
1659
1660 CHKERR swap_bases(*oit);
1661
1662 // run operator for given field or row, column or both
1663 CHKERR evaluate_op_for_fields(*oit);
1664
1665 CHKERR swap_bases(*oit);
1666
1667 } else {
1668
1669 for (int i = 0; i != 5; ++i)
1670 if (oit->opType & (1 << i))
1671 MOFEM_LOG("SELF", Sev::error) << UDO::OpTypeNames[i];
1672 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1673 "Impossible operator type");
1674 }
1675 }
1676 CATCH_OP_ERRORS(*oit);
1677 }
1679}
1680
1681const char *const ForcesAndSourcesCore::UserDataOperator::OpTypeNames[] = {
1682 "OPROW", " OPCOL", "OPROWCOL", "OPSPACE", "OPLAST"};
1683
1684MoFEMErrorCode ForcesAndSourcesCore::UserDataOperator::getProblemRowIndices(
1685 const std::string field_name, const EntityType type, const int side,
1686 VectorInt &indices) const {
1688 if (ptrFE == NULL)
1689 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
1690
1691 switch (type) {
1692 case MBVERTEX:
1694 break;
1695 default:
1696 CHKERR ptrFE->getProblemTypeRowIndices(field_name, type, side, indices);
1697 }
1699}
1700
1701MoFEMErrorCode ForcesAndSourcesCore::UserDataOperator::getProblemColIndices(
1702 const std::string field_name, const EntityType type, const int side,
1703 VectorInt &indices) const {
1705 if (ptrFE == NULL)
1706 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
1707
1708 switch (type) {
1709 case MBVERTEX:
1710 CHKERR ptrFE->getProblemNodesColIndices(field_name, indices);
1711 break;
1712 default:
1713 CHKERR ptrFE->getProblemTypeColIndices(field_name, type, side, indices);
1714 }
1716}
1717
1724
1731
1732MoFEMErrorCode ForcesAndSourcesCore::UserDataOperator::loopSide(
1733 const string &fe_name, ForcesAndSourcesCore *side_fe, const size_t side_dim,
1734 const EntityHandle ent_for_side, boost::shared_ptr<Range> fe_range,
1735 const int verb, const LogManager::SeverityLevel sev, AdjCache *adj_cache) {
1737
1738 const auto *problem_ptr = getFEMethod()->problemPtr;
1739 auto &numered_fe =
1740 problem_ptr->numeredFiniteElementsPtr->get<Unique_mi_tag>();
1741
1742 auto fe_miit = ptrFE->mField.get_finite_elements()
1744 .find(fe_name);
1745 if (fe_miit != ptrFE->mField.get_finite_elements()
1747 .end()) {
1748
1749 const auto ent = ent_for_side ? ent_for_side : getFEEntityHandle();
1750
1751 side_fe->feName = fe_name;
1752
1753 CHKERR side_fe->setSideFEPtr(ptrFE);
1754 CHKERR side_fe->copyBasicMethod(*getFEMethod());
1755 CHKERR side_fe->copyPetscData(*getFEMethod());
1756 CHKERR side_fe->copyKsp(*getFEMethod());
1757 CHKERR side_fe->copySnes(*getFEMethod());
1758 CHKERR side_fe->copyTs(*getFEMethod());
1759
1760 side_fe->cacheWeakPtr = getFEMethod()->cacheWeakPtr;
1761
1762 CHKERR side_fe->preProcess();
1763
1764 std::vector<boost::weak_ptr<NumeredEntFiniteElement>> fe_vec;
1765 auto get_numered_fe_ptr = [&](auto &fe_uid, Range &&adjacent_ents)
1766 -> std::vector<boost::weak_ptr<NumeredEntFiniteElement>> & {
1767 fe_vec.reserve(adjacent_ents.size());
1768 for (auto fe_ent : adjacent_ents) {
1769 auto miit = numered_fe.find(
1771 if (miit != numered_fe.end()) {
1772 fe_vec.emplace_back(*miit);
1773 }
1774 }
1775 return fe_vec;
1776 };
1777
1778 auto get_bit_entity_adjacency = [&]() {
1779 Range adjacent_ents;
1781 ptrFE->mField.getInterface<BitRefManager>()->getAdjacenciesAny(
1782 ent, side_dim, adjacent_ents),
1783 "getAdjacenciesAny failed");
1784 return adjacent_ents;
1785 };
1786
1787 auto get_bit_meshset_entities = [&]() {
1788 auto &bit = getFEMethod()->numeredEntFiniteElementPtr->getBitRefLevel();
1789 Range ents = *fe_range;
1791 ptrFE->mField.getInterface<BitRefManager>()->filterEntitiesByRefLevel(
1792 bit, BitRefLevel().set(), ents),
1793 "filterEntitiesByRefLevel failed");
1794 return ents;
1795 };
1796
1797 auto get_adj = [&](auto &fe_uid, auto get_adj_fun)
1798 -> std::vector<boost::weak_ptr<NumeredEntFiniteElement>> & {
1799 if (adj_cache) {
1800 try {
1801 return (*adj_cache).at(ent);
1802 } catch (const std::out_of_range &) {
1803 return (*adj_cache)[ent] = get_numered_fe_ptr(fe_uid, get_adj_fun());
1804 }
1805 } else {
1806 return get_numered_fe_ptr(fe_uid, get_adj_fun());
1807 }
1808 };
1809
1810 if (type_from_handle(ent) == MBENTITYSET) {
1811 if (!fe_range)
1812 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1813 "No range of finite elements");
1814 }
1815 auto adj = (!fe_range)
1816 ? get_adj((*fe_miit)->getFEUId(), get_bit_entity_adjacency)
1817 : get_adj((*fe_miit)->getFEUId(), get_bit_meshset_entities);
1818
1819 if (verb >= VERBOSE && !adj.empty())
1820 MOFEM_LOG("SELF", sev) << "Number of side finite elements " << adj.size();
1821
1822 int nn = 0;
1823 side_fe->loopSize = adj.size();
1824 for (auto fe_weak_ptr : adj) {
1825 if (auto fe_ptr = fe_weak_ptr.lock()) {
1826 if (verb >= VERBOSE)
1827 MOFEM_LOG("SELF", sev)
1828 << "Side finite element " << "(" << nn << "): " << *fe_ptr;
1829 side_fe->nInTheLoop = nn;
1830 side_fe->numeredEntFiniteElementPtr = fe_ptr;
1831 CHKERR (*side_fe)();
1832 }
1833 ++nn;
1834 }
1835
1836 CHKERR side_fe->postProcess();
1837 }
1838
1840}
1841
1842MoFEMErrorCode ForcesAndSourcesCore::UserDataOperator::loopThis(
1843 const string &fe_name, ForcesAndSourcesCore *this_fe, const int verb,
1844 const LogManager::SeverityLevel sev) {
1846
1847
1848
1849 auto &fes =
1850 ptrFE->mField.get_finite_elements()->get<FiniteElement_name_mi_tag>();
1851 auto fe_miit = fes.find(fe_name);
1852 if (fe_miit != fes.end()) {
1853
1854 this_fe->feName = fe_name;
1855
1856 CHKERR this_fe->setRefineFEPtr(ptrFE);
1857 CHKERR this_fe->copyBasicMethod(*getFEMethod());
1858 CHKERR this_fe->copyPetscData(*getFEMethod());
1859 CHKERR this_fe->copyKsp(*getFEMethod());
1860 CHKERR this_fe->copySnes(*getFEMethod());
1861 CHKERR this_fe->copyTs(*getFEMethod());
1862
1863 this_fe->cacheWeakPtr = getFEMethod()->cacheWeakPtr;
1864
1865 this_fe->nInTheLoop = getNinTheLoop();
1866 this_fe->loopSize = getLoopSize();
1867
1868 CHKERR this_fe->preProcess();
1869
1870 if (fe_name == getFEName()) {
1871
1872 if (verb >= VERBOSE)
1873 MOFEM_LOG("SELF", sev)
1874 << "This finite element: " << *getNumeredEntFiniteElementPtr();
1875
1876 this_fe->numeredEntFiniteElementPtr = getNumeredEntFiniteElementPtr();
1877 CHKERR (*this_fe)();
1878 } else {
1879
1880 auto get_numered_fe_ptr = [&](auto &fe_uid, auto fe_ent) {
1881 auto &numered_fe =
1882 getFEMethod()
1883 ->problemPtr->numeredFiniteElementsPtr->get<Unique_mi_tag>();
1884 auto it = numered_fe.find(
1886 boost::shared_ptr<const NumeredEntFiniteElement> this_numered_fe_ptr;
1887 if (it != numered_fe.end()) {
1888 this_numered_fe_ptr = *it;
1889 }
1890 return this_numered_fe_ptr;
1891 };
1892
1893 auto this_numered_fe_ptr = get_numered_fe_ptr(
1894 (*fe_miit)->getFEUId(), getNumeredEntFiniteElementPtr()->getEnt());
1895 if (this_numered_fe_ptr) {
1896
1897 if (verb >= VERBOSE)
1898 MOFEM_LOG("SELF", sev)
1899 << "This finite element: " << *this_numered_fe_ptr;
1900
1901 this_fe->numeredEntFiniteElementPtr = this_numered_fe_ptr;
1902 CHKERR (*this_fe)();
1903 }
1904 }
1905 CHKERR this_fe->postProcess();
1906 }
1907
1909}
1910
1911MoFEMErrorCode ForcesAndSourcesCore::UserDataOperator::loopParent(
1912 const string &fe_name, ForcesAndSourcesCore *parent_fe, const int verb,
1913 const LogManager::SeverityLevel sev) {
1915
1916 auto &fes =
1917 ptrFE->mField.get_finite_elements()->get<FiniteElement_name_mi_tag>();
1918 auto fe_miit = fes.find(fe_name);
1919 if (fe_miit != fes.end()) {
1920
1921 const auto *problem_ptr = getFEMethod()->problemPtr;
1922 auto &numered_fe =
1923 problem_ptr->numeredFiniteElementsPtr->get<Unique_mi_tag>();
1924
1925 parent_fe->feName = fe_name;
1926 CHKERR parent_fe->setRefineFEPtr(ptrFE);
1927 CHKERR parent_fe->copyBasicMethod(*getFEMethod());
1928 CHKERR parent_fe->copyPetscData(*getFEMethod());
1929 CHKERR parent_fe->copyKsp(*getFEMethod());
1930 CHKERR parent_fe->copySnes(*getFEMethod());
1931 CHKERR parent_fe->copyTs(*getFEMethod());
1932
1933 parent_fe->cacheWeakPtr = getFEMethod()->cacheWeakPtr;
1934
1935 const auto parent_ent = getNumeredEntFiniteElementPtr()->getParentEnt();
1936 auto miit = numered_fe.find(EntFiniteElement::getLocalUniqueIdCalculate(
1937 parent_ent, (*fe_miit)->getFEUId()));
1938 if (miit != numered_fe.end()) {
1939 if (verb >= VERBOSE)
1940 MOFEM_LOG("SELF", sev) << "Parent finite element: " << **miit;
1941 parent_fe->loopSize = 1;
1942 parent_fe->nInTheLoop = 0;
1943 parent_fe->numeredEntFiniteElementPtr = *miit;
1944 CHKERR parent_fe->preProcess();
1945 CHKERR (*parent_fe)();
1946 CHKERR parent_fe->postProcess();
1947 } else {
1948 if (verb >= VERBOSE)
1949 MOFEM_LOG("SELF", sev) << "Parent finite element: no parent";
1950 parent_fe->loopSize = 0;
1951 parent_fe->nInTheLoop = 0;
1952 CHKERR parent_fe->preProcess();
1953 CHKERR parent_fe->postProcess();
1954 }
1955 }
1956
1958}
1959
1960MoFEMErrorCode ForcesAndSourcesCore::UserDataOperator::loopChildren(
1961 const string &fe_name, ForcesAndSourcesCore *child_fe, const int verb,
1962 const LogManager::SeverityLevel sev) {
1964
1965 auto fe_miit = ptrFE->mField.get_finite_elements()
1967 .find(fe_name);
1968 if (fe_miit != ptrFE->mField.get_finite_elements()
1970 .end()) {
1971
1972 const auto *problem_ptr = getFEMethod()->problemPtr;
1973 auto &ref_ents = *getPtrFE()->mField.get_ref_ents();
1974 auto &numered_fe =
1975 problem_ptr->numeredFiniteElementsPtr->get<Unique_mi_tag>();
1976
1977 const auto parent_ent = getNumeredEntFiniteElementPtr()->getEnt();
1978 const auto parent_type = getNumeredEntFiniteElementPtr()->getEntType();
1979 auto range =
1980 ref_ents.get<Composite_ParentEnt_And_EntType_mi_tag>().equal_range(
1981 boost::make_tuple(parent_type, parent_ent));
1982
1983 if (auto size = std::distance(range.first, range.second)) {
1984
1985 std::vector<EntityHandle> childs_vec;
1986 childs_vec.reserve(size);
1987 for (; range.first != range.second; ++range.first)
1988 childs_vec.emplace_back((*range.first)->getEnt());
1989
1990 Range childs;
1991
1992 if ((childs_vec.back() - childs_vec.front() + 1) == size)
1993 childs = Range(childs_vec.front(), childs_vec.back());
1994 else
1995 childs.insert_list(childs_vec.begin(), childs_vec.end());
1996
1997 child_fe->feName = fe_name;
1998
1999 CHKERR child_fe->setRefineFEPtr(ptrFE);
2000 CHKERR child_fe->copyBasicMethod(*getFEMethod());
2001 CHKERR child_fe->copyPetscData(*getFEMethod());
2002 CHKERR child_fe->copyKsp(*getFEMethod());
2003 CHKERR child_fe->copySnes(*getFEMethod());
2004 CHKERR child_fe->copyTs(*getFEMethod());
2005
2006 child_fe->cacheWeakPtr = getFEMethod()->cacheWeakPtr;
2007
2008 CHKERR child_fe->preProcess();
2009
2010 int nn = 0;
2011 child_fe->loopSize = size;
2012
2013 for (auto p = childs.pair_begin(); p != childs.pair_end(); ++p) {
2014
2015 auto miit =
2016 numered_fe.lower_bound(EntFiniteElement::getLocalUniqueIdCalculate(
2017 p->first, (*fe_miit)->getFEUId()));
2018 auto hi_miit =
2019 numered_fe.upper_bound(EntFiniteElement::getLocalUniqueIdCalculate(
2020 p->second, (*fe_miit)->getFEUId()));
2021
2022 for (; miit != hi_miit; ++miit) {
2023
2024 if (verb >= VERBOSE)
2025 MOFEM_LOG("SELF", sev)
2026 << "Child finite element " << "(" << nn << "): " << **miit;
2027
2028 child_fe->nInTheLoop = nn++;
2029 child_fe->numeredEntFiniteElementPtr = *miit;
2030 CHKERR (*child_fe)();
2031 }
2032 }
2033 }
2034
2035 CHKERR child_fe->postProcess();
2036 }
2037
2039}
2040
2041MoFEMErrorCode ForcesAndSourcesCore::UserDataOperator::loopRange(
2042 const string &fe_name, ForcesAndSourcesCore *range_fe,
2043 boost::shared_ptr<Range> fe_range, const int verb,
2044 const LogManager::SeverityLevel sev) {
2046
2047 auto &fes =
2048 ptrFE->mField.get_finite_elements()->get<FiniteElement_name_mi_tag>();
2049 auto fe_miit = fes.find(fe_name);
2050 if (fe_miit != fes.end()) {
2051
2052 const auto *problem_ptr = getFEMethod()->problemPtr;
2053 auto &numered_fe =
2054 problem_ptr->numeredFiniteElementsPtr->get<Unique_mi_tag>();
2055
2056 range_fe->feName = fe_name;
2057 CHKERR range_fe->setRefineFEPtr(ptrFE);
2058 CHKERR range_fe->copyBasicMethod(*getFEMethod());
2059 CHKERR range_fe->copyPetscData(*getFEMethod());
2060 CHKERR range_fe->copyKsp(*getFEMethod());
2061 CHKERR range_fe->copySnes(*getFEMethod());
2062 CHKERR range_fe->copyTs(*getFEMethod());
2063
2064 range_fe->cacheWeakPtr = getFEMethod()->cacheWeakPtr;
2065
2066 auto get_numered_fe_ptr = [&](auto &fe_uid, auto fe_range, auto execute) {
2068 if (fe_range) {
2069 int nn = 0;
2070 for (auto p = fe_range->pair_begin(); p != fe_range->pair_end(); ++p) {
2071 auto first = p->first;
2072 auto second = p->second;
2073 auto lo = numered_fe.lower_bound(
2075 auto hi = numered_fe.upper_bound(
2077 for (; lo != hi; ++lo) {
2078 CHKERR execute(lo, nn++);
2079 }
2080 }
2081 }
2083 };
2084
2085 auto execute = [&](auto lo, auto nn) {
2087 if (verb >= VERBOSE)
2088 MOFEM_LOG("SELF", sev) << "Range finite element: " << **lo;
2089 range_fe->nInTheLoop = nn;
2090 range_fe->numeredEntFiniteElementPtr = *lo;
2091 CHKERR range_fe->preProcess();
2092 CHKERR (*range_fe)();
2093 CHKERR range_fe->postProcess();
2095 };
2096
2097 CHKERR get_numered_fe_ptr((*fe_miit)->getFEUId(), fe_range, execute);
2098 }
2099
2101}
2102
2103int ForcesAndSourcesCore::getRule(int order_row, int order_col,
2104 int order_data) {
2105 return getRuleHook ? getRuleHook(order_row, order_col, order_data)
2106 : getRule(order_data);
2107}
2108
2110 int order_data) {
2111 return setRuleHook ? setRuleHook(this, order_row, order_col, order_data)
2112 : setGaussPts(order_data);
2113}
2114
2116
2117/** \deprecated setGaussPts(int row_order, int col_order, int data order);
2118 */
2121 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Sorry, not implemented");
2123}
2124
2125ForcesAndSourcesCore::UserDataOperator::UserDataOperator(const FieldSpace space,
2126 const char type,
2127 const bool symm)
2128 : DataOperator(symm), opType(type), sPace(space), ptrFE(nullptr) {}
2129
2130ForcesAndSourcesCore::UserDataOperator::UserDataOperator(
2131 const std::string field_name, const char type, const bool symm)
2132 : DataOperator(symm), opType(type), rowFieldName(field_name),
2133 colFieldName(field_name), sPace(LASTSPACE), ptrFE(nullptr) {}
2134
2135ForcesAndSourcesCore::UserDataOperator::UserDataOperator(
2136 const std::string row_field_name, const std::string col_field_name,
2137 const char type, const bool symm)
2138 : DataOperator(symm), opType(type), rowFieldName(row_field_name),
2139 colFieldName(col_field_name), sPace(LASTSPACE), ptrFE(nullptr) {}
2140
2151 if (operatorHook) {
2152 ierr = operatorHook();
2153 CHKERRG(ierr);
2154 } else {
2155#ifndef NDEBUG
2156 MOFEM_LOG("SELF", Sev::warning)
2157 << "No method operator() overloaded on element entity on finite "
2158 "element <"
2159 << boost::typeindex::type_id_runtime(*this).pretty_name() << ">";
2160#endif
2161 }
2163}
2172
2174ForcesAndSourcesCore::UserDataOperator::setPtrFE(ForcesAndSourcesCore *ptr) {
2176 if (!(ptrFE = dynamic_cast<ForcesAndSourcesCore *>(ptr)))
2177 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2178 "User operator and finite element do not work together");
2180}
2181
2182} // namespace MoFEM
#define CATCH_OP_ERRORS(OP)
#define LOG_OP(OP)
constexpr double a
@ VERBOSE
FieldApproximationBase
approximation base
Definition definitions.h:58
@ LASTBASE
Definition definitions.h:69
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base nme:nme847.
Definition definitions.h:60
@ USER_BASE
user implemented approximation base
Definition definitions.h:68
@ NOBASE
Definition definitions.h:59
@ AINSWORTH_BERNSTEIN_BEZIER_BASE
Definition definitions.h:64
#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
@ LASTSPACE
FieldSpace in [ 0, LASTSPACE )
Definition definitions.h:89
@ NOFIELD
scalar or vector of scalars describe (no true field)
Definition definitions.h:84
@ H1
continuous field
Definition definitions.h:85
@ NOSPACE
Definition definitions.h:83
@ HCURL
field with continuous tangents
Definition definitions.h:86
@ HDIV
field with continuous normal traction
Definition definitions.h:87
FieldContinuity
Field continuity.
Definition definitions.h:99
@ CONTINUOUS
Regular field.
@ DISCONTINUOUS
Broken continuity (No effect on L2 space)
static const char *const FieldSpaceNames[]
Definition definitions.h:92
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHKERRG(n)
Check error code of MoFEM/MOAB/PETSc function.
@ 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 ...
#define THROW_MESSAGE(msg)
Throw MoFEM exception.
constexpr int order
multi_index_container< boost::shared_ptr< NumeredDofEntity >, indexed_by< ordered_unique< tag< Unique_mi_tag >, const_mem_fun< NumeredDofEntity::interface_type_DofEntity, UId, &NumeredDofEntity::getLocalUniqueId > >, ordered_non_unique< tag< Part_mi_tag >, member< NumeredDofEntity, unsigned int, &NumeredDofEntity::pArt > >, ordered_non_unique< tag< Idx_mi_tag >, member< NumeredDofEntity, DofIdx, &NumeredDofEntity::dofIdx > >, ordered_non_unique< tag< PetscGlobalIdx_mi_tag >, member< NumeredDofEntity, DofIdx, &NumeredDofEntity::petscGloablDofIdx > >, ordered_non_unique< tag< PetscLocalIdx_mi_tag >, member< NumeredDofEntity, DofIdx, &NumeredDofEntity::petscLocalDofIdx > >, ordered_non_unique< tag< Ent_mi_tag >, const_mem_fun< NumeredDofEntity::interface_type_DofEntity, EntityHandle, &NumeredDofEntity::getEnt > > > > NumeredDofEntity_multiIndex
MultiIndex container keeps NumeredDofEntity.
multi_index_container< boost::shared_ptr< SideNumber >, indexed_by< ordered_unique< member< SideNumber, EntityHandle, &SideNumber::ent > >, ordered_non_unique< composite_key< SideNumber, const_mem_fun< SideNumber, EntityType, &SideNumber::getEntType >, member< SideNumber, signed char, &SideNumber::side_number > > > > > SideNumber_multiIndex
SideNumber_multiIndex for SideNumber.
virtual MoFEMErrorCode getAdjacenciesAny(const EntityHandle from_entity, const int to_dimension, Range &adj_entities) const
Get the adjacencies associated with a entity to entities of a specified dimension.
virtual const Field * get_field_structure(const std::string &name, enum MoFEMTypes bh=MF_EXIST) const =0
get field structure
#define MOFEM_LOG(channel, severity)
Log.
SeverityLevel
Severity levels.
auto bit
set bit
FTensor::Index< 'i', SPACE_DIM > i
const double n
refractive index of diffusive medium
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
std::bitset< BITFEID_SIZE > BitFEId
Finite element Id.
Definition Types.hpp:43
int ApproximationOrder
Approximation on the entity.
Definition Types.hpp:26
std::bitset< BITFIELDID_SIZE > BitFieldId
Field Id.
Definition Types.hpp:42
uint128_t UId
Unique Id.
Definition Types.hpp:31
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition Types.hpp:40
UBlasVector< int > VectorInt
Definition Types.hpp:67
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto type_from_handle(const EntityHandle h)
get type from entity handle
static MoFEMErrorCode get_value(MatrixDouble &pts_x, MatrixDouble &pts_t, TYPE *ctx)
static auto cmp_uid_lo(const boost::weak_ptr< FieldEntity > &a, const UId &b)
EntityHandle get_id_for_max_type()
static auto cmp_uid_hi(const UId &b, const boost::weak_ptr< FieldEntity > &a)
EntityHandle get_id_for_min_type()
std::vector< boost::weak_ptr< FieldEntity > > FieldEntity_vector_view
Field_multiIndex::index< FieldName_mi_tag >::type::iterator field_it
ublas::vector< FieldEntity *, FieldEntAllocator > VectorFieldEntities
ublas::vector< FEDofEntity *, DofsAllocator > VectorDofs
static int getMaxOrder(const ENTMULTIINDEX &multi_index)
constexpr double t
plate stiffness
Definition plate.cpp:58
constexpr auto field_name
int loopSize
local number oe methods to process
MoFEMErrorCode copyBasicMethod(const BasicMethod &basic)
Copy data from other base method to this base method.
int getLoopSize() const
get loop size
boost::function< MoFEMErrorCode()> preProcessHook
Hook function for pre-processing.
const Field_multiIndex * fieldsPtr
raw pointer to fields container
int nInTheLoop
number currently of processed method
const Problem * problemPtr
raw pointer to problem
boost::function< MoFEMErrorCode()> operatorHook
Hook function for operator.
boost::weak_ptr< CacheTuple > cacheWeakPtr
int getNinTheLoop() const
get number of evaluated element in the loop
boost::function< MoFEMErrorCode()> postProcessHook
Hook function for post-processing.
Managing BitRefLevels.
MoFEMErrorCode filterEntitiesByRefLevel(const BitRefLevel bit, const BitRefLevel mask, Range &ents, int verb=QUIET) const
filter entities by bit ref level
virtual FieldBitNumber get_field_bit_number(const std::string name) const =0
get field bit number
virtual moab::Interface & get_moab()=0
virtual BitFieldId get_field_id(const std::string &name) const =0
Get field Id.
base operator to do operations at Gauss Pt. level
static bool getDefTypeMap(const EntityType fe_type, const EntityType ent_type)
Deprecated interface functions.
this class derive data form other data structure
UId getLocalUniqueIdCalculate() const
Generate UId for finite element entity.
Data on single entity (This is passed as argument to DataOperator::doWork)
data structure for finite element entity
MatrixInt facesNodes
nodes on finite element faces
std::array< std::bitset< LASTSPACE >, MBMAXTYPE > spacesOnEntities
spaces on entity types
std::bitset< LASTBASE > bAse
bases on element
std::array< boost::ptr_vector< EntData >, MBMAXTYPE > dataOnEntities
std::array< std::bitset< LASTBASE >, LASTSPACE > basesOnSpaces
base on spaces
std::array< std::bitset< LASTBASE >, LASTSPACE > brokenBasesOnSpaces
base on spaces
MatrixInt facesNodesOrder
order of face nodes on element
std::array< std::bitset< LASTBASE >, MBMAXTYPE > basesOnEntities
bases on entity types
keeps information about indexed dofs for the finite element
std::string feName
Name of finite element.
auto & getRowFieldEnts() const
auto getFEName() const
get finite element name
const FieldEntity_vector_view & getDataFieldEnts() const
boost::shared_ptr< FieldEntity_vector_view > & getDataFieldEntsPtr() const
EntityHandle getFEEntityHandle() const
auto getNumberOfNodes() const
boost::shared_ptr< const NumeredEntFiniteElement > numeredEntFiniteElementPtr
auto & getColFieldEnts() const
UId getLocalUniqueIdCalculate()
Get the Local Unique Id Calculate object.
static UId getLoLocalEntityBitNumber(const char bit_number, const EntityHandle ent)
static UId getHiLocalEntityBitNumber(const char bit_number, const EntityHandle ent)
Provide data structure for (tensor) field approximation.
FieldCoefficientsNumber getNbOfCoeffs() const
Get number of field coefficients.
FieldSpace getSpace() const
Get field approximation space.
FieldBitNumber getBitNumber() const
Get number of set bit in Field ID. Each field has uid, get getBitNumber get number of bit set for giv...
std::map< EntityHandle, std::vector< boost::weak_ptr< NumeredEntFiniteElement > > > AdjCache
structure to get information form mofem into EntitiesFieldData
MoFEMErrorCode loopOverOperators()
Iterate user data operators.
MoFEMErrorCode getProblemNodesRowIndices(const std::string &field_name, VectorInt &nodes_indices) const
MoFEMErrorCode getEntityIndices(EntitiesFieldData &data, const int bit_number, FieldEntity_vector_view &ents_field, const EntityType type_lo, const EntityType type_hi, EXTRACTOR &&extractor) const
MoFEMErrorCode getEntityRowIndices(EntitiesFieldData &data, const int bit_number, const EntityType type_lo=MBVERTEX, const EntityType type_hi=MBPOLYHEDRON) const
MoFEMErrorCode getRowNodesIndices(EntitiesFieldData &data, const int bit_number) const
get row node indices from FENumeredDofEntity_multiIndex
int getMaxRowOrder() const
Get max order of approximation for field in rows.
auto & getUserPolynomialBase()
Get the User Polynomial Base object.
MoFEMErrorCode getSpacesAndBaseOnEntities(EntitiesFieldData &data) const
Get field approximation space and base on entities.
MoFEMErrorCode getProblemTypeColIndices(const std::string &field_name, EntityType type, int side_number, VectorInt &indices) const
virtual MoFEMErrorCode operator()()
function is run for every finite element
MoFEMErrorCode getFaceNodes(EntitiesFieldData &data) const
Get nodes on faces.
const std::array< boost::shared_ptr< EntitiesFieldData >, LASTSPACE > derivedDataOnElement
Entity data on element entity columns fields.
virtual MoFEMErrorCode setGaussPts(int order_row, int order_col, int order_data)
set user specific integration rule
MoFEMErrorCode getNodesIndices(const int bit_number, FieldEntity_vector_view &ents_field, VectorInt &nodes_indices, VectorInt &local_nodes_indices, EXTRACTOR &&extractor) const
get node indices
MoFEMErrorCode getEntityFieldData(EntitiesFieldData &data, const int bit_number, const EntityType type_lo=MBVERTEX, const EntityType type_hi=MBPOLYHEDRON) const
MoFEMErrorCode setRefineFEPtr(const ForcesAndSourcesCore *refine_fe_ptr)
Set the pointer to face element refined.
auto & getElementPolynomialBase()
Get the Entity Polynomial Base object.
ForcesAndSourcesCore * sidePtrFE
Element to integrate on the sides.
ForcesAndSourcesCore(Interface &m_field)
virtual int getRule(int order_row, int order_col, int order_data)
another variant of getRule
boost::ptr_deque< UserDataOperator > opPtrVector
Vector of finite element users data operators.
MoFEMErrorCode getEntitySense(const EntityType type, boost::ptr_vector< EntitiesFieldData::EntData > &data) const
get sense (orientation) of entity
const std::array< boost::shared_ptr< EntitiesFieldData >, LASTSPACE > dataOnElement
Entity data on element entity rows fields.
MoFEMErrorCode getProblemNodesColIndices(const std::string &field_name, VectorInt &nodes_indices) const
MoFEMErrorCode getNoFieldEntityFieldData(EntitiesFieldData &data, const int bit_number, EXTRACTOR &&extractor) const
Get field data on entities where no field is defined.
MoFEMErrorCode calHierarchicalBaseFunctionsOnElement()
Calculate base functions.
MatrixDouble gaussPts
Matrix of integration points.
MoFEMErrorCode calBernsteinBezierBaseFunctionsOnElement()
Calculate Bernstein-Bezier base.
virtual MoFEMErrorCode preProcess()
function is run at the beginning of loop
MoFEMErrorCode getColNodesIndices(EntitiesFieldData &data, const int bit_number) const
get col node indices from FENumeredDofEntity_multiIndex
MoFEMErrorCode setSideFEPtr(const ForcesAndSourcesCore *side_fe_ptr)
Set the pointer to face element on the side.
int getMaxColOrder() const
Get max order of approximation for field in columns.
MoFEMErrorCode getProblemNodesIndices(const std::string &field_name, const NumeredDofEntity_multiIndex &dofs, VectorInt &nodes_indices) const
get indices of nodal indices which are declared for problem but not this particular element
GaussHookFun setRuleHook
Set function to calculate integration rule.
MoFEMErrorCode getNodesFieldData(EntitiesFieldData &data, const int bit_number) const
Get data on nodes.
MoFEMErrorCode getEntityColIndices(EntitiesFieldData &data, const int bit_number, const EntityType type_lo=MBVERTEX, const EntityType type_hi=MBPOLYHEDRON) const
MoFEMErrorCode getEntityDataOrder(const EntityType type, const FieldSpace space, boost::ptr_vector< EntitiesFieldData::EntData > &data) const
Get the entity data order.
ForcesAndSourcesCore * refinePtrFE
Element to integrate parent or child.
int getMaxDataOrder() const
Get max order of approximation for data fields.
MoFEMErrorCode getProblemTypeRowIndices(const std::string &field_name, EntityType type, int side_number, VectorInt &indices) const
MoFEMErrorCode getProblemTypeIndices(const std::string &field_name, const NumeredDofEntity_multiIndex &dofs, EntityType type, int side_number, VectorInt &indices) const
get indices by type (generic function) which are declared for problem but not this particular element
RuleHookFun getRuleHook
Hook to get rule.
MoFEMErrorCode createDataOnElement(EntityType type)
Create a entity data on element object.
virtual MoFEMErrorCode postProcess()
function is run at the end of loop
MoFEMErrorCode copyKsp(const KspMethod &ksp)
copy data form another method
MoFEMErrorCode copyPetscData(const PetscData &petsc_data)
boost::shared_ptr< NumeredDofEntity_multiIndex > numeredRowDofsPtr
store DOFs on rows for this problem
boost::shared_ptr< NumeredDofEntity_multiIndex > numeredColDofsPtr
store DOFs on columns for this problem
MoFEMErrorCode copySnes(const SnesMethod &snes)
Copy snes data.
MoFEMErrorCode copyTs(const TSMethod &ts)
Copy TS solver data.