Flow123d  release_3.0.0-680-gbed5aba
output_mesh.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file output_mesh.cc
15  * @brief Classes for auxiliary output mesh.
16  */
17 
18 #include "mesh/side_impl.hh"
19 #include "output_mesh.hh"
20 #include "output_element.hh"
21 #include "mesh/mesh.h"
22 #include "mesh/ref_element.hh"
23 #include "mesh/long_idx.hh"
24 #include "mesh/accessors.hh"
25 #include "mesh/node_accessor.hh"
26 #include "mesh/range_wrapper.hh"
27 #include "la/distribution.hh"
28 
29 
30 namespace IT=Input::Type;
31 
33  return IT::Record("OutputMesh", "Parameters of the refined output mesh. [Not impemented]")
34  .declare_key("max_level", IT::Integer(1,20),IT::Default("3"),
35  "Maximal level of refinement of the output mesh.")
36  .declare_key("refine_by_error", IT::Bool(), IT::Default("false"),
37  "Set true for using ``error_control_field``. Set false for global uniform refinement to max_level.")
38  .declare_key("error_control_field",IT::String(), IT::Default::optional(),
39  "Name of an output field, according to which the output mesh will be refined. The field must be a SCALAR one.")
40  .declare_key("refinement_error_tolerance",IT::Double(0.0), IT::Default("0.01"),
41  "Tolerance for element refinement by error. If tolerance is reached, refinement is stopped."
42  "Relative difference between error control field and its linear approximation on element is computed"
43  "and compared with tolerance.")
44  .close();
45 }
46 
48 :
49  orig_mesh_(&mesh),
50  max_level_(0),
52  refine_by_error_(false),
54 {
55 }
56 
57 
59 :
60  input_record_(in_rec),
61  orig_mesh_(&mesh),
62  max_level_(input_record_.val<int>("max_level")),
64  refine_by_error_(input_record_.val<bool>("refine_by_error")),
65  refinement_error_tolerance_(input_record_.val<double>("refinement_error_tolerance"))
66 {
67 }
68 
70 {
71 }
72 
74 {
76 // ASSERT_DBG(offsets_->n_values() > 0);
77  return OutputElementIterator(OutputElement(0, shared_from_this()));
78 }
79 
81 {
83 // ASSERT_DBG(offsets_->n_values() > 0);
84  return OutputElementIterator(OutputElement(offsets_->n_values(), shared_from_this()));
85 }
86 
87 
89 {
90  error_control_field_func_ = error_control_field_func;
91 }
92 
94 {
96  return offsets_->n_values();
97 }
98 
100 {
102  return nodes_->n_values();
103 }
104 
106 {
107  unsigned int elm_idx[1];
108  unsigned int node_idx[1];
109  unsigned int region_idx[1];
110  int partition[1];
111  elem_ids_ = std::make_shared< ElementDataCache<unsigned int> >("elements_ids", (unsigned int)1, 1, this->n_elements());
112  node_ids_ = std::make_shared< ElementDataCache<unsigned int> >("node_ids", (unsigned int)1, 1, this->n_nodes());
113  region_ids_ = std::make_shared< ElementDataCache<unsigned int> >("region_ids", (unsigned int)1, 1, this->n_elements());
114  partitions_ = std::make_shared< ElementDataCache<int> >("partitions", (unsigned int)1, 1, this->n_elements());
115  OutputElementIterator it = this->begin();
116  for (unsigned int i = 0; i < this->n_elements(); ++i, ++it) {
117  if (mesh_type_ == MeshType::orig) elm_idx[0] = orig_mesh_->find_elem_id(it->idx());
118  else elm_idx[0] = it->idx();
119  elem_ids_->store_value( i, elm_idx );
120 
121  region_idx[0] = orig_mesh_->element_accessor(it->idx()).region().id();
122  region_ids_->store_value( i, region_idx );
123 
124  partition[0] = orig_mesh_->element_accessor(it->idx())->pid();
125  partitions_->store_value( i, partition );
126 
127  std::vector< unsigned int > node_list = it->node_list();
128  for (unsigned int j = 0; j < it->n_nodes(); ++j) {
129  if (mesh_type_ == MeshType::orig) node_idx[0] = orig_mesh_->find_node_id(node_list[j]);
130  else node_idx[0] = node_list[j];
131  node_ids_->store_value( node_list[j], node_idx );
132  }
133  }
134 }
135 
136 
138 {
139  return (nodes_ && connectivity_ && offsets_);
140 }
141 
142 
143 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
144 
145 
147 : OutputMeshBase(mesh)
148 {
149 }
150 
152 : OutputMeshBase(mesh, in_rec)
153 {
154 }
155 
156 
158 {
159 }
160 
161 
163 {
164  ASSERT( !is_created() ).error("Multiple initialization of OutputMesh!\n");
165 
166  DebugOut() << "Create outputmesh identical to computational one.";
167 
168  const unsigned int n_elements = orig_mesh_->n_elements(),
170 
171  nodes_ = std::make_shared<ElementDataCache<double>>("", (unsigned int)ElementDataCacheBase::N_VECTOR, 1, n_nodes);
172  unsigned int coord_id = 0, // coordinate id in vector
173  node_id = 0; // node id
174  auto &node_vec = *( nodes_->get_component_data(0).get() );
175  for (auto node : orig_mesh_->node_range()) {
176  node->aux = node_id; // store node index in the auxiliary variable
177 
178  // use store value
179  node_vec[coord_id] = node->getX(); coord_id++;
180  node_vec[coord_id] = node->getY(); coord_id++;
181  node_vec[coord_id] = node->getZ(); coord_id++;
182  node_id++;
183  }
184 
185  orig_element_indices_ = std::make_shared<std::vector<unsigned int>>(n_elements);
186 
187  offsets_ = std::make_shared<ElementDataCache<unsigned int>>("offsets", (unsigned int)ElementDataCacheBase::N_SCALAR, 1, n_elements);
188  unsigned int ele_id = 0,
189  connect_id = 0,
190  offset = 0, // offset of node indices of element in node vector
191  li; // local node index
192  auto &offset_vec = *( offsets_->get_component_data(0).get() );
193  for (auto ele : orig_mesh_->elements_range()) {
194  // increase offset by number of nodes of the simplicial element
195  offset += ele->dim() + 1;
196  offset_vec[ele_id] = offset;
197  (*orig_element_indices_)[ele_id] = ele_id;
198  ele_id++;
199  }
200 
201  const unsigned int n_connectivities = offset_vec[offset_vec.size()-1];
202  connectivity_ = std::make_shared<ElementDataCache<unsigned int>>("connectivity", (unsigned int)ElementDataCacheBase::N_SCALAR,
203  1, n_connectivities);
204  auto &connect_vec = *( connectivity_->get_component_data(0).get() );
205  for (auto ele : orig_mesh_->elements_range()) {
206  for (li=0; li<ele->n_nodes(); li++) {
207  connect_vec[connect_id] = ele.node_accessor(li)->aux;
208  connect_id++;
209  }
210 
211  }
212 }
213 
215 {
216  ASSERT(0).error("Not implemented yet.");
217 }
218 
219 
221 {
222  ASSERT(0).error("Not implemented yet.");
223  return false;
224 }
225 
226 
228 {
229  ASSERT(0).error("Not implemented yet.");
230 }
231 
232 
233 
234 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
235 
237 : OutputMeshBase(mesh)
238 {
239 }
240 
242 : OutputMeshBase(mesh, in_rec)
243 {
244 }
245 
246 
248 {
249 }
250 
251 
253 {
254  ASSERT( !is_created() ).error("Multiple initialization of OutputMesh!\n");
255 
256  ASSERT_DBG(orig_mesh_->n_nodes() > 0); //continuous data already computed
257 
258  if (nodes_) return; //already computed
259 
260  DebugOut() << "Create discontinuous outputmesh.";
261 
262  const unsigned int n_elements = orig_mesh_->n_elements();
263 
264  orig_element_indices_ = std::make_shared<std::vector<unsigned int>>(n_elements);
265  offsets_ = std::make_shared<ElementDataCache<unsigned int>>("offsets", (unsigned int)ElementDataCacheBase::N_SCALAR, 1, n_elements);
266 
267  unsigned int ele_id = 0,
268  offset = 0, // offset of node indices of element in node vector
269  coord_id = 0, // coordinate id in vector
270  corner_id = 0, // corner index (discontinous node)
271  li = 0; // local node index
272 
273  auto &offset_vec = *( offsets_->get_component_data(0).get() );
274  for (auto ele : orig_mesh_->elements_range()) {
275  // increase offset by number of nodes of the simplicial element
276  offset += ele->dim() + 1;
277  offset_vec[ele_id] = offset;
278  (*orig_element_indices_)[ele_id] = ele_id;
279  ele_id++;
280  }
281 
282  // connectivity = for every element list the nodes => its length corresponds to discontinuous data
283  const unsigned int n_corners = offset_vec[offset_vec.size()-1];
284 
285  nodes_ = std::make_shared<ElementDataCache<double>>("", (unsigned int)ElementDataCacheBase::N_VECTOR, 1, n_corners);
286  connectivity_ = std::make_shared<ElementDataCache<unsigned int>>("connectivity", (unsigned int)ElementDataCacheBase::N_SCALAR,
287  1, n_corners);
288 
289  auto &node_vec = *( nodes_->get_component_data(0).get() );
290  auto &conn_vec = *( connectivity_->get_component_data(0).get() );
291  NodeAccessor<3> node;
292  for (auto ele : orig_mesh_->elements_range()) {
293  for (li=0; li<ele->n_nodes(); li++)
294  {
295  node = ele.node_accessor(li);
296  node_vec[coord_id] = node->getX(); ++coord_id;
297  node_vec[coord_id] = node->getY(); ++coord_id;
298  node_vec[coord_id] = node->getZ(); ++coord_id;
299 
300  conn_vec[corner_id] = corner_id;
301  corner_id++;
302  }
303  }
304 
305  mesh_type_ = MeshType::discont;
306 }
307 
308 
310 {
311  DebugOut() << "Create refined discontinuous outputmesh.\n";
312  // initial guess of size: n_elements
313  nodes_ = std::make_shared<ElementDataCache<double>>("",(unsigned int)ElementDataCacheBase::N_VECTOR,1,0);
314  connectivity_ = std::make_shared<ElementDataCache<unsigned int>>("connectivity",(unsigned int)ElementDataCacheBase::N_SCALAR,1,0);
315  offsets_ = std::make_shared<ElementDataCache<unsigned int>>("offsets",(unsigned int)ElementDataCacheBase::N_SCALAR,1,0);
316  orig_element_indices_ = std::make_shared<std::vector<unsigned int>>();
317 
318  // index of last node added; set at the end of original ones
319  unsigned int last_offset = 0;
320 
321  auto &node_vec = *( nodes_->get_component_data(0).get() );
322  auto &conn_vec = *( connectivity_->get_component_data(0).get() );
323  auto &offset_vec = *( offsets_->get_component_data(0).get() );
324 
325  node_vec.reserve(4*orig_mesh_->n_nodes());
326  conn_vec.reserve(4*4*orig_mesh_->n_elements());
327  offset_vec.reserve(4*orig_mesh_->n_elements());
328 
329 // DebugOut() << "start refinement\n";
330  for (auto ele : orig_mesh_->elements_range()) {
331  const unsigned int
332  dim = ele->dim(),
333  ele_idx = ele.idx();
334 // DebugOut() << "ele index " << ele_idx << "\n";
335 
336  AuxElement aux_ele;
337  aux_ele.nodes.resize(ele->n_nodes());
338  aux_ele.level = 0;
339 
340  unsigned int li;
341  for (li=0; li<ele->n_nodes(); li++) {
342  aux_ele.nodes[li] = ele.node_accessor(li)->point();
343  }
344 
345  std::vector<AuxElement> refinement;
346 
347  switch(dim){
348  case 1: this->refine_aux_element<1>(aux_ele, refinement, ele); break;
349  case 2: this->refine_aux_element<2>(aux_ele, refinement, ele); break;
350  case 3: this->refine_aux_element<3>(aux_ele, refinement, ele); break;
351  default: ASSERT(0 < dim && dim < 4);
352  }
353 
354  //skip unrefined element
355 // if(refinement.size() < 2) continue;
356  unsigned int node_offset = node_vec.size(),
357  con_offset = conn_vec.size();
358  node_vec.resize(node_vec.size() + (refinement.size() * (dim+1))*spacedim);
359  conn_vec.resize(conn_vec.size() + refinement.size()*(dim+1));
360 // orig_element_indices_->resize(orig_element_indices_->size() + refinement.size()*(dim+1));
361 
362 // DebugOut() << "ref size = " << refinement.size() << "\n";
363  //gather coords and connectivity (in a continous way inside element)
364  for(unsigned int i=0; i < refinement.size(); i++)
365  {
366  last_offset += dim+1;
367  offset_vec.push_back(last_offset);
368  (*orig_element_indices_).push_back(ele_idx);
369  for(unsigned int j=0; j < dim+1; j++)
370  {
371  unsigned int con = i*(dim+1) + j;
372  conn_vec[con_offset + con] = con_offset + con;
373 
374  for(unsigned int k=0; k < spacedim; k++) {
375  node_vec[node_offset + con*spacedim + k] = refinement[i].nodes[j][k];
376  }
377  }
378  }
379  }
380 
381  conn_vec.shrink_to_fit();
382  node_vec.shrink_to_fit();
383  offset_vec.shrink_to_fit();
384 
385  connectivity_->set_n_values(conn_vec.size());
386  nodes_->set_n_values(node_vec.size() / spacedim);
387  offsets_->set_n_values(offset_vec.size());
388 
389  mesh_type_ = MeshType::refined;
390 // for(unsigned int i=0; i< nodes_->n_values; i++)
391 // {
392 // cout << i << " ";
393 // for(unsigned int k=0; k<spacedim; k++){
394 // nodes_->print(cout, i*spacedim+k);
395 // cout << " ";
396 // }
397 // cout << endl;
398 // }
399 // cout << "\n\n";
400 // // nodes_->print_all(cout);
401 // // cout << "\n\n";
402 // connectivity_->print_all(cout);
403 // cout << "\n\n";
404 // offsets_->print_all(cout);
405 }
406 
407 template<int dim>
410  const ElementAccessor<spacedim> &ele_acc)
411 {
412  static const unsigned int n_subelements = 1 << dim; //2^dim
413 
414 // The refinement of elements for the output mesh is done using edge splitting
415 // technique (so called red refinement). Since we use this only for better output
416 // visualization of non-polynomial solutions, we do not care for existence of hanging
417 // nodes.
418 // In 2D case, it is straightforward process: find the midpoints of all sides,
419 // connect them and generate 4 triangles. These triangles are congruent and have
420 // equal surface areas.
421 // On the other hand, the 3D case is more complicated. After splitting the
422 // edges, we obtain 4 tetrahedra at the vertices of the original one. The octahedron
423 // that remains in the middle can be subdivided according to one of its three
424 // diagonals. Only the choice of the shortest octahedron diagonal leads to a regular
425 // tetrahedra decomposition. This algorithm originally comes from Bey.
426 // Bey's algorithm (red refinement of tetrahedron):
427 // p.29 https://www5.in.tum.de/pub/Joshi2016_Thesis.pdf
428 // p.108 http://www.bcamath.org/documentos_public/archivos/publicaciones/sergey_book.pdf
429 // https://www.math.uci.edu/~chenlong/iFEM/doc/html/uniformrefine3doc.html#1
430 // J. Bey. Simplicial grid refinement: on Freudenthal's algorithm and the optimal number of congruence classes.
431 // Numer. Math. 85(1):1--29, 2000. p11 Algorithm: RedRefinement3D.
432 // p.4 http://www.vis.uni-stuttgart.de/uploads/tx_vispublications/vis97-grosso.pdf
433 
434  // connectivity of refined element
435  // these arrays are hardwired to the current reference element
436  static const std::vector<unsigned int> conn[] = {
437  {}, //0D
438 
439  //1D:
440  // 0,1 original nodes, 2 is in the middle
441  // get 2 elements
442  {0, 2,
443  2, 1},
444 
445  //2D:
446  // 0,1,2 original nodes
447  // 3,4,5 nodes are in the middle of sides 0,1,2 in the respective order
448  // get 4 elements
449  {0, 3, 4,
450  3, 1, 5,
451  4, 5, 2,
452  3, 5, 4},
453 
454  //3D:
455  // 0,1,2,3 original nodes
456  // 4,5,6,7,8,9 are nodes in the middle of edges 0,1,2,3,4,5 in the respective order
457  // first 4 tetrahedra are at the original nodes
458  // next 4 tetrahedra are from the inner octahedron - 4 choices according to the diagonal
459  {1, 7, 4, 8,
460  7, 2, 5, 9,
461  4, 5, 0, 6,
462  8, 9, 6, 3,
463  7, 4, 8, 9, // 4-9 octahedron diagonal
464  7, 4, 5, 9,
465  4, 8, 9, 6,
466  4, 5, 9, 6},
467 
468  {1, 7, 4, 8,
469  7, 2, 5, 9,
470  4, 5, 0, 6,
471  8, 9, 6, 3,
472  8, 5, 4, 6, // 5-8 octahedron diagonal
473  5, 8, 9, 6,
474  5, 8, 4, 7,
475  8, 5, 9, 7},
476 
477  {1, 7, 4, 8,
478  7, 2, 5, 9,
479  4, 5, 0, 6,
480  8, 9, 6, 3,
481  6, 8, 7, 9, // 6-7 octahedron diagonal
482  8, 6, 7, 4,
483  6, 5, 7, 4,
484  5, 6, 7, 9}
485  };
486 // DBGMSG("level = %d, %d\n", aux_element.level, max_refinement_level_);
487 
488  ASSERT_DBG(dim == aux_element.nodes.size()-1);
489 
490  // if not refining any further, push into final vector
491  if( ! refinement_criterion(aux_element, ele_acc) ) {
492  refinement.push_back(aux_element);
493  return;
494  }
495 
496  std::vector<AuxElement> subelements(n_subelements);
497 
498  const unsigned int n_old_nodes = RefElement<dim>::n_nodes,
499  n_new_nodes = RefElement<dim>::n_lines; // new points are in the center of lines
500 
501  // auxiliary vectors
502  std::vector<Space<spacedim>::Point> nodes = aux_element.nodes;
503 
504  nodes.reserve(n_old_nodes+n_new_nodes);
505 
506  // create new points in the element
507  for(unsigned int e=0; e < n_new_nodes; e++)
508  {
511  nodes.push_back( p / 2.0);
512  //nodes.back().print();
513  }
514 
515  unsigned int diagonal = 0;
516  // find shortest diagonal: [0]:4-9, [1]:5-8 or [2]:6-7
517  if(dim == 3){
518  double min_diagonal = arma::norm(nodes[4]-nodes[9],2);
519  double d = arma::norm(nodes[5]-nodes[8],2);
520  if(d < min_diagonal){
521  min_diagonal = d;
522  diagonal = 1;
523  }
524  d = arma::norm(nodes[6]-nodes[7],2);
525  if(d < min_diagonal){
526  min_diagonal = d;
527  diagonal = 2;
528  }
529  }
530 
531  for(unsigned int i=0; i < n_subelements; i++)
532  {
533  AuxElement& sub_ele = subelements[i];
534  sub_ele.nodes.resize(n_old_nodes);
535  sub_ele.level = aux_element.level+1;
536 
537  // over nodes
538  for(unsigned int j=0; j < n_old_nodes; j++)
539  {
540  unsigned int conn_id = (n_old_nodes)*i + j;
541  sub_ele.nodes[j] = nodes[conn[dim+diagonal][conn_id]];
542  }
543  refine_aux_element<dim>(sub_ele, refinement, ele_acc);
544  }
545 }
546 
548 {
549  ASSERT( !is_created() ).error("Multiple initialization of OutputMesh!\n");
550 
551  DebugOut() << "Create output submesh containing only local elements.";
552 
553  ElementAccessor<3> ele;
554  LongIdx *el_4_loc = orig_mesh_->get_el_4_loc();
555  Distribution *el_ds = orig_mesh_->get_el_ds();
556  const unsigned int n_local_elements = el_ds->lsize();
557 
558  orig_element_indices_ = std::make_shared<std::vector<unsigned int>>(n_local_elements);
559  offsets_ = std::make_shared<ElementDataCache<unsigned int>>("offsets", (unsigned int)ElementDataCacheBase::N_SCALAR, 1, n_local_elements);
560 
561  unsigned int ele_id = 0,
562  offset = 0, // offset of node indices of element in node vector
563  coord_id = 0, // coordinate id in vector
564  corner_id = 0, // corner index (discontinous node)
565  li = 0; // local node index
566  auto &offset_vec = *( offsets_->get_component_data(0).get() );
567  for (unsigned int loc_el = 0; loc_el < n_local_elements; loc_el++) {
568  ele = orig_mesh_->element_accessor( el_4_loc[loc_el] );
569  // increase offset by number of nodes of the simplicial element
570  offset += ele->dim() + 1;
571  offset_vec[ele_id] = offset;
572  (*orig_element_indices_)[ele_id] = el_4_loc[loc_el];
573  ele_id++;
574  }
575 
576  // connectivity = for every element list the nodes => its length corresponds to discontinuous data
577  const unsigned int n_corners = offset_vec[offset_vec.size()-1];
578 
579  nodes_ = std::make_shared<ElementDataCache<double>>("", (unsigned int)ElementDataCacheBase::N_VECTOR, 1, n_corners);
580  connectivity_ = std::make_shared<ElementDataCache<unsigned int>>("connectivity", (unsigned int)ElementDataCacheBase::N_SCALAR,
581  1, n_corners);
582 
583  auto &node_vec = *( nodes_->get_component_data(0).get() );
584  auto &conn_vec = *( connectivity_->get_component_data(0).get() );
585  NodeAccessor<3> node;
586  for (unsigned int loc_el = 0; loc_el < n_local_elements; loc_el++) {
587  ele = orig_mesh_->element_accessor( el_4_loc[loc_el] );
588  for (li=0; li<ele->n_nodes(); li++)
589  {
590  node = ele.node_accessor(li);
591  node_vec[coord_id] = node->getX(); ++coord_id;
592  node_vec[coord_id] = node->getY(); ++coord_id;
593  node_vec[coord_id] = node->getZ(); ++coord_id;
594 
595  conn_vec[corner_id] = corner_id;
596  corner_id++;
597  }
598  }
599 }
600 
601 
602 template void OutputMeshDiscontinuous::refine_aux_element<1>(const OutputMeshDiscontinuous::AuxElement&,std::vector< OutputMeshDiscontinuous::AuxElement >&, const ElementAccessor<spacedim> &);
603 template void OutputMeshDiscontinuous::refine_aux_element<2>(const OutputMeshDiscontinuous::AuxElement&,std::vector< OutputMeshDiscontinuous::AuxElement >&, const ElementAccessor<spacedim> &);
604 template void OutputMeshDiscontinuous::refine_aux_element<3>(const OutputMeshDiscontinuous::AuxElement&,std::vector< OutputMeshDiscontinuous::AuxElement >&, const ElementAccessor<spacedim> &);
605 
606 
608  const ElementAccessor<spacedim> &ele_acc)
609 {
610  // check refinement criteria:
611 
612  //first check max. level
613  bool refine = refinement_criterion_uniform(aux_ele);
614 
615  //if max. level not reached and refinement by error is set
616  if(refine && refine_by_error_)
617  {
618  // compute centre of aux element
619  Space<spacedim>::Point centre({0,0,0});
620  for(auto& v : aux_ele.nodes ) centre += v;
621  centre = centre/aux_ele.nodes.size();
622  return refinement_criterion_error(aux_ele, centre, ele_acc);
623  }
624 
625  return refine;
626 }
627 
629 {
630  return (ele.level < max_level_);
631 }
632 
634  const Space<spacedim>::Point &centre,
635  const ElementAccessor<spacedim> &ele_acc
636  )
637 {
638  ASSERT_DBG(error_control_field_func_).error("Error control field not set!");
639 
640  // evaluate at nodes and center in a single call
641  std::vector<double> val_list(ele.nodes.size()+1);
643  point_list.push_back(centre);
644  point_list.insert(point_list.end(), ele.nodes.begin(), ele.nodes.end());
645  error_control_field_func_(point_list, ele_acc, val_list);
646 
647  //TODO: compute L1 or L2 error using standard quadrature
648 
649  //compare average value at nodes with value at center
650 
651  double average_val = 0.0;
652  for(unsigned int i=1; i<ele.nodes.size()+1; ++i)//(double& v: nodes_val)
653  average_val += val_list[i];
654  average_val = average_val / ele.nodes.size();
655 
656  double diff = std::abs((average_val - val_list[0])/val_list[0]);
657 // DebugOut().fmt("diff: {} {} {}\n", diff, average_val, val_list[0]);
658  return ( diff > refinement_error_tolerance_);
659 
660 }
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
Definition: long_idx.hh:22
Classes for auxiliary output mesh.
void create_refined_mesh() override
Creates refined mesh.
Definition: output_mesh.cc:214
static const unsigned int spacedim
Shortcut instead of spacedim template. We suppose only spacedim=3 at the moment.
Definition: output_mesh.hh:65
unsigned int n_nodes() const
Definition: elements.h:129
Iter< OutputElement > OutputElementIterator
Definition: output_mesh.hh:32
Base class for Output mesh.
Definition: output_mesh.hh:61
double getY() const
Definition: nodes.hh:58
NodeAccessor< 3 > node_accessor(unsigned int ni) const
Definition: accessors.hh:149
std::function< void(const std::vector< Space< spacedim >::Point > &, const ElementAccessor< spacedim > &, std::vector< double > &)> ErrorControlFieldFunc
Definition: output_mesh.hh:68
bool refinement_criterion_error(const AuxElement &ele, const Space< spacedim >::Point &centre, const ElementAccessor< spacedim > &ele_acc)
Refinement flag - measures discretisation error according to error control field. ...
Definition: output_mesh.cc:633
unsigned int n_elements()
Returns number of element.
Definition: output_mesh.cc:93
Mesh * orig_mesh_
Pointer to the computational mesh.
Definition: output_mesh.hh:126
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
Class for declaration of the input of type Bool.
Definition: type_base.hh:459
void create_mesh() override
Creates the output mesh identical to the orig mesh.
Definition: output_mesh.cc:252
void create_mesh() override
Creates the output mesh identical to the orig mesh.
Definition: output_mesh.cc:162
static const Input::Type::Record & get_input_type()
The specification of output mesh.
Definition: output_mesh.cc:32
const unsigned int max_level_
Maximal level of refinement.
Definition: output_mesh.hh:129
Definition: mesh.h:80
double refinement_error_tolerance_
Tolerance for error criterion refinement.
Definition: output_mesh.hh:136
std::shared_ptr< ElementDataCache< unsigned int > > connectivity_
Vector maps the nodes to their coordinates in vector nodes_.
Definition: output_mesh.hh:144
bool refinement_criterion(const AuxElement &ele, const ElementAccessor< spacedim > &ele_acc)
Collects different refinement criteria results.
Definition: output_mesh.cc:607
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:346
virtual unsigned int n_nodes() const
Definition: mesh.h:133
std::shared_ptr< ElementDataCache< unsigned int > > node_ids_
Vector gets ids of nodes. Data is used in GMSH output.
Definition: output_mesh.hh:149
Class for declaration of the integral input data.
Definition: type_base.hh:490
std::shared_ptr< ElementDataCache< unsigned int > > offsets_
Vector of offsets of node indices of elements. Maps elements to their nodes in connectivity_.
Definition: output_mesh.hh:146
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:303
unsigned int n_nodes()
Returns number of nodes.
Definition: output_mesh.cc:99
virtual ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
Definition: mesh.cc:719
std::shared_ptr< ElementDataCache< double > > nodes_
Vector of node coordinates. [spacedim x n_nodes].
Definition: output_mesh.hh:142
OutputMesh(Mesh &mesh)
Definition: output_mesh.cc:146
double getZ() const
Definition: nodes.hh:60
unsigned int dim() const
Definition: elements.h:124
static Default optional()
The factory function to make an empty default value which is optional.
Definition: type_record.hh:124
Class for declaration of the input data that are floating point numbers.
Definition: type_base.hh:541
int find_elem_id(unsigned int pos) const
Return element id (in GMSH file) of element of given position in element vector.
Definition: mesh.h:361
ErrorControlFieldFunc error_control_field_func_
Refinement error control field function (hold value_list function of field).
Definition: output_mesh.hh:132
arma::vec::fixed< spacedim > Point
Definition: point.hh:42
Accessor to the data with type Type::Record.
Definition: accessors.hh:292
static const IdxVector< (InDim >OutDim?InDim+1:dim-InDim) > interact(TInteraction< OutDim, InDim > interaction)
double getX() const
Definition: nodes.hh:56
Auxiliary structure defining element of refined output mesh.
Definition: output_mesh.hh:209
void refine_aux_element(const AuxElement &aux_element, std::vector< AuxElement > &refinement, const ElementAccessor< spacedim > &ele_acc)
Performs the actual refinement of AuxElement. Recurrent.
Definition: output_mesh.cc:408
void set_error_control_field(ErrorControlFieldFunc error_control_field_func)
Selects the error control field computing function of output field set according to input record...
Definition: output_mesh.cc:88
std::shared_ptr< ElementDataCache< unsigned int > > region_ids_
Vector gets ids of regions. Data is used in GMSH output.
Definition: output_mesh.hh:153
Record & declare_key(const string &key, std::shared_ptr< TypeBase > type, const Default &default_value, const string &description, TypeBase::attribute_map key_attributes=TypeBase::attribute_map())
Declares a new key of the Record.
Definition: type_record.cc:501
bool refinement_criterion()
Definition: output_mesh.cc:220
virtual ~OutputMeshBase()
Definition: output_mesh.cc:69
virtual Range< ElementAccessor< 3 > > elements_range() const
Returns range of bulk elements.
Definition: mesh.cc:1033
void create_sub_mesh() override
Creates sub mesh.
Definition: output_mesh.cc:227
Distribution * get_el_ds() const
Definition: mesh.h:168
OutputMeshDiscontinuous(Mesh &mesh)
Definition: output_mesh.cc:236
Input::Record input_record_
Input record for output mesh.
Definition: output_mesh.hh:123
General iterator template. Provides iterator over objects in some container.
bool refinement_criterion_uniform(const AuxElement &ele)
Refinement flag - checks only maximal level of refinement.
Definition: output_mesh.cc:628
OutputElementIterator end()
Gives iterator to the LAST element of the output mesh.
Definition: output_mesh.cc:80
Support classes for parallel programing.
friend class OutputElement
Friend provides access to vectors for element accessor class.
Definition: output_mesh.hh:158
virtual unsigned int n_elements(bool boundary=false) const
Returns count of boundary or bulk elements.
Definition: mesh.h:346
std::shared_ptr< ElementDataCache< int > > partitions_
Vector gets partitions of elements. Data is used in GMSH output.
Definition: output_mesh.hh:155
#define ASSERT_PTR(ptr)
Definition of assert macro checking non-null pointer (PTR)
Definition: asserts.hh:335
bool refine_by_error_
True, if output mesh is to be refined by error criterion.
Definition: output_mesh.hh:135
Class OutputElement and its iterator OutputElementIterator on the output mesh.
#define ASSERT_DBG(expr)
Definition: asserts.hh:349
Class RefElement defines numbering of vertices, sides, calculation of normal vectors etc...
Range< NodeAccessor< 3 > > node_range() const
Returns range of nodes.
Definition: mesh.cc:1039
MeshType mesh_type_
Type of OutputMesh.
Definition: output_mesh.hh:134
Record type proxy class.
Definition: type_record.hh:182
std::vector< Space< spacedim >::Point > nodes
Definition: output_mesh.hh:210
void create_id_caches()
Create nodes and elements data caches.
Definition: output_mesh.cc:105
bool is_created()
Check if nodes_, connectivity_ and offsets_ data caches are created.
Definition: output_mesh.cc:137
std::shared_ptr< ElementDataCache< unsigned int > > elem_ids_
Vector gets ids of elements. Data is used in GMSH output.
Definition: output_mesh.hh:151
#define DebugOut()
Macro defining &#39;debug&#39; record of log.
Definition: logger.hh:252
#define ASSERT_PTR_DBG(ptr)
Definition of assert macro checking non-null pointer (PTR) only for debug mode.
Definition: asserts.hh:339
void create_refined_mesh() override
Creates discontinuous refined mesh.
Definition: output_mesh.cc:309
Class for declaration of the input data that are in string format.
Definition: type_base.hh:589
LongIdx * get_el_4_loc() const
Definition: mesh.h:174
same as original (computational) mesh
Definition: output_mesh.hh:116
Implementation of range helper class.
std::shared_ptr< std::vector< unsigned int > > orig_element_indices_
Vector of element indices in the computational mesh. (Important when refining.)
Definition: output_mesh.hh:139
OutputElementIterator begin()
Gives iterator to the FIRST element of the output mesh.
Definition: output_mesh.cc:73
void create_sub_mesh() override
Creates sub mesh.
Definition: output_mesh.cc:547
int find_node_id(unsigned int pos) const
Return node id (in GMSH file) of node of given position in node vector.
Definition: mesh.h:373
OutputMeshBase(Mesh &mesh)
Constructor. Takes computational mesh as a parameter.
Definition: output_mesh.cc:47
unsigned int lsize(int proc) const
get local size