refineable_mesh.h
Go to the documentation of this file.
1 //LIC// ====================================================================
2 //LIC// This file forms part of oomph-lib, the object-oriented,
3 //LIC// multi-physics finite-element library, available
4 //LIC// at http://www.oomph-lib.org.
5 //LIC//
6 //LIC// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 #ifndef OOMPH_REFINEABLE_MESH_HEADER
31 #define OOMPH_REFINEABLE_MESH_HEADER
32 
33 #include "mesh.h"
34 #include "refineable_elements.h"
35 //Include the tree template to fill in the C++ split function
36 //Must be called after refineable_element.h
37 #include "tree.template.cc"
38 #include "error_estimator.h"
39 
40 namespace oomph
41 {
42 
43 
44 
45 
46 
47 
48 //=======================================================================
49 /// Base class for refineable meshes. Provides standardised interfaces
50 /// for the following standard mesh adaptation routines:
51 /// - Uniform mesh refinement.
52 /// - Adaptation, based on the elemental error estimates obtained
53 /// from an error estimator function which is accessed via a function
54 /// pointer.
55 ///
56 //=======================================================================
57 class RefineableMeshBase : public virtual Mesh
58 {
59 public:
60 
61  bool adapt_flag() {return Adapt_flag;}
62 
63  /// Constructor sets default values for refinement targets etc.
64  /// and initialises pointer to spatial error estimator to NULL.
66  {
67  // Initialise pointer to spatial error estimator
69 
70  // Targets
71  Min_permitted_error=1.0e-5;
72  Max_permitted_error=1.0e-3;
73 
74  //Actual errors
75  Min_error = 0.0;
76  Max_error = 0.0;
77 
78  // Do I adapt or not?
79  Adapt_flag=true;
80 
81  // Do I p-adapt or not?
82  P_adapt_flag=true;
83 
84  // Do I disable additional synchronisation of hanging nodes?
86 
87  // Where do I write the documatation of the refinement process?
88  Doc_info_pt=0;
89 
90  // If only a few elements are scheduled for unrefinement, don't bother
91  // By default unrefine all
93 
94  // Number of elements where the refinement is over-ruled
96  };
97 
98 
99  /// Broken copy constructor
101  {
102  BrokenCopy::broken_copy("RefineableMeshBase");
103  }
104 
105  /// Broken assignment operator
107  {
108  BrokenCopy::broken_assign("RefineableMeshBase");
109  }
110 
111  /// Empty Destructor:
113  {
114  }
115 
116  /// Access fct for number of elements that were refined
117  unsigned nrefined() {return Nrefined;}
118 
119  /// Access fct for number of elements that were unrefined
120  unsigned nunrefined() {return Nunrefined;}
121 
122  /// \short Number of elements that would have liked to be refined further
123  /// but can't because they've reached the max. refinement level
125 
126  /// \short Max. number of elements that we allow to remain unrefined
127  /// if no other mesh adaptation is required (to avoid
128  /// mesh-adaptations that would only unrefine a few elements
129  /// and then force a new solve -- this can't be worth our while!)
131 
132  /// Doc the targets for mesh adaptation
133  virtual void doc_adaptivity_targets(std::ostream &outfile)
134  {
135  outfile << std::endl;
136  outfile << "Targets for mesh adaptation: " << std::endl;
137  outfile << "---------------------------- " << std::endl;
138  outfile << "Target for max. error: " << Max_permitted_error << std::endl;
139  outfile << "Target for min. error: " << Min_permitted_error << std::endl;
140  outfile << "Don't unrefine if less than " << Max_keep_unrefined
141  << " elements need unrefinement." << std::endl;
142  outfile << std::endl;
143  }
144 
145 
146  /// Access to spatial error estimator
148  {
150  }
151 
152  /// Access to spatial error estimator (const version
154  {
156  }
157 
158  /// \short Access fct for min. error (i.e. (try to) merge elements if
159  /// their error is smaller)
161 
162  /// \short Access fct for max. error (i.e. split elements if their
163  /// error is larger)
165 
166  /// \short Access fct for min. actual error in present solution (i.e. before
167  /// re-solve on adapted mesh)
168  double& min_error() {return Min_error;}
169 
170  /// \short Access fct for max. actual error in present solution (i.e. before
171  /// re-solve on adapted mesh)
172  double& max_error() {return Max_error;}
173 
174  /// Access fct for pointer to DocInfo
176 
177  /// Enable adaptation
179 
180  /// Disable adaptation
182 
183  /// Enable adaptation
185 
186  /// Disable adaptation
188 
189  /// Enable additional synchronisation of hanging nodes
192 
193  /// Disable additional synchronisation of hanging nodes
196 
197  /// Return whether the mesh is to be adapted
198  bool is_adaptation_enabled() const {return Adapt_flag;}
199 
200  /// Return whether the mesh is to be adapted
201  bool is_p_adaptation_enabled() const {return P_adapt_flag;}
202 
203  /// Return whether additional synchronisation is enabled
206 
207  /// Access fct for DocInfo
209  {
210  return *Doc_info_pt;
211  }
212 
213  /// \short Adapt mesh: Refine elements whose error is lager than err_max
214  /// and (try to) unrefine those whose error is smaller than err_min
215  virtual void adapt(const Vector<double>& elemental_error)=0;
216 
217  /// \short p-adapt mesh: Refine elements whose error is lager than err_max
218  /// and (try to) unrefine those whose error is smaller than err_min
219  virtual void p_adapt(const Vector<double>& elemental_error)
220  {
221  //Derived classes must implement this as required. Default throws an error.
222  std::ostringstream err_stream;
223  err_stream << "p_adapt() called in base class RefineableMeshBase."
224  << std::endl
225  << "This needs to be implemented in the derived class."
226  << std::endl;
227  throw OomphLibError(err_stream.str(),
228  OOMPH_CURRENT_FUNCTION,
229  OOMPH_EXCEPTION_LOCATION);
230  }
231 
232  /// Refine mesh uniformly and doc process
233  virtual void refine_uniformly(DocInfo& doc_info)=0;
234 
235  /// Refine mesh uniformly
236  virtual void refine_uniformly()
237  {
239  doc_info.directory()="";
240  doc_info.disable_doc();
241  refine_uniformly(doc_info);
242  }
243 
244  /// p-refine mesh uniformly and doc process
245  virtual void p_refine_uniformly(DocInfo& doc_info)
246  {
247  //Derived classes must implement this as required. Default throws an error.
248  std::ostringstream err_stream;
249  err_stream << "p_refine_uniformly() called in base class RefineableMeshBase."
250  << std::endl
251  << "This needs to be implemented in the derived class."
252  << std::endl;
253  throw OomphLibError(err_stream.str(),
254  OOMPH_CURRENT_FUNCTION,
255  OOMPH_EXCEPTION_LOCATION);
256  }
257 
258  /// p-refine mesh uniformly
259  virtual void p_refine_uniformly()
260  {
262  doc_info.directory()="";
263  doc_info.disable_doc();
264  p_refine_uniformly(doc_info);
265  }
266 
267  /// \short Unrefine mesh uniformly: Return 0 for success,
268  /// 1 for failure (if unrefinement has reached the coarsest permitted
269  /// level)
270  virtual unsigned unrefine_uniformly()=0;
271 
272  /// \short p-unrefine mesh uniformly
274  {
275  //Derived classes must implement this as required. Default throws an error.
276  std::ostringstream err_stream;
277  err_stream << "p_unrefine_uniformly() called in base class RefineableMeshBase."
278  << std::endl
279  << "This needs to be implemented in the derived class."
280  << std::endl;
281  throw OomphLibError(err_stream.str(),
282  OOMPH_CURRENT_FUNCTION,
283  OOMPH_EXCEPTION_LOCATION);
284  }
285 
286 protected:
287 
288  /// \short Pointer to spatial error estimator
290 
291  /// Max. error (i.e. split elements if their error is larger)
293 
294  /// Min. error (i.e. (try to) merge elements if their error is smaller)
296 
297  /// Min.actual error
298  double Min_error;
299 
300  /// Max. actual error
301  double Max_error;
302 
303  /// Stats: Number of elements that were refined
304  unsigned Nrefined;
305 
306  /// Stats: Number of elements that were unrefined
307  unsigned Nunrefined;
308 
309  /// Flag that requests adaptation
311 
312  /// Flag that requests p-adaptation
314 
315  /// Flag that disables additional synchronisation of hanging nodes
317 
318  /// Pointer to DocInfo
320 
321  /// \short Max. number of elements that can remain unrefined
322  /// if no other mesh adaptation is required (to avoid
323  /// mesh-adaptations that would only unrefine a few elements
324  /// and then force a new solve -- this can't be worth our while!)
326 
327  /// \short Number of elements that would like to be refined further but can't
328  /// because they've reached the max. refinement level
330 
331 };
332 
333 
334 
335 
336 ////////////////////////////////////////////////////////////////////
337 ////////////////////////////////////////////////////////////////////
338 ////////////////////////////////////////////////////////////////////
339 
340 
341 
342 //=======================================================================
343 /// Base class for tree-based refineable meshes.
344 //=======================================================================
346 {
347 public:
348 
349 
350  /// Constructor
352  {
353  // Max/min refinement levels
354  Max_refinement_level=5;
355  Min_refinement_level=0;
356 
357  // Max/min p-refinement levels
358  Max_p_refinement_level=7;
359  Min_p_refinement_level=2;
360 
361  // Stats
362  Nrefined=0;
363  Nunrefined=0;
364 
365  // Where do I write the documatation of the refinement process?
366  Doc_info_pt=0;
367 
368  // Initialise the forest pointer to NULL
369  Forest_pt = 0;
370 
371  // Mesh hasn't been pruned yet
372  Uniform_refinement_level_when_pruned=0;
373  }
374 
375 
376  /// Broken copy constructor
378  {
379  BrokenCopy::broken_copy("TreeBasedRefineableMeshBase");
380  }
381 
382  /// Broken assignment operator
384  {
385  BrokenCopy::broken_assign("TreeBasedRefineableMeshBase");
386  }
387 
388  /// Empty Destructor:
390  {
391  //Kill the forest if there is one
392  if(Forest_pt!=0)
393  {
394  delete Forest_pt;
395  Forest_pt=0;
396  }
397  }
398 
399  /// \short Adapt mesh: Refine elements whose error is lager than err_max
400  /// and (try to) unrefine those whose error is smaller than err_min
401  void adapt(const Vector<double>& elemental_error);
402 
403  /// \short p-adapt mesh: Refine elements whose error is lager than err_max
404  /// and (try to) unrefine those whose error is smaller than err_min
405  void p_adapt(const Vector<double>& elemental_error);
406 
407  /// Refine mesh uniformly and doc process
409 
410  /// Refine mesh uniformly
412  {
414  }
415 
416  /// p-refine mesh uniformly and doc process
417  void p_refine_uniformly(DocInfo& doc_info);
418 
419  /// p-refine mesh uniformly
421  {
423  }
424 
425  /// \short Unrefine mesh uniformly: Return 0 for success,
426  /// 1 for failure (if unrefinement has reached the coarsest permitted
427  /// level)
428  unsigned unrefine_uniformly();
429 
430  /// \short p-unrefine mesh uniformly
431  void p_unrefine_uniformly(DocInfo& doc_info);
432 
433  /// Set up the tree forest associated with the Mesh (if any)
434  virtual void setup_tree_forest()=0;
435 
436  /// Return pointer to the Forest represenation of the mesh
437  TreeForest* forest_pt(){return Forest_pt;}
438 
439 
440  /// Doc the targets for mesh adaptation
441  void doc_adaptivity_targets(std::ostream &outfile)
442  {
443  outfile << std::endl;
444  outfile << "Targets for mesh adaptation: " << std::endl;
445  outfile << "---------------------------- " << std::endl;
446  outfile << "Target for max. error: " << Max_permitted_error << std::endl;
447  outfile << "Target for min. error: " << Min_permitted_error << std::endl;
448  outfile << "Min. refinement level: " << Min_refinement_level << std::endl;
449  outfile << "Max. refinement level: " << Max_refinement_level << std::endl;
450  outfile << "Min. p-refinement level: " << Min_p_refinement_level
451  << std::endl;
452  outfile << "Max. p-refinement level: " << Max_p_refinement_level
453  << std::endl;
454  outfile << "Don't unrefine if less than " << Max_keep_unrefined
455  << " elements need unrefinement." << std::endl;
456  outfile << std::endl;
457  }
458 
459  /// Access fct for max. permissible refinement level (relative to base mesh)
460  unsigned& max_refinement_level() {return Max_refinement_level;}
461 
462  /// Access fct for min. permissible refinement level (relative to base mesh)
463  unsigned& min_refinement_level() {return Min_refinement_level;}
464 
465  /// Access fct for max. permissible p-refinement level (relative to base mesh)
466  unsigned& max_p_refinement_level() {return Max_p_refinement_level;}
467 
468  /// Access fct for min. permissible p-refinement level (relative to base mesh)
469  unsigned& min_p_refinement_level() {return Min_p_refinement_level;}
470 
471  /// \short Perform the actual tree-based mesh adaptation,
472  /// documenting the progress in the directory specified in DocInfo object.
473  virtual void adapt_mesh(DocInfo& doc_info);
474 
475  /// \short Perform the actual tree-based mesh adaptation. A simple wrapper to
476  /// call the function without documentation.
477  virtual void adapt_mesh()
478  {
479  //Create a dummy doc_info object
481  doc_info.directory()="";
482  doc_info.disable_doc();
483  //Call the other adapt mesh
484  adapt_mesh(doc_info);
485  }
486 
487  /// \short Perform the actual tree-based mesh p-adaptation,
488  /// documenting the progress in the directory specified in DocInfo object.
489  void p_adapt_mesh(DocInfo& doc_info);
490 
491  /// \short Perform the actual tree-based mesh p-adaptation. A simple wrapper
492  /// to call the function without documentation.
494  {
495  //Create a dummy doc_info object
497  doc_info.directory()="";
498  doc_info.disable_doc();
499  //Call the other adapt mesh
500  p_adapt_mesh(doc_info);
501  }
502 
503  /// \short Refine mesh by splitting the elements identified
504  /// by their numbers.
505  virtual void refine_selected_elements(const Vector<unsigned>&
506  elements_to_be_refined);
507 
508  /// \short Refine mesh by splitting the elements identified
509  /// by their pointers.
510  virtual void refine_selected_elements(const Vector<RefineableElement*>&
511  elements_to_be_refined);
512 
513  /// \short p-refine mesh by refining the elements identified
514  /// by their numbers.
515  void p_refine_selected_elements(const Vector<unsigned>&
516  elements_to_be_refined);
517 
518  /// \short p-refine mesh by refining the elements identified
519  /// by their pointers.
520  void p_refine_selected_elements(const Vector<PRefineableElement*>&
521  elements_to_be_refined_pt);
522 
523 
524  /// \short Refine base mesh to same degree as reference mesh (relative
525  /// to original unrefined mesh).
526  virtual void refine_base_mesh_as_in_reference_mesh(
527  TreeBasedRefineableMeshBase* const &ref_mesh_pt);
528 
529  /// \short Refine base mesh to same degree as reference mesh minus one
530  /// level of refinement (relative to original unrefined mesh). Useful
531  /// function for multigrid solvers; allows the easy copy of a mesh
532  /// to the level of refinement just below the current one
533  virtual bool refine_base_mesh_as_in_reference_mesh_minus_one(
534  TreeBasedRefineableMeshBase* const &ref_mesh_pt);
535 
536  /// \short Refine mesh once so that its topology etc becomes that of the
537  /// (finer!) reference mesh -- if possible! Useful for meshes in multigrid
538  /// hierarchies. If the meshes are too different and the conversion
539  /// cannot be performed, the code dies (provided PARANOID is enabled).
540  virtual void refine_as_in_reference_mesh(TreeBasedRefineableMeshBase*
541  const &ref_mesh_pt);
542 
543  /// Get max/min refinement levels in mesh
544  virtual void get_refinement_levels(unsigned& min_refinement_level,
545  unsigned& max_refinement_level);
546 
547  /// \short Extract the elements at a particular refinement level in
548  /// the refinement pattern - used in Mesh::redistribute or whatever it's
549  /// going to be called (RefineableMeshBase::reduce_halo_layers or something)
550  virtual void get_elements_at_refinement_level(
551  unsigned& refinement_level, Vector<RefineableElement*>& level_elements);
552 
553  /// \short Extract refinement pattern: Consider the hypothetical mesh
554  /// obtained by truncating the refinement of the current mesh to a given
555  /// level (where \c level=0 is the un-refined base mesh). To advance
556  /// to the next refinement level, we need to refine (split) the
557  /// \c to_be_refined[level].size() elements identified by the
558  /// element numbers contained in \c vector to_be_refined[level][...]
559  virtual void get_refinement_pattern(Vector<Vector<unsigned> >&
560  to_be_refined);
561 
562  /// Refine base mesh according to specified refinement pattern
563  void refine_base_mesh(Vector<Vector<unsigned> >& to_be_refined);
564 
565  /// Refine mesh according to refinement pattern in restart file
566  virtual void refine(std::ifstream& restart_file);
567 
568  /// Dump refinement pattern to allow for rebuild
569  virtual void dump_refinement(std::ostream &outfile);
570 
571  /// Read refinement pattern to allow for rebuild
572  virtual void read_refinement(std::ifstream& restart_file,
573  Vector<Vector<unsigned> >& to_be_refined);
574 
575 
576  /// \short Level to which the mesh was uniformly refined when it was pruned
577  /// (const version)
579  {
580  return Uniform_refinement_level_when_pruned;
581  }
582 
583 
584  /// \short Level to which the mesh was uniformly refined when it was pruned
586  {
587  return Uniform_refinement_level_when_pruned;
588  }
589 
590 #ifdef OOMPH_HAS_MPI
591 
592  /// Classify all halo and haloed information in the mesh (overloaded
593  /// version from Mesh base class. Calls that one first, then synchronises
594  /// hanging nodes)
596  const bool& report_stats)
597  {
598  // Call version in base class but don't bother to call
599  // resize_halo_nodes() -- we'll do it ourselves below
600  bool backup=Resize_halo_nodes_not_required;
603  report_stats);
605 
606  double t_start=0.0;
608  {
609  t_start = TimingHelpers::timer();
610  }
611 
612  // Communicate positions of non-hanging nodes that depend on non-existent
613  // neighbours (e.g. h-refinement of neighbouring elements with different
614  // p-orders where the shared edge is on the outer edge of the halo layer)
615  synchronise_nonhanging_nodes();
616 
617  // Get number of continously interpolated variables
618  unsigned local_ncont_interpolated_values=0;
619 
620  // Bypass if we have no elements and then get overall
621  // value by reduction
622  if (nelement()>0)
623  {
624  local_ncont_interpolated_values=dynamic_cast<RefineableElement*>
625  (element_pt(0))->ncont_interpolated_values();
626  }
627  unsigned ncont_interpolated_values=0;
628  MPI_Allreduce(&local_ncont_interpolated_values,
629  &ncont_interpolated_values,1,
630  MPI_UNSIGNED,MPI_MAX,
631  Comm_pt->mpi_comm());
632 
633  // Synchronise the hanging nodes
634  synchronise_hanging_nodes(ncont_interpolated_values);
635 
637  {
638  double t_end = TimingHelpers::timer();
639  oomph_info
640  << "Time for "
641  << "TreeBasedRefineableMeshBase::synchronise_hanging_nodes() "
642  << "incl. time for initial allreduce in "
643  << "TreeBasedRefineableMeshBase::classify_halo_and_haloed_nodes(): "
644  << t_end-t_start << std::endl;
645  }
646 
647  // Now do resize halo nodes after all (unless it's been
648  // declared to be unnecessary by somebody...)
650  {
652  }
653  }
654 
655 
656  /// Classify the halo and haloed nodes in the mesh.
657  void classify_halo_and_haloed_nodes(const bool& report_stats=false)
658  {
660  doc_info.disable_doc();
661  classify_halo_and_haloed_nodes(doc_info,report_stats);
662  }
663 
664 #endif
665 
666 protected:
667 
668 #ifdef OOMPH_HAS_MPI
669 
670  /// Synchronise the hanging nodes if the mesh is distributed
671  void synchronise_hanging_nodes(const unsigned& ncont_interpolated_values);
672 
673  /// Additional synchronisation of hanging nodes
674  /// Required for reconcilliation of hanging nodes on the outer edge of the
675  /// halo layer when using elements with nonuniformly spaced nodes
676  /// Must be implemented in templated derived class because ELEMENT template
677  /// parameter is required for the node-creation functions in the
678  /// Missing_masters_functions namespace
679  virtual void additional_synchronise_hanging_nodes(
680  const unsigned& ncont_interpolated_values)=0;
681 
682  /// Synchronise the positions of non-hanging nodes that depend on
683  /// non-existent neighbours (e.g. h-refinement of neighbouring elements
684  /// with different p-orders where the shared edge is on the outer edge of
685  /// the halo layer)
686  void synchronise_nonhanging_nodes();
687 
688 #endif
689 
690  /// \short Split all the elements in the mesh if required. This template free
691  /// interface will be overloaded in RefineableMesh<ELEMENT> so that
692  /// any new elements that are created will be of the correct type.
693  virtual void split_elements_if_required()=0;
694 
695  /// \short p-refine all the elements in the mesh if required. This template
696  /// free interface will be overloaded in RefineableMesh<ELEMENT> so that
697  /// any temporary copies of the element that are created will be of the
698  /// correct type.
699  virtual void p_refine_elements_if_required()=0;
700 
701  /// \short Complete the hanging node scheme recursively
702  void complete_hanging_nodes(const int& ncont_interpolated_values);
703 
704 
705  /// Auxiliary routine for recursive hanging node completion
706  void complete_hanging_nodes_recursively(Node*& nod_pt,
707  Vector<Node*>& master_nodes,
708  Vector<double>& hang_weights,
709  const int &ival);
710 
711  /// \short Level to which the mesh was uniformly refined when it was pruned
713 
714  /// Max. permissible refinement level (relative to base mesh)
716 
717  /// Min. permissible refinement level (relative to base mesh)
719 
720  /// Max. permissible p-refinement level (relative to base mesh)
722 
723  /// Min. permissible p-refinement level (relative to base mesh)
725 
726  /// Forest representation of the mesh
728 
729  private:
730 
731 #ifdef OOMPH_HAS_MPI
732 
733  /// \short Helper struct to collate data required during
734  /// TreeBasedRefineableMeshBase::synchronise_hanging_nodes
736  {
740  double Weight;
743  // Store pointer to node and index of value in case translation attempt fails
744  // (see synchronise_hanging_nodes())
746  int icont;
747  };
748 
749 #endif
750 
751 };
752 
753 
754 ////////////////////////////////////////////////////////////////////
755 ////////////////////////////////////////////////////////////////////
756 ////////////////////////////////////////////////////////////////////
757 
758 
759 //=======================================================================
760 /// Templated base class for refineable meshes. The use of the template
761 /// parameter is required only for creating new elements during mesh
762 /// adaptation. This class overloaded the template-free inteface to
763 /// the function split_elements_if_required() to make use of the template
764 /// parameter.
765 /// All refineable meshes should inherit directly from
766 /// TreeBasedRefineableMesh<ELEMENT>
767 //=======================================================================
768 template <class ELEMENT>
770  {
771  private:
772 
773  /// \short Split all the elements if required. Overload the template-free
774  /// interface so that any new elements that are created
775  /// will be of the correct type.
777  {
778  //Find the number of trees in the forest
779  unsigned n_tree = this->Forest_pt->ntree();
780  //Loop over all "active" elements in the forest and split them
781  //if required
782  for (unsigned long e=0;e<n_tree;e++)
783  {
784  this->Forest_pt->tree_pt(e)->
785  traverse_leaves(&Tree::split_if_required<ELEMENT>);
786  }
787  }
788 
789  /// \short p-refine all the elements if required. Overload the template-free
790  /// interface so that any temporary copies of the element that are created
791  /// will be of the correct type.
793  {
794  //BENFLAG: Make a non const pointer to the mesh so it can be passed (HACK)
795  Mesh* mesh_pt=this;
796  //Find the number of trees in the forest
797  unsigned n_tree = this->Forest_pt->ntree();
798  //Loop over all "active" elements in the forest and p-refine them
799  //if required
800  for (unsigned long e=0;e<n_tree;e++)
801  {
802  this->Forest_pt->tree_pt(e)->
803  traverse_leaves(&Tree::p_refine_if_required<ELEMENT>,mesh_pt);
804  }
805  }
806 
807  protected:
808 
809 #ifdef OOMPH_HAS_MPI
810 
811  /// Additional setup of shared node scheme
812  /// This is Required for reconcilliation of hanging nodes acrross processor
813  /// boundaries when using elements with nonuniformly spaced nodes.
814  /// ELEMENT template parameter is required so that
815  /// MacroElementNodeUpdateNodes which are added as external halo master nodes
816  /// can be made fully functional
817  void additional_synchronise_hanging_nodes(
818  const unsigned& ncont_interpolated_values);
819 
820 #endif
821 
822  public:
823 
824  ///Constructor, call the constructor of the base class
826 
827  /// Broken copy constructor
829  {
830  BrokenCopy::broken_copy("TreeBasedRefineableMesh");
831  }
832 
833  ///Empty virtual destructor
835 
836  };
837 
838 
839 
840 
841 
842 ////////////////////////////////////////////////////////////////////
843 ////////////////////////////////////////////////////////////////////
844 ////////////////////////////////////////////////////////////////////
845 
846 
847 //=======================================================================
848 /// Base class for refineable tet meshes
849 //=======================================================================
851  {
852 
853 
854  public:
855 
856  /// Max element size allowed during adaptation
857  double& max_element_size(){return Max_element_size;}
858 
859  /// Min element size allowed during adaptation
860  double& min_element_size(){return Min_element_size;}
861 
862  /// Min edge ratio before remesh gets triggered
863  double& max_permitted_edge_ratio(){return Max_permitted_edge_ratio;}
864 
865 
866  /// Doc the targets for mesh adaptation
867  void doc_adaptivity_targets(std::ostream &outfile)
868  {
869  outfile << std::endl;
870  outfile << "Targets for mesh adaptation: " << std::endl;
871  outfile << "---------------------------- " << std::endl;
872  outfile << "Target for max. error: " << Max_permitted_error << std::endl;
873  outfile << "Target for min. error: " << Min_permitted_error << std::endl;
874  outfile << "Target max edge ratio: "
875  << Max_permitted_edge_ratio << std::endl;
876  outfile << "Min. allowed element size: " << Min_element_size << std::endl;
877  outfile << "Max. allowed element size: " << Max_element_size << std::endl;
878  outfile << "Don't unrefine if less than " << Max_keep_unrefined
879  << " elements need unrefinement." << std::endl;
880  outfile << std::endl;
881  }
882 
883 
884 
885  /// \short Compute target volume based on the elements' error and the
886  /// error target; return max edge ratio
887  double compute_volume_target(const Vector<double> &elem_error,
888  Vector<double> &target_volume)
889  {
890  double max_edge_ratio=0.0;
891  unsigned count_unrefined=0;
892  unsigned count_refined=0;
893  this->Nrefinement_overruled=0;
894 
895  unsigned nel=this->nelement();
896  for (unsigned e=0;e<nel;e++)
897  {
898  // Get element
899  FiniteElement* el_pt=this->finite_element_pt(e);
900 
901  // Calculate the volume of the element
902  double volume=el_pt->size();
903 
904  //Find the vertex coordinates
905  // (vertices are enumerated first)
906  double vertex[4][3];
907  for(unsigned n=0;n<4;++n)
908  {
909  for(unsigned i=0;i<3;++i)
910  {
911  vertex[n][i] = el_pt->node_pt(n)->x(i);
912  }
913  }
914 
915  //Compute the radius of the circumsphere of the tetrahedron
916  //Algorithm stolen from tetgen for consistency
917  DenseDoubleMatrix A(3);
918  for(unsigned i=0;i<3;++i)
919  {
920  A(0,i) = vertex[1][i] - vertex[0][i];
921  A(1,i) = vertex[2][i] - vertex[0][i];
922  A(2,i) = vertex[3][i] - vertex[0][i];
923  }
924 
925  Vector<double> rhs(3);
926  // Compute the right hand side vector b (3x1).
927  for(unsigned i=0;i<3;++i)
928  {
929  rhs[i] = 0.0;
930  for(unsigned k=0;k<3;++k)
931  {
932  rhs[i] += A(i,k)*A(i,k);
933  }
934  rhs[i] *= 0.5;
935  }
936 
937  //Solve the linear system, in which the rhs is over-written with
938  //the solution
939  A.solve(rhs);
940 
941  //Calculate the circum-radius
942  double circum_radius =
943  sqrt(rhs[0]*rhs[0] + rhs[1]*rhs[1] + rhs[2]*rhs[2]);
944 
945  //Now find the shortest edge length
946  Vector<double> edge(3);
947  double min_length = DBL_MAX;
948  for(unsigned start=0;start<4;++start)
949  {
950  for(unsigned end=start+1;end<4;++end)
951  {
952  for(unsigned i=0;i<3;++i)
953  {
954  edge[i] = vertex[start][i] - vertex[end][i];
955  }
956  double length =
957  sqrt(edge[0]*edge[0] + edge[1]*edge[1] + edge[2]*edge[2]);
958  if(length < min_length) {min_length = length;}
959  }
960  }
961 
962  //Now calculate the minimum edge ratio for this element
963  double local_max_edge_ratio = circum_radius/min_length;
964  if(local_max_edge_ratio > max_edge_ratio)
965  {
966  max_edge_ratio = local_max_edge_ratio;
967  }
968 
969  // Mimick refinement in tree-based procedure: Target volumes
970  // for elements that exceed permitted error is 1/4 of their
971  // current volume, corresponding to a uniform sub-division.
972  if (elem_error[e] > this->max_permitted_error())
973  {
974  target_volume[e]=std::max(volume/4.0,Min_element_size);
975  if (target_volume[e]!=Min_element_size)
976  {
977  count_refined++;
978  }
979  else
980  {
981  this->Nrefinement_overruled++;
982  }
983  }
984  else if (elem_error[e] < this->min_permitted_error())
985  {
986  target_volume[e]=std::min(4.0*volume,Max_element_size);
987  if (target_volume[e]!=Max_element_size)
988  {
989  count_unrefined++;
990  }
991  }
992  else
993  {
994  // Leave it alone
995  target_volume[e] = std::max(volume,Min_element_size);
996  }
997 
998  } //End of loop over elements
999 
1000  // Tell everybody
1001  this->Nrefined=count_refined;
1002  this->Nunrefined=count_unrefined;
1003 
1004  return max_edge_ratio;
1005  }
1006 
1007  /// Max permitted element size
1009 
1010  /// Min permitted element size
1012 
1013  /// Max edge ratio before remesh gets triggered
1015 
1016  };
1017 
1018 
1019 
1020 
1021 }
1022 
1023 #endif
void p_refine_uniformly()
p-refine mesh uniformly
Class of matrices containing doubles, and stored as a DenseMatrix<double>, but with solving functiona...
Definition: matrices.h:1234
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
unsigned & uniform_refinement_level_when_pruned()
Level to which the mesh was uniformly refined when it was pruned.
void refine_uniformly()
Refine mesh uniformly.
void resize_halo_nodes()
Helper function that resizes halo nodes to the same size as their non-halo counterparts if required...
Definition: mesh.cc:4106
void classify_halo_and_haloed_nodes(const bool &report_stats=false)
Classify the halo and haloed nodes in the mesh.
unsigned Min_p_refinement_level
Min. permissible p-refinement level (relative to base mesh)
double & max_error()
Access fct for max. actual error in present solution (i.e. before re-solve on adapted mesh) ...
virtual unsigned unrefine_uniformly()=0
Unrefine mesh uniformly: Return 0 for success, 1 for failure (if unrefinement has reached the coarses...
double & max_permitted_error()
Access fct for max. error (i.e. split elements if their error is larger)
Information for documentation of results: Directory and file number to enable output in the form RESL...
unsigned Uniform_refinement_level_when_pruned
Level to which the mesh was uniformly refined when it was pruned.
void operator=(const RefineableMeshBase &)
Broken assignment operator.
std::string directory() const
Output directory.
cstr elem_len * i
Definition: cfortran.h:607
double & max_permitted_edge_ratio()
Min edge ratio before remesh gets triggered.
void doc_adaptivity_targets(std::ostream &outfile)
Doc the targets for mesh adaptation.
unsigned Max_keep_unrefined
Max. number of elements that can remain unrefined if no other mesh adaptation is required (to avoid m...
TreeForest * forest_pt()
Return pointer to the Forest represenation of the mesh.
A general Finite Element class.
Definition: elements.h:1274
unsigned & nrefinement_overruled()
Number of elements that would have liked to be refined further but can&#39;t because they&#39;ve reached the ...
virtual ~RefineableMeshBase()
Empty Destructor:
void p_refine_elements_if_required()
p-refine all the elements if required. Overload the template-free interface so that any temporary cop...
virtual ~TreeBasedRefineableMesh()
Empty virtual destructor.
virtual void p_refine_uniformly(DocInfo &doc_info)
p-refine mesh uniformly and doc process
unsigned & min_refinement_level()
Access fct for min. permissible refinement level (relative to base mesh)
Base class for spatial error estimators.
double compute_volume_target(const Vector< double > &elem_error, Vector< double > &target_volume)
Compute target volume based on the elements&#39; error and the error target; return max edge ratio...
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:852
unsigned & max_keep_unrefined()
Max. number of elements that we allow to remain unrefined if no other mesh adaptation is required (to...
TreeBasedRefineableMesh(const TreeBasedRefineableMesh &dummy)
Broken copy constructor.
OomphInfo oomph_info
e
Definition: cfortran.h:575
bool Doc_comprehensive_timings
Global boolean to switch on comprehensive timing – can probably be declared const false when develop...
double size() const
Definition: elements.cc:4207
TreeForest * Forest_pt
Forest representation of the mesh.
void enable_additional_synchronisation_of_hanging_nodes()
Enable additional synchronisation of hanging nodes.
bool is_p_adaptation_enabled() const
Return whether the mesh is to be adapted.
void solve(DoubleVector &rhs)
Complete LU solve (replaces matrix by its LU decomposition and overwrites RHS with solution)...
Definition: matrices.cc:55
unsigned long nelement() const
Return number of elements in the mesh.
Definition: mesh.h:587
void disable_additional_synchronisation_of_hanging_nodes()
Disable additional synchronisation of hanging nodes.
unsigned & max_refinement_level()
Access fct for max. permissible refinement level (relative to base mesh)
TreeBasedRefineableMeshBase(const TreeBasedRefineableMeshBase &dummy)
Broken copy constructor.
double Max_element_size
Max permitted element size.
void enable_adaptation()
Enable adaptation.
ErrorEstimator *& spatial_error_estimator_pt()
Access to spatial error estimator.
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:995
double Max_error
Max. actual error.
virtual void adapt_mesh()
Perform the actual tree-based mesh adaptation. A simple wrapper to call the function without document...
virtual void doc_adaptivity_targets(std::ostream &outfile)
Doc the targets for mesh adaptation.
bool P_adapt_flag
Flag that requests p-adaptation.
unsigned & max_p_refinement_level()
Access fct for max. permissible p-refinement level (relative to base mesh)
void operator=(const TreeBasedRefineableMeshBase &)
Broken assignment operator.
double Max_permitted_error
Max. error (i.e. split elements if their error is larger)
Helper struct to collate data required during TreeBasedRefineableMeshBase::synchronise_hanging_nodes...
void disable_adaptation()
Disable adaptation.
Base class for tree-based refineable meshes.
void classify_halo_and_haloed_nodes(DocInfo &doc_info, const bool &report_stats)
void start(const unsigned &i)
(Re-)start i-th timer
virtual void classify_halo_and_haloed_nodes(DocInfo &doc_info, const bool &report_stats)
Classify the halo and haloed nodes in the mesh. Virtual so it can be overloaded to perform additional...
Definition: mesh.cc:2984
void disable_p_adaptation()
Disable adaptation.
virtual void adapt(const Vector< double > &elemental_error)=0
Adapt mesh: Refine elements whose error is lager than err_max and (try to) unrefine those whose error...
void p_adapt_mesh()
Perform the actual tree-based mesh p-adaptation. A simple wrapper to call the function without docume...
RefineableMeshBase(const RefineableMeshBase &dummy)
Broken copy constructor.
TreeBasedRefineableMesh()
Constructor, call the constructor of the base class.
void enable_p_adaptation()
Enable adaptation.
virtual void refine_uniformly()
Refine mesh uniformly.
void p_unrefine_uniformly(DocInfo &doc_info)
p-unrefine mesh uniformly
double Min_element_size
Min permitted element size.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2109
double timer()
returns the time in seconds after some point in past
virtual ~TreeBasedRefineableMeshBase()
Empty Destructor:
Class that contains data for hanging nodes.
Definition: nodes.h:684
bool Resize_halo_nodes_not_required
Set this to true to suppress resizing of halo nodes (at your own risk!)
Definition: mesh.h:155
bool Adapt_flag
Flag that requests adaptation.
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition: mesh.h:477
unsigned nrefined()
Access fct for number of elements that were refined.
DocInfo *& doc_info_pt()
Access fct for pointer to DocInfo.
void doc_adaptivity_targets(std::ostream &outfile)
Doc the targets for mesh adaptation.
void disable_doc()
Disable documentation.
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
unsigned nunrefined()
Access fct for number of elements that were unrefined.
unsigned Max_refinement_level
Max. permissible refinement level (relative to base mesh)
unsigned Min_refinement_level
Min. permissible refinement level (relative to base mesh)
virtual void p_refine_uniformly()
p-refine mesh uniformly
DocInfo doc_info()
Access fct for DocInfo.
unsigned Nrefinement_overruled
Number of elements that would like to be refined further but can&#39;t because they&#39;ve reached the max...
DocInfo * Doc_info_pt
Pointer to DocInfo.
bool Additional_synchronisation_of_hanging_nodes_not_required
Flag that disables additional synchronisation of hanging nodes.
virtual void p_adapt(const Vector< double > &elemental_error)
p-adapt mesh: Refine elements whose error is lager than err_max and (try to) unrefine those whose err...
double & min_error()
Access fct for min. actual error in present solution (i.e. before re-solve on adapted mesh) ...
bool is_additional_synchronisation_of_hanging_nodes_disabled() const
Return whether additional synchronisation is enabled.
unsigned Max_p_refinement_level
Max. permissible p-refinement level (relative to base mesh)
unsigned Nunrefined
Stats: Number of elements that were unrefined.
const Vector< GeneralisedElement * > & element_pt() const
Return reference to the Vector of elements.
Definition: mesh.h:470
double Min_permitted_error
Min. error (i.e. (try to) merge elements if their error is smaller)
Base class for refineable tet meshes.
bool is_adaptation_enabled() const
Return whether the mesh is to be adapted.
unsigned Nrefined
Stats: Number of elements that were refined.
double Min_error
Min.actual error.
ErrorEstimator * spatial_error_estimator_pt() const
Access to spatial error estimator (const version.
OomphCommunicator * Comm_pt
Pointer to communicator – set to NULL if mesh is not distributed.
Definition: mesh.h:130
double & min_permitted_error()
Access fct for min. error (i.e. (try to) merge elements if their error is smaller) ...
ErrorEstimator * Spatial_error_estimator_pt
Pointer to spatial error estimator.
unsigned & min_p_refinement_level()
Access fct for min. permissible p-refinement level (relative to base mesh)
A general mesh class.
Definition: mesh.h:74
unsigned uniform_refinement_level_when_pruned() const
Level to which the mesh was uniformly refined when it was pruned (const version)
double Max_permitted_edge_ratio
Max edge ratio before remesh gets triggered.
void split_elements_if_required()
Split all the elements if required. Overload the template-free interface so that any new elements tha...
double & max_element_size()
Max element size allowed during adaptation.
double & min_element_size()
Min element size allowed during adaptation.