v0.9.1
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 
7 /* This file is part of MoFEM.
8  * MoFEM is free software: you can redistribute it and/or modify it under
9  * the terms of the GNU Lesser General Public License as published by the
10  * Free Software Foundation, either version 3 of the License, or (at your
11  * option) any later version.
12  *
13  * MoFEM is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  * License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with MoFEM. If not, see <http://www.gnu.org/licenses/>. */
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 #include <cblas.h>
25 #include <lapack_wrap.h>
26 // #include <gm_rule.h>
27 #ifdef __cplusplus
28 }
29 #endif
30 
31 namespace MoFEM {
32 
34  :
35 
36  mField(m_field), getRuleHook(0), setRuleHook(0),
37  dataOnElement{
38 
39  nullptr,
40  boost::make_shared<DataForcesAndSourcesCore>(MBENTITYSET), // NOFIELD
41  boost::make_shared<DataForcesAndSourcesCore>(MBENTITYSET), // H1
42  boost::make_shared<DataForcesAndSourcesCore>(MBENTITYSET), // HCURL
43  boost::make_shared<DataForcesAndSourcesCore>(MBENTITYSET), // HDIV
44  boost::make_shared<DataForcesAndSourcesCore>(MBENTITYSET) // L2
45 
46  },
47  derivedDataOnElement{
48 
49  nullptr,
50  boost::make_shared<DerivedDataForcesAndSourcesCore>(
51  dataOnElement[NOFIELD]), // NOFIELD
52  boost::make_shared<DerivedDataForcesAndSourcesCore>(
53  dataOnElement[H1]), // H1
54  boost::make_shared<DerivedDataForcesAndSourcesCore>(
55  dataOnElement[HCURL]), // HCURL
56  boost::make_shared<DerivedDataForcesAndSourcesCore>(
57  dataOnElement[HDIV]), // HDIV
58  boost::make_shared<DerivedDataForcesAndSourcesCore>(
59  dataOnElement[L2]) // L2
60 
61  },
62  dataNoField(*dataOnElement[NOFIELD].get()),
63  dataH1(*dataOnElement[H1].get()), dataHcurl(*dataOnElement[HCURL].get()),
64  dataHdiv(*dataOnElement[HDIV].get()), dataL2(*dataOnElement[L2].get()),
65  lastEvaluatedElementEntityType(MBMAXTYPE), sidePtrFE(nullptr) {}
66 
69 
71  switch (mField.get_moab().type_from_handle(ent)) {
72  case MBVERTEX:
73  num_nodes = 1;
74  break;
75  case MBEDGE:
76  num_nodes = 2;
77  break;
78  case MBTRI:
79  num_nodes = 3;
80  break;
81  case MBQUAD:
82  num_nodes = 4;
83  break;
84  case MBTET:
85  num_nodes = 4;
86  break;
87  case MBPRISM:
88  num_nodes = 6;
89  break;
90  default:
91  SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "not implemented");
92  }
93 
95 }
96 
97 // ** Sense **
98 
100  const EntityType type,
101  boost::ptr_vector<DataForcesAndSourcesCore::EntData> &data) const {
103 
104  auto &side_table = numeredEntFiniteElementPtr->getSideNumberTable().get<2>();
105  for (auto r = side_table.equal_range(type); r.first != r.second; ++r.first) {
106  const int side_number = (*r.first)->side_number;
107  if (side_number >= 0) {
108  const int brother_side_number = (*r.first)->brother_side_number;
109  const int sense = (*r.first)->sense;
110 
111  data[side_number].getSense() = sense;
112  if (brother_side_number != -1)
113  data[brother_side_number].getSense() = sense;
114  }
115  }
117 }
118 
119 // ** Order **
120 
121 template <typename ENTMULTIINDEX>
122 static inline int getMaxOrder(const ENTMULTIINDEX &multi_index) {
123  int max_order = 0;
124  for (auto ent_field_weak_ptr : multi_index)
125  if (auto e = ent_field_weak_ptr.lock()) {
126  const int order = e->getMaxOrder();
127  max_order = (max_order < order) ? order : max_order;
128  }
129  return max_order;
130 }
131 
133  int max_order = 0;
134  for (auto e : *dataFieldEntsPtr) {
135  const int order = e->getMaxOrder();
136  max_order = (max_order < order) ? order : max_order;
137  }
138  return max_order;
139 }
140 
142  return getMaxOrder(*rowFieldEntsPtr);
143 }
144 
146  return getMaxOrder(*colFieldEntsPtr);
147 }
148 
150  const EntityType type, const FieldSpace space,
151  boost::ptr_vector<DataForcesAndSourcesCore::EntData> &data) const {
153 
154  auto &side_table = numeredEntFiniteElementPtr->getSideNumberTable();
155 
156  for (unsigned int s = 0; s != data.size(); ++s)
157  data[s].getDataOrder() = 0;
158 
159  auto &fields_ents =
161 
162  for (auto r = fields_ents.equal_range(boost::make_tuple(type, space));
163  r.first != r.second; ++r.first) {
164 
165  auto &e = **r.first;
166 
167  auto sit = side_table.find(e.getEnt());
168  if (sit != side_table.end()) {
169 
170  auto &side = *sit;
171  const int side_number = side->side_number;
172  if (side_number >= 0) {
173  ApproximationOrder ent_order = e.getMaxOrder();
174  auto &dat = data[side_number];
175  dat.getDataOrder() =
176  dat.getDataOrder() > ent_order ? dat.getDataOrder() : ent_order;
177  }
178  } else
179  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
180  "Entity on side of the element not found");
181  }
182 
183  for (auto r = side_table.get<2>().equal_range(type); r.first != r.second;
184  ++r.first) {
185  const int brother_side_number = (*r.first)->brother_side_number;
186  if (brother_side_number != -1) {
187  const int side_number = (*r.first)->side_number;
188  data[brother_side_number].getDataOrder() =
189  data[side_number].getDataOrder();
190  }
191  }
192 
194 }
195 
196 // ** Indices **
197 
199  const boost::string_ref field_name, FENumeredDofEntity_multiIndex &dofs,
200  VectorInt &nodes_indices, VectorInt &local_nodes_indices) const {
202  auto &dofs_by_type = dofs.get<Composite_Name_And_Type_mi_tag>();
203  auto tuple = boost::make_tuple(field_name, MBVERTEX);
204  auto dit = dofs_by_type.lower_bound(tuple);
205  auto hi_dit = dofs_by_type.upper_bound(tuple);
206 
207  if (dit != hi_dit) {
208 
209  int num_nodes;
210  CHKERR getNumberOfNodes(num_nodes);
211  int max_nb_dofs = 0;
212  const int nb_dofs_on_vert = (*dit)->getNbOfCoeffs();
213  max_nb_dofs = nb_dofs_on_vert * num_nodes;
214  nodes_indices.resize(max_nb_dofs, false);
215  local_nodes_indices.resize(max_nb_dofs, false);
216  if (std::distance(dit, hi_dit) != max_nb_dofs) {
217  std::fill(nodes_indices.begin(), nodes_indices.end(), -1);
218  std::fill(local_nodes_indices.begin(), local_nodes_indices.end(), -1);
219  }
220 
221  for (; dit != hi_dit; dit++) {
222  auto &dof = **dit;
223  const int idx = dof.getPetscGlobalDofIdx();
224  const int local_idx = dof.getPetscLocalDofIdx();
225  const int side_number = dof.sideNumberPtr->side_number;
226  const int pos = side_number * nb_dofs_on_vert + dof.getDofCoeffIdx();
227  nodes_indices[pos] = idx;
228  local_nodes_indices[pos] = local_idx;
229  const int brother_side_number =
230  (*dit)->sideNumberPtr->brother_side_number;
231  if (brother_side_number != -1) {
232  const int elem_idx =
233  brother_side_number * nb_dofs_on_vert + (*dit)->getDofCoeffIdx();
234  nodes_indices[elem_idx] = idx;
235  local_nodes_indices[elem_idx] = local_idx;
236  }
237  }
238 
239  } else {
240  nodes_indices.resize(0, false);
241  local_nodes_indices.resize(0, false);
242  }
243 
245 }
246 
249  const std::string &field_name) const {
250  return getNodesIndices(field_name,
251  const_cast<FENumeredDofEntity_multiIndex &>(
252  numeredEntFiniteElementPtr->getRowsDofs()),
253  data.dataOnEntities[MBVERTEX][0].getIndices(),
254  data.dataOnEntities[MBVERTEX][0].getLocalIndices());
255 }
256 
259  const std::string &field_name) const {
260  return getNodesIndices(field_name,
261  const_cast<FENumeredDofEntity_multiIndex &>(
262  numeredEntFiniteElementPtr->getColsDofs()),
263  data.dataOnEntities[MBVERTEX][0].getIndices(),
264  data.dataOnEntities[MBVERTEX][0].getLocalIndices());
265 }
266 
268  DataForcesAndSourcesCore &data, const std::string &field_name,
269  FENumeredDofEntity_multiIndex &dofs, const EntityType type_lo,
270  const EntityType type_hi) const {
272 
273  for (EntityType t = type_lo; t != type_hi; ++t) {
274  for (auto &dat : data.dataOnEntities[t]) {
275  dat.getIndices().resize(0, false);
276  dat.getLocalIndices().resize(0, false);
277  }
278  }
279 
280  auto &dofs_by_type = dofs.get<Composite_Name_And_Type_mi_tag>();
281  auto dit = dofs_by_type.lower_bound(boost::make_tuple(field_name, type_lo));
282  if (dit == dofs_by_type.end())
284  auto hi_dit =
285  dofs_by_type.lower_bound(boost::make_tuple(field_name, type_hi));
286  for (; dit != hi_dit; ++dit) {
287  auto &dof = **dit;
288  const EntityType type = dof.getEntType();
289  const int side = dof.sideNumberPtr->side_number;
290 
291  if (side >= 0) {
292 
293  auto &dat = data.dataOnEntities[type][side];
294  const int nb_dofs_on_ent = dof.getNbDofsOnEnt();
295  if (nb_dofs_on_ent) {
296  const int brother_side = dof.sideNumberPtr->brother_side_number;
297  auto &ent_field_indices = dat.getIndices();
298  auto &ent_field_local_indices = dat.getLocalIndices();
299  if (ent_field_indices.empty()) {
300  ent_field_indices.resize(nb_dofs_on_ent, false);
301  ent_field_local_indices.resize(nb_dofs_on_ent, false);
302  std::fill(ent_field_indices.data().begin(),
303  ent_field_indices.data().end(), -1);
304  std::fill(ent_field_local_indices.data().begin(),
305  ent_field_local_indices.data().end(), -1);
306  }
307  const int idx = dof.getEntDofIdx();
308  ent_field_indices[idx] = dof.getPetscGlobalDofIdx();
309  ent_field_local_indices[idx] = dof.getPetscLocalDofIdx();
310  if (brother_side != -1) {
311  auto &dat_brother = data.dataOnEntities[type][brother_side];
312  dat_brother.getIndices().resize(nb_dofs_on_ent, false);
313  dat_brother.getLocalIndices().resize(nb_dofs_on_ent, false);
314  dat_brother.getIndices()[idx] = dat.getIndices()[idx];
315  dat_brother.getLocalIndices()[idx] = dat.getLocalIndices()[idx];
316  }
317  }
318 
319  }
320  }
321 
323 }
324 
326 ForcesAndSourcesCore::getNoFieldIndices(const std::string &field_name,
328  VectorInt &indices) const {
330  auto dit = dofs.get<FieldName_mi_tag>().lower_bound(field_name);
331  auto hi_dit = dofs.get<FieldName_mi_tag>().upper_bound(field_name);
332  indices.resize(std::distance(dit, hi_dit));
333  for (; dit != hi_dit; dit++) {
334  int idx = (*dit)->getPetscGlobalDofIdx();
335  indices[(*dit)->getDofCoeffIdx()] = idx;
336  }
338 }
339 
341  DataForcesAndSourcesCore &data, const std::string &field_name) const {
343  if (data.dataOnEntities[MBENTITYSET].size() == 0) {
344  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
345  }
346  CHKERR getNoFieldIndices(field_name,
347  const_cast<FENumeredDofEntity_multiIndex &>(
348  numeredEntFiniteElementPtr->getRowsDofs()),
349  data.dataOnEntities[MBENTITYSET][0].getIndices());
351 }
352 
354  DataForcesAndSourcesCore &data, const std::string &field_name) const {
356  if (data.dataOnEntities[MBENTITYSET].size() == 0) {
357  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
358  }
359  CHKERR getNoFieldIndices(field_name,
360  const_cast<FENumeredDofEntity_multiIndex &>(
361  numeredEntFiniteElementPtr->getColsDofs()),
362  data.dataOnEntities[MBENTITYSET][0].getIndices());
364 }
365 
366 // ** Indices from problem **
367 
369  const std::string &field_name, const NumeredDofEntity_multiIndex &dofs,
370  VectorInt &nodes_indices) const {
372 
373  const Field *field_struture = mField.get_field_structure(field_name);
374  if (field_struture->getSpace() == H1) {
375 
376  int num_nodes;
377  CHKERR getNumberOfNodes(num_nodes);
378  nodes_indices.resize(field_struture->getNbOfCoeffs() * num_nodes, false);
379  std::fill(nodes_indices.begin(), nodes_indices.end(), -1);
380 
381  auto &side_table = const_cast<SideNumber_multiIndex &>(
382  numeredEntFiniteElementPtr->getSideNumberTable());
383  auto siit = side_table.get<1>().lower_bound(boost::make_tuple(MBVERTEX, 0));
384  auto hi_siit =
385  side_table.get<1>().lower_bound(boost::make_tuple(MBVERTEX, 10000));
386 
387  int nn = 0;
388  for (; siit != hi_siit; siit++, nn++) {
389 
390  if (siit->get()->side_number == -1)
391  continue;
392 
393  const EntityHandle ent = siit->get()->ent;
394  auto dit =
395  dofs.get<Composite_Name_And_Ent_And_EntDofIdx_mi_tag>().lower_bound(
396  boost::make_tuple(field_name, ent, 0));
397  auto hi_dit =
398  dofs.get<Composite_Name_And_Ent_And_EntDofIdx_mi_tag>().upper_bound(
399  boost::make_tuple(field_name, ent, 10000)); /// very large number
400  for (; dit != hi_dit; dit++) {
401  nodes_indices[siit->get()->side_number * (*dit)->getNbOfCoeffs() +
402  (*dit)->getDofCoeffIdx()] =
403  (*dit)->getPetscGlobalDofIdx();
404  }
405  }
406  } else {
407  nodes_indices.resize(0, false);
408  }
409 
410 
412 }
413 
415  const std::string &field_name, const NumeredDofEntity_multiIndex &dofs,
416  EntityType type, int side_number, VectorInt &indices) const {
418 
419  indices.resize(0);
420 
421  auto &side_table = const_cast<SideNumber_multiIndex &>(
422  numeredEntFiniteElementPtr->getSideNumberTable());
423  auto siit =
424  side_table.get<1>().lower_bound(boost::make_tuple(type, side_number));
425  auto hi_siit =
426  side_table.get<1>().upper_bound(boost::make_tuple(type, side_number));
427 
428  for (; siit != hi_siit; siit++) {
429 
430  if (siit->get()->side_number == -1)
431  continue;
432 
433  const EntityHandle ent = siit->get()->ent;
434  NumeredDofEntity_multiIndex::index<
435  Composite_Name_And_Ent_And_EntDofIdx_mi_tag>::type::iterator dit,
436  hi_dit;
437  dit = dofs.get<Composite_Name_And_Ent_And_EntDofIdx_mi_tag>().lower_bound(
438  boost::make_tuple(field_name, ent, 0));
439  hi_dit =
440  dofs.get<Composite_Name_And_Ent_And_EntDofIdx_mi_tag>().upper_bound(
441  boost::make_tuple(field_name, ent, 10000)); /// very large number
442 
443  indices.resize(std::distance(dit, hi_dit));
444  for (; dit != hi_dit; dit++) {
445 
446  indices[(*dit)->getEntDofIdx()] = (*dit)->getPetscGlobalDofIdx();
447  }
448  }
449 
451 }
452 
454  const std::string &field_name, VectorInt &nodes_indices) const {
455  return getProblemNodesIndices(field_name, *(problemPtr->numeredDofsRows),
456  nodes_indices);
457 }
458 
461  EntityType type, int side_number,
462  VectorInt &indices) const {
463  return getProblemTypeIndices(field_name, *(problemPtr->numeredDofsRows), type,
464  side_number, indices);
465 }
466 
468  const std::string &field_name, VectorInt &nodes_indices) const {
469  return getProblemNodesIndices(field_name, *(problemPtr->numeredDofsCols),
470  nodes_indices);
471 }
472 
475  EntityType type, int side_number,
476  VectorInt &indices) const {
477  return getProblemTypeIndices(field_name, *(problemPtr->numeredDofsCols), type,
478  side_number, indices);
479 }
480 
481 // ** Data **
482 
485  const std::string &field_name) const {
486 
487  auto get_nodes_field_data = [&](FEDofEntity_multiIndex &dofs,
488  VectorDouble &nodes_data,
489  VectorDofs &nodes_dofs, FieldSpace &space,
491  VectorInt &bb_node_order) {
493 
494  auto &dofs_by_name_and_type = dofs.get<Composite_Name_And_Type_mi_tag>();
495  auto tuple = boost::make_tuple(field_name, MBVERTEX);
496  auto dit = dofs_by_name_and_type.lower_bound(tuple);
497  if (dit == dofs_by_name_and_type.end())
498  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
499  "No nodal dofs on element");
500  auto hi_dit = dofs.get<Composite_Name_And_Type_mi_tag>().upper_bound(tuple);
501 
502  if (dit != hi_dit) {
503  auto &first_dof = **dit;
504  space = first_dof.getSpace();
505  base = first_dof.getApproxBase();
506  int num_nodes;
507  CHKERR getNumberOfNodes(num_nodes);
508  bb_node_order.resize(num_nodes, false);
509  bb_node_order.clear();
510  const int nb_dof_idx = first_dof.getNbOfCoeffs();
511  const int max_nb_dofs = nb_dof_idx * num_nodes;
512  nodes_data.resize(max_nb_dofs, false);
513  nodes_dofs.resize(max_nb_dofs, false);
514  nodes_data.clear();
515 
516  std::vector<boost::weak_ptr<FEDofEntity>> brother_dofs_vec;
517  for (; dit != hi_dit;) {
518  const auto &dof_ptr = *dit;
519  const auto &dof = *dof_ptr;
520  const auto &sn = *dof.sideNumberPtr;
521  const int side_number = sn.side_number;
522  const int brother_side_number = sn.brother_side_number;
523  if (brother_side_number != -1)
524  brother_dofs_vec.emplace_back(dof_ptr);
525 
526  bb_node_order[side_number] = dof.getMaxOrder();
527  int pos = side_number * nb_dof_idx;
528  auto ent_filed_data_vec = dof.getEntFieldData();
529  for (int ii = 0; ii != nb_dof_idx; ++ii) {
530  nodes_data[pos] = ent_filed_data_vec[ii];
531  nodes_dofs[pos] = *dit;
532  ++pos;
533  ++dit;
534  }
535  }
536 
537  for (auto &dof_ptr : brother_dofs_vec) {
538  if (const auto d = dof_ptr.lock()) {
539  const auto &sn = d->sideNumberPtr;
540  const int side_number = sn->side_number;
541  const int brother_side_number = sn->brother_side_number;
542  bb_node_order[brother_side_number] = bb_node_order[side_number];
543  int pos = side_number * nb_dof_idx;
544  int brother_pos = brother_side_number * nb_dof_idx;
545  for (int ii = 0; ii != nb_dof_idx; ++ii) {
546  nodes_data[brother_pos] = nodes_data[pos];
547  nodes_dofs[brother_pos] = nodes_dofs[pos];
548  ++pos;
549  ++brother_pos;
550  }
551  }
552  }
553 
554  } else {
555  nodes_data.resize(0, false);
556  nodes_dofs.resize(0, false);
557  }
558 
560  };
561 
562  return get_nodes_field_data(
563  const_cast<FEDofEntity_multiIndex &>(
564  numeredEntFiniteElementPtr->getDataDofs()),
565  data.dataOnEntities[MBVERTEX][0].getFieldData(),
566  data.dataOnEntities[MBVERTEX][0].getFieldDofs(),
567  data.dataOnEntities[MBVERTEX][0].getSpace(),
568  data.dataOnEntities[MBVERTEX][0].getBase(),
569  data.dataOnEntities[MBVERTEX][0].getBBNodeOrder());
570 }
571 
573  DataForcesAndSourcesCore &data, const std::string &field_name,
574  const EntityType type_lo, const EntityType type_hi) const {
576  for (EntityType t = type_lo; t != type_hi; ++t) {
577  for (auto &dat : data.dataOnEntities[t]) {
578  dat.getDataOrder() = 0;
579  dat.getBase() = NOBASE;
580  dat.getSpace() = NOSPACE;
581  dat.getFieldData().resize(0, false);
582  dat.getFieldDofs().resize(0, false);
583  }
584  }
585 
586  auto &dofs = const_cast<FEDofEntity_multiIndex &>(
587  numeredEntFiniteElementPtr->getDataDofs());
588  auto &dofs_by_type = dofs.get<Composite_Name_And_Type_mi_tag>();
589  auto dit = dofs_by_type.lower_bound(boost::make_tuple(field_name, type_lo));
590  if (dit == dofs_by_type.end())
592  auto hi_dit =
593  dofs_by_type.lower_bound(boost::make_tuple(field_name, type_hi));
594  std::vector<boost::weak_ptr<FEDofEntity>> brother_dofs_vec;
595  for (; dit != hi_dit;) {
596 
597  auto &dof = **dit;
598  const int nb_dofs_on_ent = dof.getNbDofsOnEnt();
599  if (nb_dofs_on_ent) {
600 
601  const EntityType type = dof.getEntType();
602  const int side = dof.sideNumberPtr->side_number;
603  if (side >= 0) {
604 
605  auto &dat = data.dataOnEntities[type][side];
606  auto &ent_field_dofs = dat.getFieldDofs();
607  auto &ent_field_data = dat.getFieldData();
608  const int brother_side = dof.sideNumberPtr->brother_side_number;
609  if (brother_side != -1)
610  brother_dofs_vec.emplace_back(*dit);
611 
612  if (ent_field_data.empty()) {
613 
614  dat.getBase() = dof.getApproxBase();
615  dat.getSpace() = dof.getSpace();
616  const int ent_order = dof.getMaxOrder();
617  dat.getDataOrder() =
618  dat.getDataOrder() > ent_order ? dat.getDataOrder() : ent_order;
619  ent_field_data.resize(nb_dofs_on_ent, false);
620  noalias(ent_field_data) = dof.getEntFieldData();
621  ent_field_dofs.resize(nb_dofs_on_ent, false);
622  for (int ii = 0; ii != nb_dofs_on_ent; ++ii) {
623  ent_field_dofs[ii] = *dit;
624  ++dit;
625  }
626  }
627 
628  } else {
629 
630  for (int ii = 0; ii != nb_dofs_on_ent; ++ii)
631  ++dit;
632 
633  }
634 
635  }
636  }
637 
638  for (auto &dof_ptr : brother_dofs_vec) {
639  if (auto d = dof_ptr.lock()) {
640  const EntityType type = d->getEntType();
641  const int side = d->sideNumberPtr->side_number;
642  const int brother_side = d->sideNumberPtr->brother_side_number;
643  auto &dat = data.dataOnEntities[type][side];
644  auto &dat_brother = data.dataOnEntities[type][brother_side];
645  dat_brother.getBase() = dat.getBase();
646  dat_brother.getSpace() = dat.getSpace();
647  dat_brother.getDataOrder() = dat.getDataOrder();
648  dat_brother.getFieldData() = dat.getFieldData();
649  dat_brother.getFieldDofs() = dat.getFieldDofs();
650  }
651  }
652 
654 }
655 
657  const boost::string_ref field_name, FEDofEntity_multiIndex &dofs,
658  VectorDouble &ent_field_data, VectorDofs &ent_field_dofs) const {
660  auto dit = dofs.get<FieldName_mi_tag>().lower_bound(field_name);
661  auto hi_dit = dofs.get<FieldName_mi_tag>().upper_bound(field_name);
662  int size = std::distance(dit, hi_dit);
663  ent_field_data.resize(size, false);
664  ent_field_dofs.resize(size, false);
665  for (; dit != hi_dit; dit++) {
666  int idx = (*dit)->getDofCoeffIdx();
667  ent_field_data[idx] = (*dit)->getFieldData();
668  ent_field_dofs[idx] = *dit;
669  }
671 }
672 
674  DataForcesAndSourcesCore &data, const boost::string_ref field_name) const {
676  if (data.dataOnEntities[MBENTITYSET].size() == 0) {
677  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
678  }
680  field_name,
681  const_cast<FEDofEntity_multiIndex &>(
682  numeredEntFiniteElementPtr->getDataDofs()),
683  data.dataOnEntities[MBENTITYSET][0].getFieldData(),
684  data.dataOnEntities[MBENTITYSET][0].getFieldDofs());
686 }
687 
688 // ** Face **
689 
693  // PetscAttachDebugger();
694  data.facesNodes.resize(4, 3, false);
695  auto &side_table = const_cast<SideNumber_multiIndex &>(
696  numeredEntFiniteElementPtr->getSideNumberTable());
697  auto siit = side_table.get<1>().lower_bound(boost::make_tuple(MBTRI, 0));
698  auto hi_siit = side_table.get<1>().upper_bound(boost::make_tuple(MBTRI, 4));
699  if (std::distance(siit, hi_siit) != 4) {
700  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
701  "Should be 4 triangles on tet, side_table not initialized");
702  }
703  const int canonical_face_sense_p1[4][3] = {
704  {0, 1, 3},
705  {1, 2, 3},
706  {0, 3, 2} /**/,
707  {0, 2, 1} /**/}; // second index is offset (positive sense)
708  const int canonical_face_sense_m1[4][3] = {
709  {0, 3, 1},
710  {1, 3, 2},
711  {0, 2, 3},
712  {0, 1, 2}}; // second index is offset (negative sense
713  for (; siit != hi_siit; siit++) {
714  const boost::shared_ptr<SideNumber> side = *siit;
715  int face_conn[3] = {-1, -1, -1};
716  if (side->offset == 0) {
717  face_conn[0] = side->sense == 1
718  ? canonical_face_sense_p1[(int)side->side_number][0]
719  : canonical_face_sense_m1[(int)side->side_number][0];
720  face_conn[1] = side->sense == 1
721  ? canonical_face_sense_p1[(int)side->side_number][1]
722  : canonical_face_sense_m1[(int)side->side_number][1];
723  face_conn[2] = side->sense == 1
724  ? canonical_face_sense_p1[(int)side->side_number][2]
725  : canonical_face_sense_m1[(int)side->side_number][2];
726  }
727  if (side->offset == 1) {
728  face_conn[0] =
729  side->sense == 1
730  ? canonical_face_sense_p1[(int)side->side_number][1]
731  : canonical_face_sense_m1[(int)side->side_number][2] /**/;
732  face_conn[1] = side->sense == 1
733  ? canonical_face_sense_p1[(int)side->side_number][2]
734  : canonical_face_sense_m1[(int)side->side_number][0];
735  face_conn[2] = side->sense == 1
736  ? canonical_face_sense_p1[(int)side->side_number][0]
737  : canonical_face_sense_m1[(int)side->side_number][1];
738  }
739  if (side->offset == 2) {
740  face_conn[0] =
741  side->sense == 1
742  ? canonical_face_sense_p1[(int)side->side_number][2]
743  : canonical_face_sense_m1[(int)side->side_number][1] /**/;
744  face_conn[1] = side->sense == 1
745  ? canonical_face_sense_p1[(int)side->side_number][0]
746  : canonical_face_sense_m1[(int)side->side_number][2];
747  face_conn[2] = side->sense == 1
748  ? canonical_face_sense_p1[(int)side->side_number][1]
749  : canonical_face_sense_m1[(int)side->side_number][0];
750  }
751  for (int nn = 0; nn < 3; nn++)
752  data.facesNodes(side->side_number, nn) = face_conn[nn];
753  {
754  const EntityHandle *conn_tet;
755  int num_nodes_tet;
757  CHKERR mField.get_moab().get_connectivity(ent, conn_tet, num_nodes_tet,
758  true);
759  if (num_nodes_tet != 4)
760  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
761  "data inconsistency");
762  int num_nodes_face;
763  const EntityHandle *conn_face;
764  CHKERR mField.get_moab().get_connectivity(side->ent, conn_face,
765  num_nodes_face, true);
766  if (num_nodes_face != 3)
767  SETERRQ(PETSC_COMM_SELF, 1, "data inconsistency");
768  if (conn_face[0] != conn_tet[data.facesNodes(side->side_number, 0)])
769  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
770  "data inconsistency");
771  if (conn_face[1] != conn_tet[data.facesNodes(side->side_number, 1)])
772  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
773  "data inconsistency");
774  if (conn_face[2] != conn_tet[data.facesNodes(side->side_number, 2)])
775  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
776  "data inconsistency");
777  }
778  }
780 }
781 
782 // ** Space and Base **
783 
785  DataForcesAndSourcesCore &data) const {
787 
788  if (nInTheLoop == 0) {
789  data.sPace.reset();
790  data.bAse.reset();
791  for (EntityType t = MBVERTEX; t != MBMAXTYPE; ++t) {
792  data.spacesOnEntities[t].reset();
793  data.basesOnEntities[t].reset();
794  }
795  for (int s = 0; s != LASTSPACE; ++s) {
796  data.basesOnSpaces[s].reset();
797  }
798  }
799 
800  if (dataFieldEntsPtr)
801  for (auto e : *dataFieldEntsPtr) {
802  // get data from entity
803  const EntityType type = e->getEntType();
804  const FieldSpace space = e->getSpace();
805  const FieldApproximationBase approx = e->getApproxBase();
806 
807  // set data
808  data.sPace.set(space);
809  data.bAse.set(approx);
810  data.spacesOnEntities[type].set(space);
811  data.basesOnEntities[type].set(approx);
812  data.basesOnSpaces[space].set(approx);
813  }
814  else
815  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
816  "data fields ents not allocated on element");
817 
819 }
820 
822  const FieldApproximationBase b) {
824  if (dataOnElement[H1]->bAse.test(b)) {
825  switch (static_cast<FieldApproximationBase>(b)) {
826  case NOBASE:
827  break;
829  // BERNSTEIN_BEZIER_BASE is not hierarchical base
830  break;
835  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
836  "Functions genrating approximation base not defined");
837 
838  for (int space = H1; space != LASTSPACE; ++space) {
839  if (dataOnElement[H1]->sPace.test(space) &&
840  dataOnElement[H1]->bAse.test(b) &&
841  dataOnElement[H1]->basesOnSpaces[space].test(b)) {
842  CHKERR getElementPolynomialBase()->getValue(
843  gaussPts,
844  boost::make_shared<EntPolynomialBaseCtx>(
845  *dataOnElement[space], static_cast<FieldSpace>(space),
846  static_cast<FieldApproximationBase>(b), NOBASE));
847  }
848  }
849  break;
850  case USER_BASE:
851  if (!getUserPolynomialBase())
852  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
853  "Functions genrating user approximation base not defined");
854 
855  for (int space = H1; space != LASTSPACE; ++space)
856  if (dataOnElement[H1]->sPace.test(space) &&
857  dataOnElement[H1]->bAse.test(b) &&
858  dataOnElement[H1]->basesOnSpaces[space].test(b)) {
859  CHKERR getUserPolynomialBase()->getValue(
860  gaussPts,
861  boost::make_shared<EntPolynomialBaseCtx>(
862  *dataOnElement[space], static_cast<FieldSpace>(space),
863  static_cast<FieldApproximationBase>(b), NOBASE));
864  }
865  break;
866  default:
868  "Base <%s> not yet implemented",
869  ApproximationBaseNames[static_cast<FieldApproximationBase>(b)]);
870  }
871  }
873 }
874 
877  /// Use the some node base. Node base is usually used for construction other
878  /// bases.
879  for (int space = HCURL; space != LASTSPACE; ++space) {
880  dataOnElement[space]->dataOnEntities[MBVERTEX][0].getNSharedPtr(NOBASE) =
881  dataOnElement[H1]->dataOnEntities[MBVERTEX][0].getNSharedPtr(NOBASE);
882  }
883  for (int b = AINSWORTH_LEGENDRE_BASE; b != LASTBASE; b++) {
885  static_cast<FieldApproximationBase>(b));
886  }
888 }
889 
893 
894  auto get_nodal_base_data = [&](DataForcesAndSourcesCore &data,
895  const std::string &field_name) {
897  auto &space = data.dataOnEntities[MBVERTEX][0].getSpace();
898  auto &base = data.dataOnEntities[MBVERTEX][0].getBase();
899  auto &bb_node_order = data.dataOnEntities[MBVERTEX][0].getBBNodeOrder();
900 
901  auto &dofs_by_name_and_type =
903  auto tuple = boost::make_tuple(field_name, MBVERTEX);
904  auto dit = dofs_by_name_and_type.lower_bound(tuple);
905  if (dit == dofs_by_name_and_type.end())
906  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
907  "No nodal dofs on element");
908  auto hi_dit =
909  dataPtr->get<Composite_Name_And_Type_mi_tag>().upper_bound(tuple);
910 
911  if (dit != hi_dit) {
912  auto &first_dof = **dit;
913  space = first_dof.getSpace();
914  base = first_dof.getApproxBase();
915  int num_nodes;
916  CHKERR getNumberOfNodes(num_nodes);
917  bb_node_order.resize(num_nodes, false);
918  bb_node_order.clear();
919  const int nb_dof_idx = first_dof.getNbOfCoeffs();
920 
921  std::vector<boost::weak_ptr<FEDofEntity>> brother_dofs_vec;
922  for (; dit != hi_dit;) {
923  const auto &dof_ptr = *dit;
924  const auto &dof = *dof_ptr;
925  const auto &sn = *dof.sideNumberPtr;
926  const int side_number = sn.side_number;
927  const int brother_side_number = sn.brother_side_number;
928  if (brother_side_number != -1)
929  brother_dofs_vec.emplace_back(dof_ptr);
930  bb_node_order[side_number] = dof.getMaxOrder();
931  for (int ii = 0; ii != nb_dof_idx; ++ii)
932  ++dit;
933  }
934 
935  for (auto &dof_ptr : brother_dofs_vec) {
936  if (const auto d = dof_ptr.lock()) {
937  const auto &sn = d->sideNumberPtr;
938  const int side_number = sn->side_number;
939  const int brother_side_number = sn->brother_side_number;
940  bb_node_order[brother_side_number] = bb_node_order[side_number];
941  }
942  }
943  }
945  };
946 
947  auto get_entity_base_data = [&](DataForcesAndSourcesCore &data,
948  const std::string &field_name,
949  const EntityType type_lo,
950  const EntityType type_hi) {
952  for (EntityType t = type_lo; t != type_hi; ++t) {
953  for (auto &dat : data.dataOnEntities[t]) {
954  dat.getDataOrder() = 0;
955  dat.getBase() = NOBASE;
956  dat.getSpace() = NOSPACE;
957  dat.getFieldData().resize(0, false);
958  dat.getFieldDofs().resize(0, false);
959  }
960  }
961 
962  auto &dofs = const_cast<FEDofEntity_multiIndex &>(
963  numeredEntFiniteElementPtr->getDataDofs());
964  auto &dofs_by_type = dofs.get<Composite_Name_And_Type_mi_tag>();
965  auto dit = dofs_by_type.lower_bound(boost::make_tuple(field_name, type_lo));
966  if (dit == dofs_by_type.end())
968  auto hi_dit =
969  dofs_by_type.lower_bound(boost::make_tuple(field_name, type_hi));
970  std::vector<boost::weak_ptr<FEDofEntity>> brother_dofs_vec;
971  for (; dit != hi_dit;) {
972 
973  auto &dof = **dit;
974  const int nb_dofs_on_ent = dof.getNbDofsOnEnt();
975  if (nb_dofs_on_ent) {
976  const EntityType type = dof.getEntType();
977  const int side = dof.sideNumberPtr->side_number;
978  auto &dat = data.dataOnEntities[type][side];
979 
980  const int brother_side = dof.sideNumberPtr->brother_side_number;
981  if (brother_side != -1)
982  brother_dofs_vec.emplace_back(*dit);
983 
984  dat.getBase() = dof.getApproxBase();
985  dat.getSpace() = dof.getSpace();
986  const int ent_order = dof.getMaxOrder();
987  dat.getDataOrder() =
988  dat.getDataOrder() > ent_order ? dat.getDataOrder() : ent_order;
989  for (int ii = 0; ii != nb_dofs_on_ent; ++ii) {
990  ++dit;
991  }
992  }
993  }
994 
995  for (auto &dof_ptr : brother_dofs_vec) {
996  if (auto d = dof_ptr.lock()) {
997  const EntityType type = d->getEntType();
998  const int side = d->sideNumberPtr->side_number;
999  const int brother_side = d->sideNumberPtr->brother_side_number;
1000  auto &dat = data.dataOnEntities[type][side];
1001  auto &dat_brother = data.dataOnEntities[type][brother_side];
1002  dat_brother.getBase() = dat.getBase();
1003  dat_brother.getSpace() = dat.getSpace();
1004  dat_brother.getDataOrder() = dat.getDataOrder();
1005  }
1006  }
1008  };
1009 
1010  auto &ents_data = *dataFieldEntsPtr;
1011  for (auto &e : ents_data) {
1012  if (e->getApproxBase() == AINSWORTH_BERNSTEIN_BEZIER_BASE) {
1013  auto space = e->getSpace();
1014  for (EntityType t = MBVERTEX; t != MBPOLYHEDRON; ++t) {
1015  for (auto &dat : (*dataOnElement[space]).dataOnEntities[t]) {
1016  for (auto &ptr : dat.getBBAlphaIndicesByOrderArray())
1017  ptr.reset();
1018  for (auto &ptr : dat.getBBNByOrderArray())
1019  ptr.reset();
1020  for (auto &ptr : dat.getBBDiffNByOrderArray())
1021  ptr.reset();
1022  }
1023  }
1024  }
1025  }
1026 
1027  for (auto &e : ents_data) {
1028  if (e->getApproxBase() == AINSWORTH_BERNSTEIN_BEZIER_BASE) {
1029  auto field_name = e->getName();
1030  auto space = e->getSpace();
1031  CHKERR get_nodal_base_data(*dataOnElement[space], field_name);
1032  CHKERR get_entity_base_data(*dataOnElement[space], field_name, MBEDGE,
1033  MBPOLYHEDRON);
1034  CHKERR getElementPolynomialBase()->getValue(
1035  gaussPts,
1036  boost::make_shared<EntPolynomialBaseCtx>(
1037  *dataOnElement[space], field_name, static_cast<FieldSpace>(space),
1039  }
1040  }
1041 
1043 };
1044 
1047 
1048  const EntityType type = numeredEntFiniteElementPtr->getEntType();
1051 
1052  // Data on elements for proper spaces
1053  for (int space = H1; space != LASTSPACE; ++space) {
1054  dataOnElement[space]->setElementType(type);
1055  derivedDataOnElement[space]->setElementType(type);
1056  }
1057 
1059 
1061 }
1062 
1063 #define FUNCTION_NAME_WITH_OP_NAME(OP) \
1064  std::ostringstream ss; \
1065  ss << "(Calling user data operator " \
1066  << boost::typeindex::type_id_runtime(OP).pretty_name() << " rowField " \
1067  << (OP).rowFieldName << " colField " << (OP).colFieldName << ") "
1068 
1069 #define CATCH_OP_ERRORS(OP) \
1070  catch (MoFEMExceptionInitial const &ex) { \
1071  FUNCTION_NAME_WITH_OP_NAME(OP) << PETSC_FUNCTION_NAME; \
1072  return PetscError(PETSC_COMM_SELF, ex.lINE, ss.str().c_str(), __FILE__, \
1073  ex.errorCode, PETSC_ERROR_INITIAL, ex.what()); \
1074  } \
1075  catch (MoFEMExceptionRepeat const &ex) { \
1076  FUNCTION_NAME_WITH_OP_NAME(OP) << PETSC_FUNCTION_NAME; \
1077  return PetscError(PETSC_COMM_SELF, ex.lINE, ss.str().c_str(), __FILE__, \
1078  ex.errorCode, PETSC_ERROR_REPEAT, " "); \
1079  } \
1080  catch (MoFEMException const &ex) { \
1081  FUNCTION_NAME_WITH_OP_NAME(OP) << ex.errorMessage; \
1082  SETERRQ(PETSC_COMM_SELF, ex.errorCode, ss.str().c_str()); \
1083  } \
1084  catch (std::exception const &ex) { \
1085  std::string message("Error: " + std::string(ex.what()) + " at " + \
1086  boost::lexical_cast<std::string>(__LINE__) + " : " + \
1087  std::string(__FILE__) + " in " + \
1088  std::string(PETSC_FUNCTION_NAME)); \
1089  FUNCTION_NAME_WITH_OP_NAME(OP) << message; \
1090  SETERRQ(PETSC_COMM_SELF, MOFEM_STD_EXCEPTION_THROW, ss.str().c_str()); \
1091  }
1092 
1095 
1096  const EntityType type = numeredEntFiniteElementPtr->getEntType();
1099  std::vector<std::string> last_eval_field_name(2);
1100 
1101  boost::ptr_vector<UserDataOperator>::iterator oit, hi_oit;
1102  oit = opPtrVector.begin();
1103  hi_oit = opPtrVector.end();
1104 
1105  for (; oit != hi_oit; oit++) {
1106 
1107  try {
1108 
1109  CHKERR oit->setPtrFE(this);
1110 
1111  if (oit->opType == UserDataOperator::OPLAST) {
1112 
1113  // Set field
1114  switch (oit->sPace) {
1115  case NOSPACE:
1116  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Unknown space");
1117  case NOFIELD:
1118  case H1:
1119  case HCURL:
1120  case HDIV:
1121  case L2:
1122  break;
1123  default:
1124  SETERRQ1(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
1125  "Not implemented for this space", oit->sPace);
1126  }
1127 
1128  // Reseat all data which all field dependent
1129  dataOnElement[oit->sPace]->resetFieldDependentData();
1130  last_eval_field_name[0] = "";
1131 
1132  // Run operator
1133  try {
1134  CHKERR oit->opRhs(*dataOnElement[oit->sPace], false);
1135  }
1136  CATCH_OP_ERRORS(*oit);
1137 
1138  } else {
1139 
1140  boost::shared_ptr<DataForcesAndSourcesCore> op_data[2];
1141  std::array<bool, 2> base_swap;
1142  std::array<std::pair<std::string, FieldApproximationBase>, 2>
1143  base_swap_data;
1144  auto swap_bases = [&]() {
1146  for (size_t ss = 0; ss != 2; ++ss)
1147  if (base_swap[ss])
1148  CHKERR op_data[ss]->baseSwap(base_swap_data[ss].first,
1149  base_swap_data[ss].second);
1151  };
1152 
1153  for (size_t ss = 0; ss != 2; ss++) {
1154 
1155  const std::string field_name =
1156  !ss ? oit->rowFieldName : oit->colFieldName;
1157  if (field_name.empty()) {
1158  SETERRQ2(
1159  PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1160  "No field name in operator %d (0-row, 1-column) in operator %s",
1161  ss,
1162  (boost::typeindex::type_id_runtime(*oit).pretty_name())
1163  .c_str());
1164  }
1165  const Field *field_struture = mField.get_field_structure(field_name);
1166  const BitFieldId data_id = field_struture->getId();
1167  const FieldSpace space = field_struture->getSpace();
1168  const FieldApproximationBase base = field_struture->getApproxBase();
1169  op_data[ss] =
1170  !ss ? dataOnElement[space] : derivedDataOnElement[space];
1171 
1172  switch (base) {
1174  base_swap_data[ss] = std::pair<std::string, FieldApproximationBase>(
1175  field_name, AINSWORTH_BERNSTEIN_BEZIER_BASE);
1176  base_swap[ss] = true;
1177  break;
1178  default:
1179  base_swap[ss] = false;
1180  };
1181 
1182  if ((oit->getNumeredEntFiniteElementPtr()->getBitFieldIdData() &
1183  data_id)
1184  .none()) {
1185  SETERRQ2(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1186  "no data field < %s > on finite element < %s >",
1187  field_name.c_str(), feName.c_str());
1188  }
1189 
1190  if (oit->getOpType() & types[ss] ||
1191  oit->getOpType() & UserDataOperator::OPROWCOL) {
1192 
1193  switch (space) {
1194  case NOSPACE:
1195  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1196  "unknown space");
1197  break;
1198  case NOFIELD:
1199  case H1:
1200  case HCURL:
1201  case HDIV:
1202  case L2:
1203  break;
1204  default:
1205  SETERRQ1(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
1206  "Not implemented for this space", space);
1207  }
1208 
1209  if (last_eval_field_name[ss] != field_name) {
1210 
1211  CHKERR getEntityFieldData(*op_data[ss], field_name, MBEDGE);
1212  if (!ss)
1213  CHKERR getEntityRowIndices(*op_data[ss], field_name, MBEDGE);
1214  else
1215  CHKERR getEntityColIndices(*op_data[ss], field_name, MBEDGE);
1216 
1217  switch (space) {
1218  case NOSPACE:
1219  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1220  "unknown space");
1221  break;
1222  case H1:
1223  if (!ss)
1224  CHKERR getRowNodesIndices(*op_data[ss], field_name);
1225  else
1226  CHKERR getColNodesIndices(*op_data[ss], field_name);
1227  CHKERR getNodesFieldData(*op_data[ss], field_name);
1228  break;
1229  case HCURL:
1230  case HDIV:
1231  break;
1232  case L2:
1233  switch (type) {
1234  case MBVERTEX:
1235  CHKERR getNodesFieldData(*op_data[ss], field_name);
1236  break;
1237  default:
1238  break;
1239  }
1240  break;
1241  case NOFIELD:
1242  if (!getNinTheLoop()) {
1243  // NOFIELD data are the same for each element, can be
1244  // retrieved only once
1245  if (!ss) {
1246  CHKERR getNoFieldRowIndices(*op_data[ss], field_name);
1247  } else {
1248  CHKERR getNoFieldColIndices(*op_data[ss], field_name);
1249  }
1250  CHKERR getNoFieldFieldData(*op_data[ss], field_name);
1251  }
1252  break;
1253  default:
1254  SETERRQ1(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
1255  "Not implemented for this space", space);
1256  }
1257  last_eval_field_name[ss] = field_name;
1258  }
1259  }
1260  }
1261 
1262  CHKERR swap_bases();
1263 
1264  if (oit->getOpType() & UserDataOperator::OPROW) {
1265  try {
1266  CHKERR oit->opRhs(*op_data[0], false);
1267  }
1268  CATCH_OP_ERRORS(*oit);
1269  }
1270 
1271  if (oit->getOpType() & UserDataOperator::OPCOL) {
1272  try {
1273  CHKERR oit->opRhs(*op_data[1], false);
1274  }
1275  CATCH_OP_ERRORS(*oit);
1276  }
1277 
1278  if (oit->getOpType() & UserDataOperator::OPROWCOL) {
1279  try {
1280  CHKERR oit->opLhs(*op_data[0], *op_data[1]);
1281  }
1282  CATCH_OP_ERRORS(*oit);
1283  }
1284 
1285  CHKERR swap_bases();
1286  }
1287  }
1288  CATCH_OP_ERRORS(*oit);
1289  }
1291 }
1292 
1294  const std::string field_name, const EntityType type, const int side,
1295  VectorInt &indices) const {
1297  if (ptrFE == NULL)
1298  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
1299 
1300  switch (type) {
1301  case MBVERTEX:
1302  CHKERR ptrFE->getProblemNodesRowIndices(field_name, indices);
1303  break;
1304  default:
1305  CHKERR ptrFE->getProblemTypeRowIndices(field_name, type, side, indices);
1306  }
1308 }
1309 
1311  const std::string field_name, const EntityType type, const int side,
1312  VectorInt &indices) const {
1314  if (ptrFE == NULL)
1315  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
1316 
1317  switch (type) {
1318  case MBVERTEX:
1319  CHKERR ptrFE->getProblemNodesColIndices(field_name, indices);
1320  break;
1321  default:
1322  CHKERR ptrFE->getProblemTypeColIndices(field_name, type, side, indices);
1323  }
1325 }
1326 
1330  sidePtrFE = const_cast<ForcesAndSourcesCore *>(side_fe_ptr);
1332 }
1333 
1336  ForcesAndSourcesCore *side_fe,
1337  const size_t side_dim) {
1339  const EntityHandle ent = getNumeredEntFiniteElementPtr()->getEnt();
1340  const Problem *problem_ptr = getFEMethod()->problemPtr;
1341  Range adjacent_ents;
1342  CHKERR ptrFE->mField.getInterface<BitRefManager>()->getAdjacenciesAny(
1343  ent, side_dim, adjacent_ents);
1344  typedef NumeredEntFiniteElement_multiIndex::index<
1345  Composite_Name_And_Ent_mi_tag>::type FEByComposite;
1346  FEByComposite &numered_fe =
1348 
1349  side_fe->feName = fe_name;
1350 
1351  CHKERR side_fe->setSideFEPtr(ptrFE);
1352  CHKERR side_fe->copyBasicMethod(*getFEMethod());
1353  CHKERR side_fe->copyKsp(*getFEMethod());
1354  CHKERR side_fe->copySnes(*getFEMethod());
1355  CHKERR side_fe->copyTs(*getFEMethod());
1356 
1357  CHKERR side_fe->preProcess();
1358 
1359  int nn = 0;
1360  side_fe->loopSize = adjacent_ents.size();
1361  for (Range::iterator vit = adjacent_ents.begin(); vit != adjacent_ents.end();
1362  vit++) {
1363  FEByComposite::iterator miit =
1364  numered_fe.find(boost::make_tuple(fe_name, *vit));
1365  if (miit != numered_fe.end()) {
1366  side_fe->nInTheLoop = nn++;
1367  side_fe->numeredEntFiniteElementPtr = *miit;
1368  side_fe->dataFieldEntsPtr = (*miit)->sPtr->data_field_ents_view;
1369  side_fe->rowFieldEntsPtr = (*miit)->sPtr->row_field_ents_view;
1370  side_fe->colFieldEntsPtr = (*miit)->sPtr->col_field_ents_view;
1371  side_fe->dataPtr = (*miit)->sPtr->data_dofs;
1372  side_fe->rowPtr = (*miit)->rows_dofs;
1373  side_fe->colPtr = (*miit)->cols_dofs;
1374  CHKERR (*side_fe)();
1375  }
1376  }
1377 
1378  CHKERR side_fe->postProcess();
1379 
1381 }
1382 
1383 int ForcesAndSourcesCore::getRule(int order_row, int order_col,
1384  int order_data) {
1385  return getRuleHook ? getRuleHook(order_row, order_col, order_data)
1386  : getRule(order_data);
1387 }
1388 
1390  int order_data) {
1391  return setRuleHook ? setRuleHook(order_row, order_col, order_data)
1392  : setGaussPts(order_data);
1393 }
1394 
1396 
1397 /** \deprecated setGaussPts(int row_order, int col_order, int data order);
1398  */
1401  SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Sorry, not implemented");
1403 }
1404 
1406  const char type,
1407  const bool symm)
1408  : DataOperator(symm), opType(type), sPace(space), ptrFE(nullptr) {}
1409 
1411  const std::string &field_name, const char type, const bool symm)
1412  : DataOperator(symm), opType(type), rowFieldName(field_name),
1413  colFieldName(field_name), sPace(LASTSPACE), ptrFE(nullptr) {}
1414 
1416  const std::string &row_field_name, const std::string &col_field_name,
1417  const char type, const bool symm)
1418  : DataOperator(symm), opType(type), rowFieldName(row_field_name),
1419  colFieldName(col_field_name), sPace(LASTSPACE), ptrFE(nullptr) {}
1420 
1423  if (preProcessHook) {
1424  ierr = preProcessHook();
1425  CHKERRG(ierr);
1426  }
1428 }
1431  if (operatorHook) {
1432  ierr = operatorHook();
1433  CHKERRG(ierr);
1434  }
1436 }
1439  if (postProcessHook) {
1440  ierr = postProcessHook();
1441  CHKERRG(ierr);
1442  }
1444 }
1445 
1449  if (!(ptrFE = dynamic_cast<ForcesAndSourcesCore *>(ptr)))
1450  SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1451  "User operator and finite element do not work together");
1453 }
1454 
1455 } // namespace MoFEM
MoFEMErrorCode copyBasicMethod(const BasicMethod &basic)
Copy data from other base method to this base method.
ForcesAndSourcesCore(Interface &m_field)
int getMaxRowOrder() const
Get max order of approximation for field in rows.
Deprecated interface functions.
boost::ptr_vector< UserDataOperator > opPtrVector
Vector of finite element users data operators.
MoFEMErrorCode getProblemColIndices(const std::string filed_name, const EntityType type, const int side, VectorInt &indices) const
Get col indices.
MatrixDouble gaussPts
Matrix of integration points.
base operator to do operations at Gauss Pt. level
field with continuous normal traction
Definition: definitions.h:178
user implemented approximation base
Definition: definitions.h:159
MoFEMErrorCode getNoFieldColIndices(DataForcesAndSourcesCore &data, const std::string &field_name) const
get col NoField indices
virtual moab::Interface & get_moab()=0
ForcesAndSourcesCore * sidePtrFE
Element to integrate on the sides.
MoFEMErrorCode getEntitySense(const EntityType type, boost::ptr_vector< DataForcesAndSourcesCore::EntData > &data) const
get sense (orientation) of entity
virtual int getRule(int order_row, int order_col, int order_data)
another variant of getRule
data structure for finite element entityIt keeps that about indices of degrees of freedom,...
MoFEMErrorCode createDataOnElement()
Create a entity data on element object.
Provide data structure for (tensor) field approximation.The Field is intended to provide support for ...
MoFEMErrorCode getColNodesIndices(DataForcesAndSourcesCore &data, const std::string &field_name) const
get col node indices from FENumeredDofEntity_multiIndex
MoFEMErrorCode calBernsteinBezierBaseFunctionsOnElement()
Calculate Bernstein-Bezier base.
int ApproximationOrder
Approximation on the entity.
Definition: Types.hpp:37
std::array< boost::ptr_vector< EntData >, MBMAXTYPE > dataOnEntities
int loopSize
local number oe methods to process
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:506
scalar or vector of scalars describe (no true field)
Definition: definitions.h:175
MoFEMErrorCode getEntityDataOrder(const EntityType type, const FieldSpace space, boost::ptr_vector< DataForcesAndSourcesCore::EntData > &data) const
Get the entity data order.
auto & getUserPolynomialBase()
Get the User Polynomial Base object.
multi_index_container< boost::shared_ptr< FENumeredDofEntity >, indexed_by< ordered_unique< tag< Unique_mi_tag >, const_mem_fun< FENumeredDofEntity::interface_type_DofEntity, const UId &, &FENumeredDofEntity::getGlobalUniqueId > >, ordered_non_unique< tag< Ent_mi_tag >, const_mem_fun< FENumeredDofEntity::interface_type_DofEntity, EntityHandle, &FENumeredDofEntity::getEnt > >, ordered_non_unique< tag< FieldName_mi_tag >, const_mem_fun< FENumeredDofEntity::interface_type_Field, boost::string_ref, &FENumeredDofEntity::getNameRef > >, ordered_non_unique< tag< Composite_Name_Type_And_Side_Number_mi_tag >, composite_key< FENumeredDofEntity, const_mem_fun< FENumeredDofEntity::interface_type_Field, boost::string_ref, &FENumeredDofEntity::getNameRef >, const_mem_fun< FENumeredDofEntity::interface_type_RefEntity, EntityType, &FENumeredDofEntity::getEntType >, KeyFromKey< member< SideNumber, char, &SideNumber::side_number >, member< FENumeredDofEntity::BaseFEEntity, boost::shared_ptr< SideNumber >, &FENumeredDofEntity::sideNumberPtr > > > >, ordered_non_unique< tag< Composite_Name_And_Type_mi_tag >, composite_key< FENumeredDofEntity, const_mem_fun< FENumeredDofEntity::interface_type_Field, boost::string_ref, &FENumeredDofEntity::getNameRef >, const_mem_fun< FENumeredDofEntity::interface_type_RefEntity, EntityType, &FENumeredDofEntity::getEntType > > >, ordered_non_unique< tag< Composite_Name_And_Ent_mi_tag >, composite_key< FENumeredDofEntity, const_mem_fun< FENumeredDofEntity::interface_type_Field, boost::string_ref, &FENumeredDofEntity::getNameRef >, const_mem_fun< FENumeredDofEntity::interface_type_DofEntity, EntityHandle, &FENumeredDofEntity::getEnt > > > > > FENumeredDofEntity_multiIndex
MultiIndex container keeps FENumeredDofEntity.
boost::shared_ptr< const FieldEntity_vector_view > colFieldEntsPtr
Pointer to finite element field entities column view.
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:482
#define CHKERRG(n)
Check error code of MoFEM/MOAB/PETSc function.
Definition: definitions.h:549
std::string feName
Name of finite element.
MoFEMErrorCode getFaceTriNodes(DataForcesAndSourcesCore &data) const
Get nodes on triangles.
FieldCoefficientsNumber getNbOfCoeffs() const
Get number of field coefficients.
int getNinTheLoop() const
get number of evaluated element in the loop
boost::shared_ptr< const FieldEntity_vector_view > rowFieldEntsPtr
Pointer to finite element field entities row view.
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
Definition: definitions.h:513
keeps basic data about problemThis is low level structure with information about problem,...
MoFEMErrorCode getNoFieldRowIndices(DataForcesAndSourcesCore &data, const std::string &field_name) const
get col NoField indices
UserDataOperator(const FieldSpace space, const char type=OPLAST, const bool symm=true)
boost::shared_ptr< const FEDofEntity_multiIndex > dataPtr
Pointer to finite element data dofs.
std::array< std::bitset< LASTBASE >, LASTSPACE > basesOnSpaces
base on spaces
implementation of Data Operators for Forces and Sources
Definition: Common.hpp:21
FieldSpace getSpace() const
Get field approximation space.
boost::function< MoFEMErrorCode()> postProcessHook
Hook function for post-processing.
OpType
Controls loop over entities on element.
MoFEMErrorCode getNoFieldFieldData(const boost::string_ref field_name, FEDofEntity_multiIndex &dofs, VectorDouble &ent_field_data, VectorDofs &ent_field_dofs) const
Get field data on nodes.
FieldSpace in [ 0, LASTSPACE )
Definition: definitions.h:180
const Problem * problemPtr
raw pointer to problem
static const char *const ApproximationBaseNames[]
Definition: definitions.h:163
MoFEMErrorCode loopOverOperators()
Iterate user data operators.
boost::shared_ptr< const NumeredEntFiniteElement > numeredEntFiniteElementPtr
MoFEMErrorCode copyKsp(const KspMethod &ksp)
copy data form another method
Definition: LoopMethods.cpp:60
MoFEMErrorCode setSideFEPtr(const ForcesAndSourcesCore *side_fe_ptr)
Set the pointer to face element on the side.
MoFEMErrorCode getProblemNodesRowIndices(const std::string &field_name, VectorInt &nodes_indices) const
MoFEMErrorCode getNodesFieldData(DataForcesAndSourcesCore &data, const std::string &field_name) const
Get data on nodes.
RuleHookFun getRuleHook
Hook to get rule.
#define CATCH_OP_ERRORS(OP)
MoFEMErrorCode copyTs(const TSMethod &ts)
Copy TS solver data.
EntityType lastEvaluatedElementEntityType
Last evaluated type of element entity.
boost::function< MoFEMErrorCode()> operatorHook
Hook function for operator.
MoFEMErrorCode getProblemTypeRowIndices(const std::string &field_name, EntityType type, int side_number, VectorInt &indices) const
const Tensor1_Expr< const dTensor0< T, Dim, i >, typename promote< T, double >::V, Dim, i > d(const Tensor0< T * > &a, const Index< i, Dim > index, const Tensor1< int, Dim > &d_ijk, const Tensor1< double, Dim > &d_xyz)
Definition: dTensor0.hpp:27
const std::array< boost::shared_ptr< DataForcesAndSourcesCore >, LASTSPACE > derivedDataOnElement
Entity data on element entity columns fields.
MatrixInt facesNodes
nodes on finite element faces
FieldApproximationBase
approximation base
Definition: definitions.h:149
constexpr int order
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
Definition: Exceptions.hpp:66
const BitFieldId & getId() const
Get unique field id.
MoFEMErrorCode getNodesIndices(const boost::string_ref field_name, FENumeredDofEntity_multiIndex &dofs, VectorInt &nodes_indices, VectorInt &local_nodes_indices) const
get node indices
MoFEMErrorCode getProblemNodesColIndices(const std::string &field_name, VectorInt &nodes_indices) const
FieldApproximationBase getApproxBase() const
Get approximation base.
Managing BitRefLevels.
Ainsworth Cole (Legendre) approx. base .
Definition: definitions.h:151
MoFEMErrorCode getProblemTypeColIndices(const std::string &field_name, EntityType type, int side_number, VectorInt &indices) const
boost::shared_ptr< NumeredDofEntity_multiIndex > numeredDofsRows
store DOFs on rows for this problem
field with continuous tangents
Definition: definitions.h:177
FieldSpace
approximation spaces
Definition: definitions.h:173
virtual MoFEMErrorCode setGaussPts(int order_row, int order_col, int order_data)
set user specific integration rule
std::bitset< BITFIELDID_SIZE > BitFieldId
Field Id.
Definition: Types.hpp:53
#define CHKERR
Inline error check.
Definition: definitions.h:601
MoFEMErrorCode getEntityIndices(DataForcesAndSourcesCore &data, const std::string &field_name, FENumeredDofEntity_multiIndex &dofs, const EntityType type_lo=MBVERTEX, const EntityType type_hi=MBPOLYHEDRON) const
int nInTheLoop
number currently of processed method
virtual MoFEMErrorCode postProcess()
function is run at the end of loop
MoFEMErrorCode getEntityFieldData(DataForcesAndSourcesCore &data, const std::string &field_name, const EntityType type_lo=MBVERTEX, const EntityType type_hi=MBPOLYHEDRON) const
std::array< std::bitset< LASTBASE >, MBMAXTYPE > basesOnEntities
bases on entity types
MoFEMErrorCode getNoFieldIndices(const std::string &field_name, FENumeredDofEntity_multiIndex &dofs, VectorInt &nodes_indices) const
get NoField indices
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
static int getMaxOrder(const ENTMULTIINDEX &multi_index)
multi_index_container< boost::shared_ptr< FEDofEntity >, indexed_by< ordered_unique< tag< Unique_mi_tag >, const_mem_fun< FEDofEntity::interface_type_DofEntity, const UId &, &FEDofEntity::getGlobalUniqueId > >, ordered_non_unique< tag< Ent_mi_tag >, const_mem_fun< FEDofEntity::interface_type_DofEntity, EntityHandle, &FEDofEntity::getEnt > >, ordered_non_unique< tag< FieldName_mi_tag >, const_mem_fun< FEDofEntity::interface_type_Field, boost::string_ref, &FEDofEntity::getNameRef > >, ordered_non_unique< tag< EntType_mi_tag >, const_mem_fun< FEDofEntity::interface_type_RefEntity, EntityType, &FEDofEntity::getEntType > >, ordered_non_unique< tag< Composite_Name_And_Type_mi_tag >, composite_key< FEDofEntity, const_mem_fun< FEDofEntity::interface_type_Field, boost::string_ref, &FEDofEntity::getNameRef >, const_mem_fun< FEDofEntity::interface_type_RefEntity, EntityType, &FEDofEntity::getEntType > > >, ordered_non_unique< tag< Composite_Name_And_Ent_mi_tag >, composite_key< FEDofEntity, const_mem_fun< FEDofEntity::interface_type_Field, boost::string_ref, &FEDofEntity::getNameRef >, const_mem_fun< FEDofEntity::interface_type_DofEntity, EntityHandle, &FEDofEntity::getEnt > > >, ordered_non_unique< tag< Composite_Name_Type_And_Side_Number_mi_tag >, composite_key< FEDofEntity, const_mem_fun< FEDofEntity::interface_type_Field, boost::string_ref, &FEDofEntity::getNameRef >, const_mem_fun< FEDofEntity::interface_type_RefEntity, EntityType, &FEDofEntity::getEntType >, KeyFromKey< member< SideNumber, char, &SideNumber::side_number >, member< FEDofEntity::BaseFEEntity, boost::shared_ptr< SideNumber >, &FEDofEntity::sideNumberPtr > > > > > > FEDofEntity_multiIndex
MultiIndex container keeps FEDofEntity.
ublas::vector< int, IntAllocator > VectorInt
Definition: Types.hpp:71
ublas::vector< boost::shared_ptr< const FEDofEntity >, DofsAllocator > VectorDofs
MultiIndex Tag for field name.
MoFEMErrorCode copySnes(const SnesMethod &snes)
Copy snes data.
Definition: LoopMethods.cpp:84
virtual MoFEMErrorCode setPtrFE(ForcesAndSourcesCore *ptr)
std::bitset< LASTSPACE > sPace
spaces on element
MoFEMErrorCode getNumberOfNodes(int &num_nodes) const
Get number of DOFs on element.
MoFEMErrorCode calHierarchicalBaseFunctionsOnElement()
Calculate base functions.
virtual MoFEMErrorCode operator()()
function is run for every finite element
MoFEMErrorCode getEntityColIndices(DataForcesAndSourcesCore &data, const std::string &field_name, const EntityType type_lo=MBVERTEX, const EntityType type_hi=MBPOLYHEDRON) const
boost::shared_ptr< const FieldEntity_multiIndex_spaceType_view > dataFieldEntsPtr
Pointer to finite element field entities data view.
std::array< std::bitset< LASTSPACE >, MBMAXTYPE > spacesOnEntities
spaces on entity types
structure to get information form mofem into DataForcesAndSourcesCore
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
Definition: definitions.h:412
virtual MPI_Comm & get_comm() const =0
continuous field
Definition: definitions.h:176
virtual const Field * get_field_structure(const std::string &name)=0
get field structure
ublas::vector< double, DoubleAllocator > VectorDouble
Definition: Types.hpp:72
MoFEMErrorCode getRowNodesIndices(DataForcesAndSourcesCore &data, const std::string &field_name) const
get row node indices from FENumeredDofEntity_multiIndex
boost::shared_ptr< NumeredEntFiniteElement_multiIndex > numeredFiniteElements
store finite elements
virtual MoFEMErrorCode preProcess()
function is run at the beginning of loop
MoFEMErrorCode getSpacesAndBaseOnEntities(DataForcesAndSourcesCore &data) const
Get field approximation space and base on entities.
const std::array< boost::shared_ptr< DataForcesAndSourcesCore >, LASTSPACE > dataOnElement
Entity data on element entity rows fields.
boost::shared_ptr< const FENumeredDofEntity_multiIndex > colPtr
Pointer to finite element columns dofs view.
std::bitset< LASTBASE > bAse
bases on element
boost::shared_ptr< NumeredDofEntity_multiIndex > numeredDofsCols
store DOFs on columns for this problem
boost::function< MoFEMErrorCode()> preProcessHook
Hook function for pre-processing.
int getMaxColOrder() const
Get max order of approximation for field in columns.
MoFEMErrorCode getProblemRowIndices(const std::string filed_name, const EntityType type, const int side, VectorInt &indices) const
Get row indices.
RuleHookFun setRuleHook
Set function to calculate integration rule.
int getMaxDataOrder() const
Get max order of approximation for data fields.
MoFEMErrorCode loopSide(const string &fe_name, ForcesAndSourcesCore *side_fe, const size_t dim)
User call this function to loop over elements on the side of face. This function calls finite element...
boost::shared_ptr< const FENumeredDofEntity_multiIndex > rowPtr
Pointer to finite element rows dofs view.
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
MoFEMErrorCode getEntityRowIndices(DataForcesAndSourcesCore &data, const std::string &field_name, const EntityType type_lo=MBVERTEX, const EntityType type_hi=MBPOLYHEDRON) const
auto & getElementPolynomialBase()
Get the Entity Polynomial Base object.
multi_index_container< boost::shared_ptr< NumeredDofEntity >, indexed_by< ordered_unique< tag< Unique_mi_tag >, const_mem_fun< NumeredDofEntity::interface_type_DofEntity, const UId &, &NumeredDofEntity::getGlobalUniqueId > >, ordered_non_unique< tag< Unique_Ent_mi_tag >, const_mem_fun< NumeredDofEntity::interface_type_DofEntity, const UId &, &NumeredDofEntity::getEntGlobalUniqueId > >, 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< FieldName_mi_tag >, const_mem_fun< NumeredDofEntity::interface_type_Field, boost::string_ref, &NumeredDofEntity::getNameRef > >, 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 > >, ordered_non_unique< tag< Composite_Name_And_Ent_And_EntDofIdx_mi_tag >, composite_key< NumeredDofEntity, const_mem_fun< NumeredDofEntity::interface_type_Field, boost::string_ref, &NumeredDofEntity::getNameRef >, const_mem_fun< NumeredDofEntity::interface_type_DofEntity, EntityHandle, &NumeredDofEntity::getEnt >, const_mem_fun< NumeredDofEntity::interface_type_DofEntity, DofIdx, &NumeredDofEntity::getEntDofIdx > > >, ordered_non_unique< tag< Composite_Name_And_Part_mi_tag >, composite_key< NumeredDofEntity, const_mem_fun< NumeredDofEntity::interface_type_Field, boost::string_ref, &NumeredDofEntity::getNameRef >, member< NumeredDofEntity, unsigned int, &NumeredDofEntity::pArt > > >, ordered_non_unique< tag< Composite_Name_Ent_And_Part_mi_tag >, composite_key< NumeredDofEntity, const_mem_fun< NumeredDofEntity::interface_type_Field, boost::string_ref, &NumeredDofEntity::getNameRef >, const_mem_fun< NumeredDofEntity::interface_type_DofEntity, EntityHandle, &NumeredDofEntity::getEnt >, member< NumeredDofEntity, unsigned int, &NumeredDofEntity::pArt > > > > > NumeredDofEntity_multiIndex
MultiIndex container keeps NumeredDofEntity.
field with C-1 continuity
Definition: definitions.h:179