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 //Header file for general mesh classes
31 
32 //Include guards to prevent multiple inclusion of the header
33 #ifndef OOMPH_GENERIC_MESH_HEADER
34 #define OOMPH_GENERIC_MESH_HEADER
35 
36 // Config header generated by autoconfig
37 #ifdef HAVE_CONFIG_H
38  #include <oomph-lib-config.h>
39 #endif
40 
41 #ifdef OOMPH_HAS_MPI
42 #include "mpi.h"
43 #endif
44 
45 #include<float.h>
46 #include <list>
47 #include <typeinfo>
48 #include<string>
49 
50 //oomph-lib headers
51 #include "Vector.h"
52 #include "nodes.h"
53 #include "elements.h"
54 #include "timesteppers.h"
56 #include "matrices.h"
57 #include "refineable_elements.h"
58 
59 namespace oomph
60 {
61 
62 
63 
64 
65 //=================================================================
66 /// \short A general mesh class.
67 ///
68 /// The main components of a Mesh are:
69 /// - pointers to its Nodes
70 /// - pointers to its Elements
71 /// - pointers to its boundary Nodes
72 ///
73 //=================================================================
74 class Mesh
75 {
76 
77  public:
78 
79  /// Problem is a friend
80  friend class Problem;
81 
82 
83  /// \short Default Steady Timestepper, to be used in default arguments
84  /// to Mesh constructors
86 
87 
88  protected:
89 
90  /// \short Vector of Vector of pointers to nodes on the boundaries:
91  /// Boundary_node_pt(b,n). Note that this is private to force
92  /// the use of the add_boundary_node() function, which ensures
93  /// that the reverse look-up schemes for the nodes are set up.
95 
96  /// Flag to indicate that the lookup schemes for elements that are adjacent
97  /// to the boundaries has been set up.
99 
100  /// \short Vector of Vector of pointers to elements on the boundaries:
101  /// Boundary_element_pt(b,e)
103 
104  /// \short For the e-th finite element on boundary b, this is the index of
105  /// the face that lies along that boundary
107 
108 #ifdef OOMPH_HAS_MPI
109 
110  /// Map of vectors holding the pointers to the root halo elements
111  std::map<unsigned, Vector<GeneralisedElement*> > Root_halo_element_pt;
112 
113  /// Map of vectors holding the pointers to the root haloed elements
114  std::map<unsigned, Vector<GeneralisedElement*> > Root_haloed_element_pt;
115 
116  /// Map of vectors holding the pointers to the halo nodes
117  std::map<unsigned, Vector<Node*> > Halo_node_pt;
118 
119  /// Map of vectors holding the pointers to the haloed nodes
120  std::map<unsigned, Vector<Node*> > Haloed_node_pt;
121 
122  /// Map of vectors holding the pointers to the shared nodes.
123  /// These are all the nodes that are on two "neighbouring" processes
124  /// (the halo(ed) lookup scheme depends upon which processor is in charge
125  /// - a node which is on 3 processors, for example, will not feature in
126  /// the halo(ed) lookup scheme between the two lowest-numbered processors)
127  std::map<unsigned, Vector<Node*> > Shared_node_pt;
128 
129  /// Pointer to communicator -- set to NULL if mesh is not distributed
131 
132  /// External halo(ed) elements are created as and when they are needed
133  /// to act as source elements for the particular process's mesh.
134  /// The storage is wiped and rebuilt every time the mesh is refined.
135 
136  /// Map of vectors holding the pointers to the external halo elements
137  std::map<unsigned, Vector<GeneralisedElement*> > External_halo_element_pt;
138 
139  /// Map of vectors holding the pointers to the external haloed elements
140  std::map<unsigned, Vector<GeneralisedElement*> > External_haloed_element_pt;
141 
142 
143  // External halo(ed) nodes are on the external halo(ed) elements
144 
145  /// Map of vectors holding the pointers to the external halo nodes
146  std::map<unsigned, Vector<Node*> > External_halo_node_pt;
147 
148  /// Map of vectors holding the pointers to the external haloed nodes
149  std::map<unsigned, Vector<Node*> > External_haloed_node_pt;
150 
151  /// bool to indicate whether to keep all elements in a mesh as halos or not
153 
154  /// Set this to true to suppress resizing of halo nodes (at your own risk!)
156 
157  /// Setup shared node scheme
159 
160 #endif
161 
162  /// \short Assign the global equation numbers in the Data stored at the nodes
163  /// and also internal element Data. Also, build (via push_back) the
164  /// Vector of pointers to the dofs (variables).
165  unsigned long
167 
168  /// \short Function to describe the dofs of the Mesh. The ostream
169  /// specifies the output stream to which the description
170  /// is written; the string stores the currently
171  /// assembled output that is ultimately written to the
172  /// output stream by Data::describe_dofs(...); it is typically
173  /// built up incrementally as we descend through the
174  /// call hierarchy of this function when called from
175  /// Problem::describe_dofs(...)
176  void describe_dofs(std::ostream& out,const std::string& current_string) const;
177 
178  /// \short Function to describe the local dofs of the elements. The ostream
179  /// specifies the output stream to which the description
180  /// is written; the string stores the currently
181  /// assembled output that is ultimately written to the
182  /// output stream by Data::describe_dofs(...); it is typically
183  /// built up incrementally as we descend through the
184  /// call hierarchy of this function when called from
185  /// Problem::describe_dofs(...)
186  void describe_local_dofs(std::ostream& out,
187  const std::string& current_string) const;
188 
189  /// \short Assign the local equation numbers in all elements
190  /// If the boolean argument is true then also store pointers to dofs
191  void assign_local_eqn_numbers(const bool &store_local_dof_pt);
192 
193  /// Vector of pointers to nodes
195 
196  /// Vector of pointers to generalised elements
198 
199  /// \short Vector of boolean data that indicates whether the boundary
200  /// coordinates have been set for the boundary
201  std::vector<bool> Boundary_coordinate_exists;
202 
203  /// \short A function that upgrades an ordinary node to a boundary node
204  /// We shouldn't ever really use this, but it does make life that
205  /// bit easier for the lazy mesh writer. The pointer to the node is
206  /// replaced by a pointer to the new boundary node in all element look-up
207  /// schemes and in the mesh's Node_pt vector. The new node is also
208  /// addressed by node_pt on return from the function.
211 
213 
214 
215 public:
216 
217 
218 #ifdef OOMPH_HAS_MPI
219 
220 
221  /// \short Helper function that resizes halo nodes to the same
222  /// size as their non-halo counterparts if required. (A discrepancy
223  /// can arise if a FaceElement that introduces additional unknowns
224  /// are attached to a bulk element that shares a node with a haloed element.
225  /// In that case the joint node between haloed and non-haloed element
226  /// is resized on that processor but not on the one that holds the
227  /// halo counterpart (because no FaceElement is attached to the halo
228  /// element)
229  void resize_halo_nodes();
230 
231 #endif
232 
233 
234  /// \short Typedef for function pointer to function that computes
235  /// steady exact solution
237  const Vector<double>& x, Vector<double>& soln);
238 
239  /// \short Typedef for function pointer to function that computes unsteady
240  /// exact solution
242  const double& time, const Vector<double>& x, Vector<double>& soln);
243 
244  /// \short Boolean used to control warning about empty mesh level
245  /// timestepper function
247 
248  /// \short Default constructor
250  {
251  // Lookup scheme hasn't been setup yet
252  Lookup_for_elements_next_boundary_is_setup=false;
253 #ifdef OOMPH_HAS_MPI
254  // Set defaults for distributed meshes
255 
256  // Mesh hasn't been distributed: Null out pointer to communicator
257  Comm_pt=0;
258  // Don't keep all objects as halos
259  Keep_all_elements_as_halos=false;
260  // Don't output halo elements
261  Output_halo_elements=false;
262  // Don't suppress automatic resizing of halo nodes
263  Resize_halo_nodes_not_required=false;
264 #endif
265  }
266 
267  /// \short Constructor builds combined mesh from the meshes specified.
268  /// Note: This simply merges the meshes' elements and nodes (ignoring
269  /// duplicates; no boundary information etc. is created).
270  Mesh(const Vector<Mesh*>& sub_mesh_pt)
271  {
272 #ifdef OOMPH_HAS_MPI
273  // Mesh hasn't been distributed: Null out pointer to communicator
274  Comm_pt=0;
275 #endif
276  // Now merge the meshes
277  merge_meshes(sub_mesh_pt);
278  }
279 
280  /// \short Merge meshes.
281  /// Note: This simply merges the meshes' elements and nodes (ignoring
282  /// duplicates; no boundary information etc. is created).
283  void merge_meshes(const Vector<Mesh*>& sub_mesh_pt);
284 
285  /// \short Interface for function that is used to setup the boundary
286  /// information (Empty virtual function -- implement this for specific
287  /// Mesh classes)
288  virtual void setup_boundary_element_info() { }
289 
290  /// \short Setup lookup schemes which establish whic elements are located
291  /// next to mesh's boundaries. Doc in outfile (if it's open).
292  /// (Empty virtual function -- implement this for specific
293  /// Mesh classes)
294  virtual void setup_boundary_element_info(std::ostream &outfile) {}
295 
296  /// Virtual function to perform the reset boundary elements info rutines
298  Vector<unsigned> &ntmp_boundary_elements,
299  Vector<Vector<unsigned> > &ntmp_boundary_elements_in_region,
300  Vector<FiniteElement*> &deleted_elements)
301  {
302  std::ostringstream error_stream;
303  error_stream << "Empty default reset boundary element info function"
304  << "called.\n";
305  error_stream << "This should be overloaded in a specific "
306  << "TriangleMeshBase\n";
307  throw OomphLibError(error_stream.str(),
308  "Mesh::reset_boundary_element_info()",
309  OOMPH_EXCEPTION_LOCATION);
310  }
311 
312  /// \short Output boundary coordinates on boundary b -- template argument
313  /// specifies the bulk element type (needed to create FaceElement
314  /// of appropriate type on mesh boundary).
315  template<class BULK_ELEMENT>
316  void doc_boundary_coordinates(const unsigned& b, std::ofstream& the_file)
317  {
318  if (nelement()==0) return;
319  if (!Boundary_coordinate_exists[b])
320  {
321  oomph_info << "No boundary coordinates were set up for boundary "
322  << b << std::endl;
323  return;
324  }
325 
326  // Get spatial dimension
327  unsigned dim=finite_element_pt(0)->node_pt(0)->ndim();
328 
329  // Loop over all elements on boundaries
330  unsigned nel=this->nboundary_element(b);
331 
332  // Loop over the bulk elements adjacent to boundary b
333  for(unsigned e=0;e<nel;e++)
334  {
335  // Get pointer to the bulk element that is adjacent to boundary b
336  FiniteElement* bulk_elem_pt = this->boundary_element_pt(b,e);
337 
338  //Find the index of the face of element e along boundary b
339  int face_index = this->face_index_at_boundary(b,e);
340 
341  // Create new face element
343  new DummyFaceElement<BULK_ELEMENT>(bulk_elem_pt,face_index);
344 
345  // Specify boundary id in bulk mesh (needed to extract
346  // boundary coordinate)
348 
349  // Doc boundary coordinate
350  Vector<double> s(dim-1);
351  Vector<double> zeta(dim-1);
352  Vector<double> x(dim);
353  unsigned n_plot=5;
354  the_file << el_pt->tecplot_zone_string(n_plot);
355 
356  // Loop over plot points
357  unsigned num_plot_points=el_pt->nplot_points(n_plot);
358  for (unsigned iplot=0;iplot<num_plot_points;iplot++)
359  {
360  // Get local coordinates of plot point
361  el_pt->get_s_plot(iplot,n_plot,s);
362  el_pt->interpolated_zeta(s,zeta);
363  el_pt->interpolated_x(s,x);
364  for (unsigned i=0;i<dim;i++)
365  {
366  the_file << x[i] << " ";
367  }
368  for (unsigned i=0;i<(dim-1);i++)
369  {
370  the_file << zeta[i] << " ";
371  }
372 
373  the_file << std::endl;
374  }
375  el_pt->write_tecplot_zone_footer(the_file,n_plot);
376 
377  // Cleanup
378  delete el_pt;
379  }
380  }
381 
382 
383  /// \short Scale all nodal coordinates by given factor. Virtual
384  /// so it can be overloaded in SolidMesh class where it also
385  /// re-assigns the Lagrangian coordinates.
386  virtual void scale_mesh(const double& factor)
387  {
388  unsigned nnod=this->nnode();
389  unsigned dim=this->node_pt(0)->ndim();
390  for (unsigned j=0;j<nnod;j++)
391  {
392  Node* nod_pt=this->node_pt(j);
393  for (unsigned i=0;i<dim;i++)
394  {
395  nod_pt->x(i)*=factor;
396  }
397  }
398  }
399 
400 
401  /// Broken copy constructor
402  Mesh(const Mesh& dummy)
403  {
404  BrokenCopy::broken_copy("Mesh");
405  }
406 
407  /// Broken assignment operator
408  void operator=(const Mesh&)
409  {
411  }
412 
413  /// Virtual Destructor to clean up all memory
414  virtual ~Mesh();
415 
416 
417 /// \short Flush storage for elements and nodes by emptying the
418 /// vectors that store the pointers to them. This is
419 /// useful if a particular mesh is only built to generate
420 /// a small part of a bigger mesh. Once the elements and
421 /// nodes have been created, they are typically copied
422 /// into the new mesh and the auxiliary mesh can be
423 /// deleted. However, if we simply call the destructor
424 /// of the auxiliary mesh, it will also wipe out
425 /// the nodes and elements, because it still "thinks"
426 /// it's in charge of these...
428  {
431  }
432 
433 /// \short Flush storage for elements (only) by emptying the
434 /// vectors that store the pointers to them. This is
435 /// useful if a particular mesh is only built to generate
436 /// a small part of a bigger mesh. Once the elements and
437 /// nodes have been created, they are typically copied
438 /// into the new mesh and the auxiliary mesh can be
439 /// deleted. However, if we simply call the destructor
440 /// of the auxiliary mesh, it will also wipe out
441 /// the nodes and elements, because it still "thinks"
442 /// it's in charge of these...
444  {
445  Element_pt.clear();
446  }
447 
448 /// \short Flush storage for nodes (only) by emptying the
449 /// vectors that store the pointers to them.
451  {
452  Node_pt.clear();
453  }
454 
455  /// Return pointer to global node n
456  Node* &node_pt(const unsigned long &n) {return Node_pt[n];}
457 
458  /// Return pointer to global node n (const version)
459  Node* node_pt(const unsigned long &n) const {return Node_pt[n];}
460 
461  /// Return pointer to element e
462  GeneralisedElement* &element_pt(const unsigned long &e)
463  {return Element_pt[e];}
464 
465  /// Return pointer to element e (const version)
466  GeneralisedElement* element_pt(const unsigned long &e) const
467  {return Element_pt[e];}
468 
469  /// Return reference to the Vector of elements
471 
472  /// Return reference to the Vector of elements
474 
475  /// \short Upcast (downcast?) to FiniteElement
476  /// (needed to access FiniteElement member functions).
477  FiniteElement* finite_element_pt(const unsigned &e) const
478  {
479 #ifdef PARANOID
480  FiniteElement* el_pt=dynamic_cast<FiniteElement*>(Element_pt[e]);
481  if (el_pt==0)
482  {
483  //Error
484  throw OomphLibError("Failed cast to FiniteElement* ",
485  OOMPH_CURRENT_FUNCTION,
486  OOMPH_EXCEPTION_LOCATION);
487  //Dummy return to keep intel compiler happy
488  return el_pt;
489  }
490  return el_pt;
491 #else
492  return dynamic_cast<FiniteElement*>(Element_pt[e]);
493 #endif
494  }
495 
496  /// Return pointer to node n on boundary b
497  Node* &boundary_node_pt(const unsigned &b, const unsigned &n)
498  {return Boundary_node_pt[b][n];}
499 
500  /// Return pointer to node n on boundary b
501  Node* boundary_node_pt(const unsigned &b, const unsigned &n) const
502  {return Boundary_node_pt[b][n];}
503 
504  /// Set the number of boundaries in the mesh
505  void set_nboundary(const unsigned &nbound)
506  {
507  Boundary_node_pt.resize(nbound);
508  Boundary_coordinate_exists.resize(nbound,false);
509  }
510 
511  ///\short Clear all pointers to boundary nodes
512  void remove_boundary_nodes();
513 
514  /// \short Remove all information about nodes stored on the b-th
515  /// boundary of the mesh
516  void remove_boundary_nodes(const unsigned &b);
517 
518  //\ short Remove a node from the boundary b
519  void remove_boundary_node(const unsigned &b, Node* const &node_pt);
520 
521  /// Add a (pointer to) a node to the b-th boundary
522  void add_boundary_node(const unsigned &b, Node* const &node_pt);
523 
524  /// Replace existing boundary node lookup schemes with new schemes created
525  /// using the boundary data stored in the nodes.
527  {
528  // Clear existing boundary data
529  Boundary_node_pt.clear();
530 
531  // Loop over nodes adding them to the appropriate boundary lookup schemes
532  // in the mesh.
533  const unsigned n_node = nnode();
534  for(unsigned nd=0; nd<n_node; nd++)
535  {
536  Node* nd_pt = node_pt(nd);
537 
538  if(nd_pt->is_on_boundary())
539  {
540  // Get set of boundaries that the node is on
541  std::set<unsigned>* boundaries_pt;
542  nd_pt->get_boundaries_pt(boundaries_pt);
543 
544  // If needed then add more boundaries to this mesh
545  unsigned max_boundary_n = 1 +
546  *std::max_element(boundaries_pt->begin(), boundaries_pt->end());
547  if(max_boundary_n > nboundary())
548  {
549  set_nboundary(max_boundary_n);
550  }
551 
552  // Add node pointer to the appropriate Boundary_node_pt vectors
553  std::set<unsigned>::const_iterator it;
554  for(it=boundaries_pt->begin(); it!=boundaries_pt->end(); it++)
555  {
556  Boundary_node_pt[*it].push_back(nd_pt);
557  }
558  }
559  }
560  }
561 
562  /// Indicate whether the i-th boundary has an intrinsic coordinate.
563  // By default, if the array Boundary_coordinate has not been resized,
564  // return false
565  bool boundary_coordinate_exists(const unsigned &i) const
566  {
567  if(Boundary_coordinate_exists.empty()) {return false;}
568  //ALH: This bounds-checking code needs to remain, because
569  //Boundary_coordinate_exists is
570  //an stl vector not our overloaded Vector class
571 #ifdef RANGE_CHECKING
572  if (i>=Boundary_coordinate_exists.size())
573  {
574  std::ostringstream error_message;
575  error_message << "Range Error: " << i << " is not in the range (0,"
576  << Boundary_coordinate_exists.size()-1 << std::endl;
577 
578  throw OomphLibError(error_message.str(),
579  OOMPH_CURRENT_FUNCTION,
580  OOMPH_EXCEPTION_LOCATION);
581  }
582 #endif
583  return Boundary_coordinate_exists[i];
584  }
585 
586  /// Return number of elements in the mesh
587  unsigned long nelement() const {return Element_pt.size();}
588 
589  /// Return number of nodes in the mesh
590  unsigned long nnode() const {return Node_pt.size();}
591 
592  /// Return number of dof types in mesh
593  unsigned ndof_types() const;
594 
595  /// Return number of elemental dimension in mesh
596  unsigned elemental_dimension() const;
597 
598  /// Return number of nodal dimension in mesh
599  unsigned nodal_dimension() const;
600 
601  /// Add a (pointer to a) node to the mesh
602  void add_node_pt(Node* const &node_pt) {Node_pt.push_back(node_pt);}
603 
604  /// Add a (pointer to) an element to the mesh
606  {Element_pt.push_back(element_pt);}
607 
608  /// \short Update nodal positions in response to changes in the domain shape.
609  /// Uses the FiniteElement::get_x(...) function for FiniteElements
610  /// and doesn't do anything for other element types.
611  /// If a MacroElement pointer has been set for a FiniteElement,
612  /// the MacroElement representation is used to update the
613  /// nodal positions; if not get_x(...) uses the FE interpolation
614  /// and thus leaves the nodal positions unchanged.
615  /// Virtual, so it can be overloaded by specific meshes,
616  /// such as AlgebraicMeshes or SpineMeshes.
617  /// Generally, this function updates the position of all nodes
618  /// in response to changes in the boundary position.
619  /// However, we ignore all SolidNodes since their
620  /// position is computed as part of the solution -- unless
621  /// the bool flag is set to true. Such calls are typically made
622  /// when the initial mesh is created and/or after a mesh has been
623  /// refined repeatedly before the start of the computation.
624  virtual void node_update(const bool& update_all_solid_nodes=false);
625 
626  /// \short Re-order nodes in the order in which they appear in elements --
627  /// can be overloaded for more efficient re-ordering
628  virtual void reorder_nodes(const bool& use_old_ordering=true);
629 
630  /// \short Get a reordering of the nodes in the order in which they
631  /// appear in elements -- can be overloaded for more efficient
632  /// re-ordering
633  virtual void get_node_reordering(Vector<Node*> &reordering,
634  const bool& use_old_ordering=true) const;
635 
636  /// \short Constuct a Mesh of FACE_ELEMENTs along the b-th boundary
637  /// of the mesh (which contains elements of type BULK_ELEMENT)
638  template<class BULK_ELEMENT, template<class> class FACE_ELEMENT>
639  void build_face_mesh(const unsigned &b, Mesh* const &face_mesh_pt)
640  {
641  //Find the number of nodes on the boundary
642  unsigned nbound_node = nboundary_node(b);
643  //Loop over the boundary nodes and add them to face mesh node pointer
644  for(unsigned n=0;n<nbound_node;n++)
645  {face_mesh_pt->add_node_pt(boundary_node_pt(b,n));}
646 
647  //Find the number of elements next to the boundary
648  unsigned nbound_element = nboundary_element(b);
649  //Loop over the elements adjacent to boundary b
650  for(unsigned e=0;e<nbound_element;e++)
651  {
652  //Create the FaceElement
653  FACE_ELEMENT<BULK_ELEMENT>* face_element_pt =
654  new FACE_ELEMENT<BULK_ELEMENT>(boundary_element_pt(b,e),
656 
657  //Add the face element to the face mesh
658  face_mesh_pt->add_element_pt(face_element_pt);
659  }
660 
661 #ifdef OOMPH_HAS_MPI
662  // If the bulk mesh has been distributed then the face mesh is too
663  if (this->is_mesh_distributed())
664  {
665  face_mesh_pt->set_communicator_pt(this->communicator_pt());
666  }
667 #endif
668  }
669 
670  /// \short Self-test: Check elements and nodes. Return 0 for OK
671  unsigned self_test();
672 
673 
674  /// \short Determine max and min area for all FiniteElements in the mesh
675  /// (non-FiniteElements are ignored)
676  void max_and_min_element_size(double& max_size, double& min_size)
677  {
678  max_size=0.0;
679  min_size=DBL_MAX;
680  unsigned nel=nelement();
681  for (unsigned e=0;e<nel;e++)
682  {
683  max_size=std::max(max_size,
684  finite_element_pt(e)->size());
685  min_size=std::min(min_size,
686  finite_element_pt(e)->size()); }
687  }
688 
689 
690  /// \short Determine the sum of all "sizes" of the FiniteElements in the mesh
691  /// (non-FiniteElements are ignored). This gives the length/area/volume
692  /// occupied by the mesh
693  double total_size()
694  {
695  double size=0.0;
696  unsigned nel=nelement();
697  for (unsigned e=0;e<nel;e++)
698  {
700  if (fe_pt!=0)
701  {
702  size+=fe_pt->size();
703  }
704  }
705  return size;
706  }
707 
708 
709  /// \short Check for inverted elements and report outcome
710  /// in boolean variable. This visits all elements at their
711  /// integration points and checks if the Jacobian of the
712  /// mapping between local and global coordinates is positive --
713  /// using the same test that would be carried out (but only in PARANOID
714  /// mode) during the assembly of the elements' Jacobian matrices.
715  /// Inverted elements are output in inverted_element_file (if the
716  /// stream is open).
717  void check_inverted_elements(bool& mesh_has_inverted_elements,
718  std::ofstream& inverted_element_file);
719 
720 
721 /// \short Check for inverted elements and report outcome
722  /// in boolean variable. This visits all elements at their
723  /// integration points and checks if the Jacobian of the
724  /// mapping between local and global coordinates is positive --
725  /// using the same test that would be carried out (but only in PARANOID
726  /// mode) during the assembly of the elements' Jacobian matrices.
727  void check_inverted_elements(bool& mesh_has_inverted_elements)
728  {
729  std::ofstream inverted_element_file;
730  check_inverted_elements(mesh_has_inverted_elements,
731  inverted_element_file);
732  }
733 
734 
735  /// \short Check for repeated nodes within a given spatial tolerance.
736  /// Return (0/1) for (pass/fail).
737  unsigned check_for_repeated_nodes(const double& epsilon=1.0e-12)
738  {
739  oomph_info <<"\n\nStarting check for repeated nodes...";
740  bool failed=false;
741  unsigned nnod=nnode();
742  for (unsigned j=0;j<nnod;j++)
743  {
744  Node* nod1_pt=this->node_pt(j);
745  unsigned dim=nod1_pt->ndim();
746  for (unsigned k=j+1;k<nnod;k++)
747  {
748  Node* nod2_pt=this->node_pt(k);
749  double dist=0.0;
750  for (unsigned i=0;i<dim;i++)
751  {
752  dist+=pow((nod1_pt->x(i)-nod2_pt->x(i)),2);
753  }
754  dist=sqrt(dist);
755  if (dist<epsilon)
756  {
757  oomph_info << "\n\nRepeated node!" << std::endl;
758  oomph_info << "Distance between nodes " << j << " and " << k
759  << std::endl;
760  oomph_info << "is " << dist << " which is less than the"
761  << std::endl;
762  oomph_info << "permitted distance of " << epsilon
763  << std::endl << std::endl;
764  oomph_info << "The offending nodes are located at: " << std::endl;
765  for (unsigned i=0;i<dim;i++)
766  {
767  oomph_info << nod1_pt->x(i) << " ";
768  }
769  if (nod1_pt->is_a_copy()||
770  nod2_pt->is_a_copy())
771  {
772  oomph_info
773  << "\n\n[NOTE: message issued as diagonistic rather than an error\n"
774  << " because at least one of the nodes is a copy; you may still\n"
775  << " want to check this out. BACKGROUND: Copied nodes share the same Data but\n"
776  << " will, in general, have different spatial positions (e.g. when used\n"
777  << " as periodic nodes); however there are cases when they are located\n"
778  << " at the same spatial position (e.g. in oomph-lib's annular mesh which\n"
779  << " is a rolled-around version of the rectangular quadmesh). In such cases,\n"
780  << " the nodes could have been deleted and completely replaced by \n"
781  << " pointers to existing nodes, but may have been left there for convenience\n"
782  << " or out of laziness...]\n";
783  }
784  else
785  {
786  failed=true;
787  }
788  oomph_info << std::endl << std::endl;
789 
790  }
791  }
792  }
793  if (failed) return 1;
794 
795  // If we made it to here, we must have passed the test.
796  oomph_info <<"...done: Test passed!" << std::endl << std::endl;
797  return 0;
798  }
799 
800  /// \short Prune nodes. Nodes that have been marked as obsolete are removed
801  /// from the mesh (and its boundary-node scheme). Returns vector
802  /// of pointers to deleted nodes.
804 
805  /// Return number of boundaries
806  unsigned nboundary() const {return Boundary_node_pt.size();}
807 
808  /// Return number of nodes on a particular boundary
809  unsigned long nboundary_node(const unsigned &ibound) const
810  {return Boundary_node_pt[ibound].size();}
811 
812 
813  /// Return pointer to e-th finite element on boundary b
814  FiniteElement* boundary_element_pt(const unsigned &b, const unsigned &e) const
815  {
816 #ifdef PARANOID
817  if (!Lookup_for_elements_next_boundary_is_setup)
818  {
819  throw OomphLibError(
820  "Lookup scheme for elements next to boundary hasn't been set up yet!\n",
821  OOMPH_CURRENT_FUNCTION,
822  OOMPH_EXCEPTION_LOCATION);
823  }
824 #endif
825  return Boundary_element_pt[b][e];
826  }
827 
828 
829  /// \short Find a node not on any boundary in mesh_pt (useful for pinning
830  /// a single node in a purely Neumann problem so that it is fully
831  /// determined).
833  {
834  for(unsigned nd=0, nnd=nnode(); nd<nnd; nd++)
835  {
836  if( !(node_pt(nd)->is_on_boundary()))
837  {
838  return node_pt(nd);
839  }
840  }
841 
842  std::ostringstream error_msg;
843  error_msg << "No non-boundary nodes in the mesh.";
844  throw OomphLibError(error_msg.str(),
845  OOMPH_CURRENT_FUNCTION,
846  OOMPH_EXCEPTION_LOCATION);
847  // Never get here!
848  return 0;
849  }
850 
851  /// Return number of finite elements that are adjacent to boundary b
852  unsigned nboundary_element(const unsigned &b) const
853  {
854 #ifdef PARANOID
855  if (!Lookup_for_elements_next_boundary_is_setup)
856  {
857  throw OomphLibError(
858  "Lookup scheme for elements next to boundary hasn't been set up yet!\n",
859  OOMPH_CURRENT_FUNCTION,
860  OOMPH_EXCEPTION_LOCATION);
861  }
862 #endif
863  return Boundary_element_pt[b].size();
864  }
865 
866 
867  /// \short For the e-th finite element on boundary b, return int to indicate
868  /// the face_index of the face adjacent to the boundary. This is consistent
869  /// with input required during the generation of FaceElements.
870  int face_index_at_boundary(const unsigned &b, const unsigned &e) const
871  {
872 #ifdef PARANOID
873  if (!Lookup_for_elements_next_boundary_is_setup)
874  {
875  throw OomphLibError(
876  "Lookup scheme for elements next to boundary hasn't been set up yet!\n",
877  OOMPH_CURRENT_FUNCTION,
878  OOMPH_EXCEPTION_LOCATION);
879  }
880 #endif
881  return Face_index_at_boundary[b][e];
882  }
883 
884  /// Dump the data in the mesh into a file for restart
885  virtual void dump(std::ofstream &dump_file,
886  const bool& use_old_ordering=true) const;
887 
888  /// Dump the data in the mesh into a file for restart
889  void dump(const std::string &dump_file_name,
890  const bool& use_old_ordering=true) const
891  {
892  std::ofstream dump_stream(dump_file_name.c_str());
893 #ifdef PARANOID
894  if(!dump_stream.is_open())
895  {
896  std::string err = "Couldn't open file "+dump_file_name;
897  throw OomphLibError(err, OOMPH_EXCEPTION_LOCATION,
898  OOMPH_CURRENT_FUNCTION);
899  }
900 #endif
901  dump(dump_stream, use_old_ordering);
902  }
903 
904  /// \short Read solution from restart file
905  virtual void read(std::ifstream &restart_file);
906 
907 
908  /// \short Output in paraview format into specified file. Breaks up each
909  /// element into sub-elements for plotting purposes. We assume
910  /// that all elements are of the same type (fct will break
911  /// break (in paranoid mode) if paraview output fcts of the
912  /// elements are inconsistent).
913  void output_paraview(std::ofstream &file_out,
914  const unsigned &nplot) const;
915 
916  /// \short Output in paraview format into specified file. Breaks up each
917  /// element into sub-elements for plotting purposes. We assume
918  /// that all elements are of the same type (fct will break
919  /// break (in paranoid mode) if paraview output fcts of the
920  /// elements are inconsistent).
921  void output_fct_paraview(std::ofstream &file_out,
922  const unsigned &nplot,
923  FiniteElement::SteadyExactSolutionFctPt exact_soln_pt) const;
924 
925  /// Output for all elements
926  void output(std::ostream &outfile);
927 
928  /// Output at f(n_plot) points in each element
929  void output(std::ostream &outfile, const unsigned &n_plot);
930 
931  /// Output for all elements (C-style output)
932  void output(FILE* file_pt);
933 
934  /// Output at f(n_plot) points in each element (C-style output)
935  void output(FILE* file_pt, const unsigned &nplot);
936 
937  /// Output for all elements
938  void output(const std::string& output_filename)
939  {
940  std::ofstream outfile;
941  outfile.open(output_filename.c_str());
942  output(outfile);
943  outfile.close();
944  }
945 
946  /// Output at f(n_plot) points in each element
947  void output(const std::string& output_filename, const unsigned &n_plot)
948  {
949  std::ofstream outfile;
950  outfile.open(output_filename.c_str());
951  output(outfile,n_plot);
952  outfile.close();
953  }
954 
955  /// Output a given Vector function at f(n_plot) points in each element
956  void output_fct(std::ostream &outfile, const unsigned &n_plot,
958 
959  /// \short Output a given time-dep. Vector function at f(n_plot) points in
960  /// each element
961  void output_fct(std::ostream &outfile, const unsigned &n_plot,
962  const double& time,
964 
965  /// Output the nodes on the boundaries (into separate tecplot zones)
966  void output_boundaries(std::ostream &outfile);
967 
968  /// Output the nodes on the boundaries (into separate tecplot zones).
969  /// Specify filename
970  void output_boundaries(const std::string& output_filename)
971  {
972  std::ofstream outfile;
973  outfile.open(output_filename.c_str());
974  output_boundaries(outfile);
975  outfile.close();
976  }
977 
978  /// \short Assign initial values for an impulsive start
980 
981  /// \short Shift time-dependent data along for next timestep:
982  /// Deal with nodal Data/positions and the element's internal
983  /// Data
984  void shift_time_values();
985 
986 
987  /// \short Calculate predictions for all Data and positions associated
988  /// with the mesh, usually used in adaptive time-stepping.
989  void calculate_predictions();
990 
991  /// \short Set the timestepper associated with all nodal and elemental
992  /// data stored in the mesh.
993  void set_nodal_and_elemental_time_stepper(TimeStepper* const &time_stepper_pt,
994  const bool &preserve_existing_data)
995  {
996  this->set_nodal_time_stepper(time_stepper_pt,preserve_existing_data);
997  this->set_elemental_internal_time_stepper(time_stepper_pt,
998  preserve_existing_data);
999  }
1000 
1001  /// \short Function that can be used to set any additional timestepper data
1002  /// stored at the Mesh (as opposed to nodal and elemental) levels. This
1003  /// is virtual so that it can be overloaded in the appropriate Meshes.
1004  /// Examples include the SpineMeshes and adaptive triangle and tet meshes
1005  virtual void set_mesh_level_time_stepper(TimeStepper* const &time_stepper_pt,
1006  const bool &preserve_existing_data);
1007 
1008  /// \short Set consistent values for pinned data in continuation
1010  ContinuationStorageScheme* const &continuation_stepper_pt);
1011 
1012  /// \short Does the double pointer correspond to any mesh data
1013  bool does_pointer_correspond_to_mesh_data(double* const &parameter_pt);
1014 
1015  /// \short Set the timestepper associated with the nodal data in the mesh
1016  void set_nodal_time_stepper(TimeStepper* const &time_stepper_pt,
1017  const bool &preserve_existing_data);
1018 
1019  /// \short Set the timestepper associated with the internal data stored
1020  /// within elements in the meah
1021  void set_elemental_internal_time_stepper(TimeStepper* const &time_stepper_pt,
1022  const bool &preserve_existing_data);
1023 
1024  /// \short Compute norm of solution by summing contributions of
1025  /// compute_norm(...) for all constituent elements in the mesh.
1026  /// What that norm means depends on what's defined in the element's
1027  /// function; may need to take the square root afterwards if the elements
1028  /// compute the square of the L2 norm, say.
1029  virtual void compute_norm(double& norm)
1030  {
1031  //Initialse the norm
1032  norm=0.0;
1033 
1034  //Per-element norm
1035  double el_norm=0;
1036 
1037  //Loop over the elements
1038  unsigned long n_element = Element_pt.size();
1039  for(unsigned long e=0;e<n_element;e++)
1040  {
1041  GeneralisedElement* el_pt=Element_pt[e];
1042 
1043 #ifdef OOMPH_HAS_MPI
1044  //Compute error for each non-halo element
1045  if (!(el_pt->is_halo()))
1046 #endif
1047  {
1048  el_pt->compute_norm(el_norm);
1049  }
1050  norm+=el_norm;
1051  }
1052  }
1053 
1054 
1055  /// \short Plot error when compared against a given exact solution.
1056  /// Also returns the norm of the error and that of the exact solution
1057  virtual void compute_error(std::ostream &outfile,
1059  const double& time,
1060  double& error, double& norm)
1061  {
1062  //Initialse the norm and error
1063  norm=0.0; error=0.0;
1064  //Per-element norm and error
1065  double el_error,el_norm;
1066 
1067  //Loop over the elements
1068  unsigned long Element_pt_range = Element_pt.size();
1069  for(unsigned long e=0;e<Element_pt_range;e++)
1070  {
1071  // Try to cast to FiniteElement
1072  FiniteElement* el_pt=dynamic_cast<FiniteElement*>(Element_pt[e]);
1073  if (el_pt==0)
1074  {
1075  throw OomphLibError(
1076  "Can't execute compute_error(...) for non FiniteElements",
1077  OOMPH_CURRENT_FUNCTION,
1078  OOMPH_EXCEPTION_LOCATION);
1079  }
1080 
1081  // Reset elemental errors and norms
1082  el_norm=0.0;
1083  el_error=0.0;
1084 #ifdef OOMPH_HAS_MPI
1085  //Compute error for each non-halo element
1086  if (!(el_pt->is_halo()))
1087 #endif
1088  {
1089  el_pt->compute_error(outfile,exact_soln_pt,time,el_error,el_norm);
1090  }
1091  //Add each element error to the global errors
1092  norm+=el_norm; error+=el_error;
1093  }
1094  }
1095 
1096  /// \short Plot error when compared against a given time-depdendent
1097  /// exact solution. Also returns the norm of the error and
1098  /// that of the exact solution
1099  virtual void compute_error(std::ostream &outfile,
1101  double& error, double& norm)
1102  {
1103  //Initialise norm and error
1104  norm=0.0; error=0.0;
1105  //Per-element norm and error
1106  double el_error,el_norm;
1107 
1108  //Loop over the elements
1109  unsigned long Element_pt_range = Element_pt.size();
1110  for(unsigned long e=0;e<Element_pt_range;e++)
1111  {
1112  // Try to cast to FiniteElement
1113  FiniteElement* el_pt=dynamic_cast<FiniteElement*>(Element_pt[e]);
1114  if (el_pt==0)
1115  {
1116  throw OomphLibError(
1117  "Can't execute compute_error(...) for non FiniteElements",
1118  OOMPH_CURRENT_FUNCTION,
1119  OOMPH_EXCEPTION_LOCATION);
1120  }
1121  // Reset elemental errors and norms
1122  el_norm=0.0;
1123  el_error=0.0;
1124  //Calculate the elemental errors for each non-halo element
1125 #ifdef OOMPH_HAS_MPI
1126  if (!(el_pt->is_halo()))
1127 #endif
1128  {
1129  el_pt->compute_error(outfile,exact_soln_pt,el_error,el_norm);
1130  }
1131  //Add each elemental error to the global error
1132  norm+=el_norm; error+=el_error;
1133  }
1134  }
1135 
1136  /// \short Plot error when compared against a given time-depdendent
1137  /// exact solution. Also returns the norm of the error and
1138  /// that of the exact solution. Version with vectors of norms and errors so
1139  /// that different variables' norms and errors can be returned individually
1140  virtual void compute_error(
1141  std::ostream &outfile,
1143  const double& time,
1144  Vector<double>& error, Vector<double>& norm)
1145  {
1146  //Initialise norm and error
1147  unsigned n_error=error.size();
1148  unsigned n_norm=norm.size();
1149  for(unsigned i=0;i<n_error;i++)
1150  {
1151  error[i]=0.0;
1152  }
1153  for(unsigned i=0;i<n_norm;i++)
1154  {
1155  norm[i]=0.0;
1156  }
1157  //Per-element norm and error
1158  Vector<double> el_error(n_error),el_norm(n_norm);
1159 
1160  //Loop over the elements
1161  unsigned long Element_pt_range = Element_pt.size();
1162  for(unsigned long e=0;e<Element_pt_range;e++)
1163  {
1164  // Try to cast to FiniteElement
1165  FiniteElement* el_pt=dynamic_cast<FiniteElement*>(Element_pt[e]);
1166  if (el_pt==0)
1167  {
1168  throw OomphLibError(
1169  "Can't execute compute_error(...) for non FiniteElements",
1170  OOMPH_CURRENT_FUNCTION,
1171  OOMPH_EXCEPTION_LOCATION);
1172  }
1173  // Reset elemental errors and norms
1174  for(unsigned i=0;i<n_error;i++)
1175  {
1176  el_error[i]=0.0;
1177  }
1178  for(unsigned i=0;i<n_norm;i++)
1179  {
1180  el_norm[i]=0.0;
1181  }
1182  //Calculate the elemental errors for each non-halo element
1183 #ifdef OOMPH_HAS_MPI
1184  if (!(el_pt->is_halo()))
1185 #endif
1186  {
1187  el_pt->compute_error(outfile,exact_soln_pt,time,el_error,el_norm);
1188  }
1189  //Add each elemental error to the global error
1190  for(unsigned i=0;i<n_error;i++)
1191  {
1192  error[i]+=el_error[i];
1193  }
1194  for(unsigned i=0;i<n_norm;i++)
1195  {
1196  norm[i]+=el_norm[i];
1197  }
1198  }
1199  }
1200 
1201  /// \short Plot error when compared against a given time-depdendent
1202  /// exact solution. Also returns the norm of the error and
1203  /// that of the exact solution. Version with vectors of norms and errors so
1204  /// that different variables' norms and errors can be returned individually
1205  virtual void compute_error(std::ostream &outfile,
1207  Vector<double>& error, Vector<double>& norm)
1208  {
1209  //Initialise norm and error
1210  unsigned n_error=error.size();
1211  unsigned n_norm=norm.size();
1212  for(unsigned i=0;i<n_error;i++)
1213  {
1214  error[i]=0.0;
1215  }
1216  for(unsigned i=0;i<n_norm;i++)
1217  {
1218  norm[i]=0.0;
1219  }
1220  //Per-element norm and error
1221  Vector<double> el_error(n_error),el_norm(n_norm);
1222 
1223  //Loop over the elements
1224  unsigned long Element_pt_range = Element_pt.size();
1225  for(unsigned long e=0;e<Element_pt_range;e++)
1226  {
1227  // Try to cast to FiniteElement
1228  FiniteElement* el_pt=dynamic_cast<FiniteElement*>(Element_pt[e]);
1229  if (el_pt==0)
1230  {
1231  throw OomphLibError(
1232  "Can't execute compute_error(...) for non FiniteElements",
1233  OOMPH_CURRENT_FUNCTION,
1234  OOMPH_EXCEPTION_LOCATION);
1235  }
1236  // Reset elemental errors and norms
1237  for(unsigned i=0;i<n_error;i++)
1238  {
1239  el_error[i]=0.0;
1240  }
1241  for(unsigned i=0;i<n_norm;i++)
1242  {
1243  el_norm[i]=0.0;
1244  }
1245  //Calculate the elemental errors for each non-halo element
1246 #ifdef OOMPH_HAS_MPI
1247  if (!(el_pt->is_halo()))
1248 #endif
1249  {
1250  el_pt->compute_error(outfile,exact_soln_pt,el_error,el_norm);
1251  }
1252  //Add each elemental error to the global error
1253  for(unsigned i=0;i<n_error;i++)
1254  {
1255  error[i]+=el_error[i];
1256  }
1257  for(unsigned i=0;i<n_norm;i++)
1258  {
1259  norm[i]+=el_norm[i];
1260  }
1261  }
1262  }
1263 
1264 
1265  /// Boolean to indicate if Mesh has been distributed
1266  bool is_mesh_distributed() const
1267  {
1268 #ifdef OOMPH_HAS_MPI
1269  return communicator_pt() != 0;
1270 #else
1271  // Can't be distributed without mpi
1272  return false;
1273 #endif
1274  }
1275 
1276  /// Read-only access fct to communicator (Null if mesh is not distributed,
1277  /// i.e. if we don't have mpi).
1279  {
1280 #ifdef OOMPH_HAS_MPI
1281  return Comm_pt;
1282 #else
1283  return 0;
1284 #endif
1285  }
1286 
1287 
1288 #ifdef OOMPH_HAS_MPI
1289 
1290  /// Function to set communicator (mesh is assumed to be distributed if the
1291  /// communicator pointer is non-null). Only defined if mpi is enabled
1292  /// becaus Comm_pt itself is only defined when mpi is enabled.
1293  void set_communicator_pt(OomphCommunicator* comm_pt) {Comm_pt = comm_pt;}
1294 
1295  /// \short Call this function to keep all the elements as halo elements
1296  void set_keep_all_elements_as_halos() {Keep_all_elements_as_halos=true;}
1297 
1298  /// \short Calll this function to unset the flag that keeps all elements
1299  /// in the mesh as halo elements
1300  void unset_keep_all_elements_as_halos() {Keep_all_elements_as_halos=false;}
1301 
1302  /// \short Distribute the problem and doc; make this virtual to allow
1303  /// overloading for particular meshes where further work is required.
1304  /// Add to vector of pointers to deleted elements.
1305  virtual void distribute(OomphCommunicator* comm_pt,
1306  const Vector<unsigned>& element_domain,
1307  Vector<GeneralisedElement*>& deleted_element_pt,
1308  DocInfo& doc_info,
1309  const bool& report_stats,
1310  const bool& overrule_keep_as_halo_element_status);
1311 
1312  /// \short Distribute the problem
1313  /// Add to vector of pointers to deleted elements.
1315  const Vector<unsigned>& element_domain,
1316  Vector<GeneralisedElement*>& deleted_element_pt,
1317  const bool& report_stats=false)
1318  {
1319  DocInfo doc_info;
1320  doc_info.disable_doc();
1321  bool overrule_keep_as_halo_element_status=false;
1322  return distribute(comm_pt,element_domain,deleted_element_pt,
1323  doc_info,report_stats,
1324  overrule_keep_as_halo_element_status);
1325  }
1326 
1327  /// \short (Irreversibly) prune halo(ed) elements and nodes, usually
1328  /// after another round of refinement, to get rid of
1329  /// excessively wide halo layers. Note that the current
1330  /// mesh will be now regarded as the base mesh and no unrefinement
1331  /// relative to it will be possible once this function
1332  /// has been called.
1334  deleted_element_pt,
1335  const bool& report_stats=false)
1336  {
1337  DocInfo doc_info;
1338  doc_info.disable_doc();
1339  prune_halo_elements_and_nodes(deleted_element_pt,
1340  doc_info,report_stats);
1341  }
1342 
1343 
1344  /// \short (Irreversibly) prune halo(ed) elements and nodes, usually
1345  /// after another round of refinement, to get rid of
1346  /// excessively wide halo layers. Note that the current
1347  /// mesh will be now regarded as the base mesh and no unrefinement
1348  /// relative to it will be possible once this function
1349  /// has been called.
1351  deleted_element_pt,
1352  DocInfo& doc_info,
1353  const bool& report_stats);
1354 
1355  /// \short Get efficiency of mesh distribution: In an ideal distribution
1356  /// without halo overhead, each processor would only hold its own
1357  /// elements. Efficieny per processor = (number of non-halo elements)/
1358  /// (total number of elements).
1359  void get_efficiency_of_mesh_distribution(double& av_efficiency,
1360  double& max_efficiency,
1361  double& min_efficiency);
1362 
1363  /// Doc the mesh distribution, to be processed with tecplot macros
1364  void doc_mesh_distribution(DocInfo& doc_info);
1365 
1366  /// Check halo and shared schemes on the mesh
1367  void check_halo_schemes(DocInfo& doc_info,
1368  double& max_permitted_error_for_halo_check);
1369 
1370  /// \short Classify the halo and haloed nodes in the mesh. Virtual
1371  /// so it can be overloaded to perform additional functionality
1372  /// (such as synchronising hanging nodes) in refineable meshes, say.
1373  virtual void classify_halo_and_haloed_nodes(DocInfo& doc_info,
1374  const bool& report_stats);
1375 
1376  /// Classify the halo and haloed nodes in the mesh. Virtual
1377  /// so it can be overloaded to perform additional functionality
1378  /// (such as synchronising hanging nodes) in refineable meshes, say.
1379  virtual void classify_halo_and_haloed_nodes(const bool& report_stats=false)
1380  {
1381  DocInfo doc_info;
1382  doc_info.disable_doc();
1383  classify_halo_and_haloed_nodes(doc_info,report_stats);
1384  }
1385 
1386  /// \short Synchronise shared node lookup schemes to cater for the
1387  /// the case where:
1388  /// (1) a certain node on the current processor is halo with proc p
1389  /// (i.e. its non-halo counterpart lives on processor p)
1390  /// (2) that node is also exists (also as a halo) on another processor
1391  /// (q, say) where its non-halo counter part is also known to be
1392  /// on processor p.
1393  /// However, without calling this function the current processor does not
1394  /// necessarily know that it shares a node with processor q. This
1395  /// information can be required, e.g. when synchronising hanging node
1396  /// schemes over all processors.
1397  void synchronise_shared_nodes(const bool& report_stats);
1398 
1399 
1400  /// \short Get all the halo data stored in the mesh and add pointers to
1401  /// the data to the map, indexed by global equation number
1402  void get_all_halo_data(std::map<unsigned,double*> &map_of_halo_data);
1403 
1404  /// \short Return vector of halo elements in this Mesh
1405  /// whose non-halo counterpart is held on processor p.
1407  {
1408  // Prepare vector
1409  Vector<GeneralisedElement*> vec_el_pt;
1410 
1411  // Loop over all root halo elements
1412  unsigned nelem=nroot_halo_element(p);
1413  for (unsigned e=0;e<nelem;e++)
1414  {
1416 
1417  // Is it a refineable element?
1418  RefineableElement* ref_el_pt=dynamic_cast<RefineableElement*>(el_pt);
1419  if (ref_el_pt!=0)
1420  {
1421  // Vector of pointers to leaves in tree emanating from
1422  // current root halo element
1423  Vector<Tree*> leaf_pt;
1424  ref_el_pt->tree_pt()->stick_leaves_into_vector(leaf_pt);
1425 
1426  // Loop over leaves and add their objects (the finite elements)
1427  // to vector
1428  unsigned nleaf=leaf_pt.size();
1429  for (unsigned l=0;l<nleaf;l++)
1430  {
1431  vec_el_pt.push_back(leaf_pt[l]->object_pt());
1432  }
1433  }
1434  else
1435  {
1436  vec_el_pt.push_back(el_pt);
1437  }
1438  }
1439  return vec_el_pt;
1440  }
1441 
1442 
1443  /// \short Return vector of haloed elements in this Mesh
1444  /// whose haloing counterpart is held on processor p.
1446  {
1447  // Prepare vector
1448  Vector<GeneralisedElement*> vec_el_pt;
1449 
1450  // Loop over all root haloed elements
1451  unsigned nelem=nroot_haloed_element(p);
1452  for (unsigned e=0;e<nelem;e++)
1453  {
1455 
1456  // Is it a refineable element?
1457  RefineableElement* ref_el_pt=dynamic_cast<RefineableElement*>(el_pt);
1458  if (ref_el_pt!=0)
1459  {
1460  // Vector of pointers to leaves in tree emanating from
1461  // current root haloed element
1462  Vector<Tree*> leaf_pt;
1463  ref_el_pt->tree_pt()->stick_leaves_into_vector(leaf_pt);
1464 
1465  // Loop over leaves and add their objects (the finite elements)
1466  // to vector
1467  unsigned nleaf=leaf_pt.size();
1468  for (unsigned l=0;l<nleaf;l++)
1469  {
1470  vec_el_pt.push_back(leaf_pt[l]->object_pt());
1471  }
1472  }
1473  else
1474  {
1475  vec_el_pt.push_back(el_pt);
1476  }
1477  }
1478  return vec_el_pt;
1479  }
1480 
1481  /// \short Total number of non-halo elements in this mesh (Costly call computes
1482  /// result on the fly)
1484  {
1485  unsigned count=0;
1486  unsigned n=nelement();
1487  for (unsigned e=0;e<n;e++)
1488  {
1489  if (!(element_pt(e)->is_halo())) count++;
1490  }
1491  return count;
1492  }
1493 
1494 
1495  /// \short Total number of root halo elements in this Mesh
1497  {
1498  unsigned n=0;
1499  for (std::map<unsigned,Vector<GeneralisedElement*> >::iterator it=
1500  Root_halo_element_pt.begin();it!=Root_halo_element_pt.end();it++)
1501  {
1502  n+=it->second.size();
1503  }
1504  return n;
1505  }
1506 
1507 
1508  /// \short Number of root halo elements in this Mesh whose non-halo
1509  /// counterpart is held on processor p.
1510  unsigned nroot_halo_element(const unsigned& p)
1511  {
1512  return Root_halo_element_pt[p].size();
1513  }
1514 
1515 
1516  /// \short Vector of pointers to root halo elements in this Mesh
1517  /// whose non-halo counterpart is held on processor p.
1519  {
1520  return Root_halo_element_pt[p];
1521  }
1522 
1523 
1524  /// \short Access fct to the e-th root halo element in this Mesh
1525  /// whose non-halo counterpart is held on processor p.
1527  const unsigned& e)
1528  {
1529  return Root_halo_element_pt[p][e];
1530  }
1531 
1532 
1533  /// \short Add root halo element whose non-halo counterpart is held
1534  /// on processor p to this Mesh.
1535  void add_root_halo_element_pt(const unsigned& p, GeneralisedElement*& el_pt)
1536  {
1537  Root_halo_element_pt[p].push_back(el_pt);
1538  el_pt->set_halo(p);
1539  }
1540 
1541  /// \short Total number of halo nodes in this Mesh
1542  unsigned nhalo_node()
1543  {
1544  unsigned n=0;
1545  for (std::map<unsigned,Vector<Node*> >::iterator it=
1546  Halo_node_pt.begin();it!=Halo_node_pt.end();it++)
1547  {
1548  n+=it->second.size();
1549  }
1550  return n;
1551  }
1552 
1553  /// \short Number of halo nodes in this Mesh whose non-halo counterpart
1554  /// is held on processor p.
1555  unsigned nhalo_node(const unsigned& p)
1556  {
1557  //Memory saving version of: return Halo_node_pt[p].size();
1558  std::map<unsigned, Vector<Node*> >::iterator it=
1559  Halo_node_pt.find(p);
1560  if (it==Halo_node_pt.end())
1561  {
1562  return 0;
1563  }
1564  return (*it).second.size();
1565  }
1566 
1567  /// \short Add halo node whose non-halo counterpart is held
1568  /// on processor p to the storage scheme for halo nodes.
1569  void add_halo_node_pt(const unsigned& p, Node*& nod_pt)
1570  {
1571  Halo_node_pt[p].push_back(nod_pt);
1572  }
1573 
1574 
1575  /// \short Access fct to the j-th halo node in this Mesh
1576  /// whose non-halo counterpart is held on processor p.
1577  Node* halo_node_pt(const unsigned& p, const unsigned& j)
1578  {
1579  return Halo_node_pt[p][j];
1580  }
1581 
1582 
1583  /// \short Total number of root haloed elements in this Mesh
1585  {
1586  unsigned n=0;
1587  for (std::map<unsigned,Vector<GeneralisedElement*> >::iterator it=
1588  Root_haloed_element_pt.begin();it!=Root_haloed_element_pt.end();it++)
1589  {
1590  n+=it->second.size();
1591  }
1592  return n;
1593  }
1594 
1595  /// \short Number of root haloed elements in this Mesh whose non-halo
1596  /// counterpart is held on processor p.
1597  unsigned nroot_haloed_element(const unsigned& p)
1598  {
1599  //Memory saving version of: return Root_haloed_element_pt[p].size();
1600  std::map<unsigned, Vector<GeneralisedElement*> >::iterator it=
1601  Root_haloed_element_pt.find(p);
1602  if (it==Root_haloed_element_pt.end())
1603  {
1604  return 0;
1605  }
1606  return (*it).second.size();
1607  }
1608 
1609 
1610  /// \short Vector of pointers to root haloed elements in this Mesh
1611  /// whose non-halo counterpart is held on processor p.
1613  {
1614  //Memory saving version of: return Root_haloed_element_pt[p];
1615  std::map<unsigned, Vector<GeneralisedElement*> >::iterator it=
1616  Root_haloed_element_pt.find(p);
1617  if (it==Root_haloed_element_pt.end())
1618  {
1620  return tmp;
1621  }
1622  return (*it).second;
1623  }
1624 
1625  /// \short Access fct to the e-th root haloed element in this Mesh
1626  /// whose non-halo counterpart is held on processor p.
1628  const unsigned& e)
1629  {
1630  return Root_haloed_element_pt[p][e];
1631  }
1632 
1633  /// \short Add root haloed element whose non-halo counterpart is held
1634  /// on processor p to the storage scheme for haloed elements.
1635  /// Note: This does not add the element to the storage scheme
1636  /// for elements as it's understood to naturally live on this
1637  /// processor anyway!
1638  void add_root_haloed_element_pt(const unsigned& p, GeneralisedElement*& el_pt)
1639  {
1640  Root_haloed_element_pt[p].push_back(el_pt);
1641  }
1642 
1643 
1644  /// \short Total number of haloed nodes in this Mesh
1645  unsigned nhaloed_node()
1646  {
1647  unsigned n=0;
1648  for (std::map<unsigned,Vector<Node*> >::iterator it=
1649  Haloed_node_pt.begin();it!=Haloed_node_pt.end();it++)
1650  {
1651  n+=it->second.size();
1652  }
1653  return n;
1654  }
1655 
1656 
1657  /// \short Number of haloed nodes in this Mesh whose haloed counterpart
1658  /// is held on processor p.
1659  unsigned nhaloed_node(const unsigned& p)
1660  {
1661  // Memory saving version of: return Haloed_node_pt[p].size();
1662  std::map<unsigned, Vector<Node*> >::iterator it=
1663  Haloed_node_pt.find(p);
1664  if (it==Haloed_node_pt.end())
1665  {
1666  return 0;
1667  }
1668  return (*it).second.size();
1669  }
1670 
1671  /// \short Access fct to the j-th haloed node in this Mesh
1672  /// whose halo counterpart is held on processor p.
1673  Node* haloed_node_pt(const unsigned& p, const unsigned& j)
1674  {
1675  return Haloed_node_pt[p][j];
1676  }
1677 
1678  /// \short Add haloed node whose halo counterpart is held
1679  /// on processor p to the storage scheme for haloed nodes.
1680  void add_haloed_node_pt(const unsigned& p, Node*& nod_pt)
1681  {
1682  Haloed_node_pt[p].push_back(nod_pt);
1683  }
1684 
1685  /// Bool for output of halo elements
1687 
1688 
1689  /// \short Function to suppress resizing of halo nodes -- optmisation
1690  /// but call it at your own risk!
1692  {
1693  Resize_halo_nodes_not_required=true;
1694  }
1695 
1696 
1697  /// \short Function to (re-)enable resizing of halo nodes -- this returns
1698  /// things to the default behaviour.
1700  {
1701  Resize_halo_nodes_not_required=false;
1702  }
1703 
1704  /// Function to disable halo element output
1706  {
1707  Output_halo_elements=false;
1708  }
1709 
1710  /// Function to enable halo element output
1712  {
1713  Output_halo_elements=true;
1714  }
1715 
1716  /// \short Total number of shared nodes in this Mesh
1717  unsigned nshared_node()
1718  {
1719  unsigned n=0;
1720  for (std::map<unsigned,Vector<Node*> >::iterator it=
1721  Shared_node_pt.begin();it!=Shared_node_pt.end();it++)
1722  {
1723  n+=it->second.size();
1724  }
1725  return n;
1726  }
1727 
1728  /// \short Doc shared nodes
1730  {
1731  for (std::map<unsigned,Vector<Node*> >::iterator it=
1732  Shared_node_pt.begin();it!=Shared_node_pt.end();it++)
1733  {
1734  unsigned n=it->second.size();
1735  for (unsigned j=0;j<n;j++)
1736  {
1737  oomph_info << "Shared node with proc " << it->first << " ";
1738  Node* nod_pt=it->second[j];
1739  unsigned ndim=nod_pt->ndim();
1740  for (unsigned i=0;i<ndim;i++)
1741  {
1742  oomph_info << nod_pt->x(i) << " ";
1743  }
1744  oomph_info << nod_pt->is_hanging() << " ";
1745  oomph_info << j << " " << nod_pt << std::endl;
1746  }
1747  }
1748  }
1749 
1750  /// \short Number of shared nodes in this Mesh who have a counterpart
1751  /// on processor p.
1752  unsigned nshared_node(const unsigned& p)
1753  {
1754  // Memory saving version of: return Shared_node_pt[p].size();
1755  std::map<unsigned, Vector<Node*> >::iterator it=
1756  Shared_node_pt.find(p);
1757  if (it==Shared_node_pt.end())
1758  {
1759  return 0;
1760  }
1761  return (*it).second.size();
1762  }
1763 
1764  /// \short Access fct to the j-th shared node in this Mesh
1765  /// who has a counterpart on processor p.
1766  Node* shared_node_pt(const unsigned& p, const unsigned& j)
1767  {
1768  return Shared_node_pt[p][j];
1769  }
1770 
1771  /// \short Get vector of pointers to shared nodes with processor p.
1772  /// Required for faster search in
1773  /// Missing_masters_functions::add_external_haloed_node_helper() and
1774  /// Missing_masters_functions::add_external_haloed_master_node_helper()
1776  {
1777  unsigned np=nshared_node(p);
1778  shared_node_pt.resize(np);
1779  for (unsigned j=0;j<np;j++)
1780  {
1781  shared_node_pt[j] = Shared_node_pt[p][j];
1782  }
1783  }
1784 
1785 
1786  /// \short Add shared node whose counterpart is held
1787  /// on processor p to the storage scheme for shared nodes.
1788  /// (NB: ensure that this routine is called twice, once for each process)
1789  void add_shared_node_pt(const unsigned& p, Node*& nod_pt)
1790  {
1791  Shared_node_pt[p].push_back(nod_pt);
1792  }
1793 
1794  /// \short Get halo node stats for this distributed mesh:
1795  /// Average/max/min number of halo nodes over all processors.
1796  /// \b Careful: Involves MPI Broadcasts and must therefore
1797  /// be called on all processors!
1798  void get_halo_node_stats(double& av_number,
1799  unsigned& max_number,
1800  unsigned& min_number);
1801 
1802  /// \short Get haloed node stats for this distributed mesh:
1803  /// Average/max/min number of haloed nodes over all processors.
1804  /// \b Careful: Involves MPI Broadcasts and must therefore
1805  /// be called on all processors!
1806  void get_haloed_node_stats(double& av_number,
1807  unsigned& max_number,
1808  unsigned& min_number);
1809 
1810  // External halo(ed) elements are "source/other" elements which are
1811  // on different processes to the element for which they are the source
1812 
1813  /// \short Output all external halo elements
1814  void output_external_halo_elements(std::ostream &outfile,
1815  const unsigned &n_plot=5)
1816  {
1817  for (std::map<unsigned,Vector<GeneralisedElement*> >::iterator it=
1818  External_halo_element_pt.begin();
1819  it!=External_halo_element_pt.end();it++)
1820  {
1821  unsigned p=(*it).first;
1822  output_external_halo_elements(p,outfile,n_plot);
1823  }
1824  }
1825 
1826  /// \short Output all external halo elements with processor p
1827  void output_external_halo_elements(const unsigned& p, std::ostream &outfile,
1828  const unsigned &n_plot=5)
1829  {
1830  unsigned nel=External_halo_element_pt[p].size();
1831  for (unsigned e=0;e<nel;e++)
1832  {
1833  FiniteElement* fe_pt=dynamic_cast<FiniteElement*>(
1834  External_halo_element_pt[p][e]);
1835  if (fe_pt!=0)
1836  {
1837  fe_pt->output(outfile,n_plot);
1838  }
1839  }
1840  }
1841 
1842 
1843  /// \short Output all external haloed elements
1844  void output_external_haloed_elements(std::ostream &outfile,
1845  const unsigned &n_plot=5)
1846  {
1847  for (std::map<unsigned,Vector<GeneralisedElement*> >::iterator it=
1848  External_haloed_element_pt.begin();
1849  it!=External_haloed_element_pt.end();it++)
1850  {
1851  unsigned p=(*it).first;
1852  output_external_haloed_elements(p,outfile,n_plot);
1853  }
1854  }
1855 
1856  /// \short Output all external haloed elements with processor p
1857  void output_external_haloed_elements(const unsigned& p, std::ostream &outfile,
1858  const unsigned &n_plot=5)
1859  {
1860  unsigned nel=External_haloed_element_pt[p].size();
1861  for (unsigned e=0;e<nel;e++)
1862  {
1863  FiniteElement* fe_pt=dynamic_cast<FiniteElement*>(
1864  External_haloed_element_pt[p][e]);
1865  if (fe_pt!=0)
1866  {
1867  fe_pt->output(outfile,n_plot);
1868  }
1869  }
1870  }
1871 
1872 
1873  /// \short Total number of external halo elements in this Mesh
1875  {
1876  unsigned n=0;
1877  for (std::map<unsigned,Vector<GeneralisedElement*> >::iterator it=
1878  External_halo_element_pt.begin();
1879  it!=External_halo_element_pt.end();it++)
1880  {
1881  n+=it->second.size();
1882  }
1883  return n;
1884  }
1885 
1886  /// \short Number of external halo elements in this Mesh whose non-halo
1887  /// counterpart is held on processor p.
1888  unsigned nexternal_halo_element(const unsigned& p)
1889  {
1890  // Memory saving version of: return External_halo_element_pt[p].size();
1891  std::map<unsigned, Vector<GeneralisedElement*> >::iterator it=
1892  External_halo_element_pt.find(p);
1893  if (it==External_halo_element_pt.end())
1894  {
1895  return 0;
1896  }
1897  return (*it).second.size();
1898  }
1899 
1900  /// \short Access fct to the e-th external halo element in this Mesh
1901  /// whose non-halo counterpart is held on processor p.
1903  const unsigned& e)
1904  {
1905  return External_halo_element_pt[p][e];
1906  }
1907 
1908  /// \short Add external halo element whose non-halo counterpart is held
1909  /// on processor p to this Mesh.
1910  void add_external_halo_element_pt(const unsigned& p,
1911  GeneralisedElement*& el_pt)
1912  {
1913  External_halo_element_pt[p].push_back(el_pt);
1914  el_pt->set_halo(p);
1915  }
1916 
1917  /// \short Total number of external haloed elements in this Mesh
1919  {
1920  unsigned n=0;
1921  for (std::map<unsigned,Vector<GeneralisedElement*> >::iterator it=
1922  External_haloed_element_pt.begin();
1923  it!=External_haloed_element_pt.end();it++)
1924  {
1925  n+=it->second.size();
1926  }
1927  return n;
1928  }
1929 
1930  /// \short Number of external haloed elements in this Mesh whose non-halo
1931  /// counterpart is held on processor p.
1932  unsigned nexternal_haloed_element(const unsigned& p)
1933  {
1934  // Memory saving version of: return External_haloed_element_pt[p].size();
1935  std::map<unsigned, Vector<GeneralisedElement*> >::iterator it=
1936  External_haloed_element_pt.find(p);
1937  if (it==External_haloed_element_pt.end())
1938  {
1939  return 0;
1940  }
1941  return (*it).second.size();
1942  }
1943 
1944  /// \short Access fct to the e-th external haloed element in this Mesh
1945  /// whose non-halo counterpart is held on processor p.
1947  const unsigned& e)
1948  {
1949  return External_haloed_element_pt[p][e];
1950  }
1951 
1952  /// \short Add external haloed element whose non-halo counterpart is held
1953  /// on processor p to the storage scheme for haloed elements.
1954  unsigned add_external_haloed_element_pt(const unsigned& p,
1955  GeneralisedElement*& el_pt);
1956 
1957  /// \short Total number of external halo nodes in this Mesh
1959  {
1960  unsigned n=0;
1961  for (std::map<unsigned,Vector<Node*> >::iterator it=
1962  External_halo_node_pt.begin();it!=External_halo_node_pt.end();it++)
1963  {
1964  n+=it->second.size();
1965  }
1966  return n;
1967  }
1968 
1969 
1970  /// \short Get vector of pointers to all external halo nodes
1972  {
1973  unsigned n_total=nexternal_halo_node();
1974  external_halo_node_pt.reserve(n_total);
1975  for (std::map<unsigned,Vector<Node*> >::iterator it=
1976  External_halo_node_pt.begin();it!=External_halo_node_pt.end();it++)
1977  {
1978  unsigned np=(it->second).size();
1979  for (unsigned j=0;j<np;j++)
1980  {
1981  external_halo_node_pt.push_back((it->second)[j]);
1982  }
1983  }
1984 #ifdef PARANOID
1985  if (external_halo_node_pt.size()!=n_total)
1986  {
1987  std::ostringstream error_stream;
1988  error_stream
1989  << "Total number of external halo nodes, "
1990  << n_total << " doesn't match number of entries \n in vector, "
1991  << external_halo_node_pt.size() << std::endl;
1992  throw OomphLibError(error_stream.str(),
1993  OOMPH_CURRENT_FUNCTION,
1994  OOMPH_EXCEPTION_LOCATION);
1995  }
1996 #endif
1997  }
1998 
1999 
2000  /// \short Number of external halo nodes in this Mesh whose non-halo
2001  /// (external) counterpart is held on processor p.
2002  unsigned nexternal_halo_node(const unsigned& p)
2003  {
2004  // Memory saving version of: return External_halo_node_pt[p].size();
2005  std::map<unsigned, Vector<Node*> >::iterator it=
2006  External_halo_node_pt.find(p);
2007  if (it==External_halo_node_pt.end())
2008  {
2009  return 0;
2010  }
2011  return (*it).second.size();
2012  }
2013 
2014  /// \short Add external halo node whose non-halo (external) counterpart
2015  /// is held on processor p to the storage scheme for halo nodes.
2016  void add_external_halo_node_pt(const unsigned& p, Node*& nod_pt)
2017  {
2018  External_halo_node_pt[p].push_back(nod_pt);
2019  nod_pt->set_halo(p);
2020  }
2021 
2022 
2023  /// \short Access fct to the j-th external halo node in this Mesh
2024  /// whose non-halo external counterpart is held on processor p.
2025  Node* &external_halo_node_pt(const unsigned& p, const unsigned& j)
2026  {
2027  return External_halo_node_pt[p][j];
2028  }
2029 
2030  /// \short Access fct to vector of external halo node in this Mesh
2031  /// whose non-halo external counterpart is held on processor p. (read only)
2033  {
2034  std::map<unsigned, Vector<Node*> >::iterator it=
2035  External_halo_node_pt.find(p);
2036  if (it==External_halo_node_pt.end())
2037  {
2038  Vector<Node*> tmp;
2039  return tmp;
2040  }
2041  return (*it).second;
2042  }
2043 
2044  /// \short Set vector of external halo node in this Mesh
2045  /// whose non-halo external counterpart is held on processor p.
2046  void set_external_halo_node_pt(const unsigned& p,
2048  {
2049  External_halo_node_pt[p]=external_halo_node_pt;
2050  }
2051 
2052  /// Null out specified external halo node (used when deleting duplicates)
2053  void null_external_halo_node(const unsigned& p, Node* nod_pt);
2054 
2055  /// \short Consolidate external halo node storage by removing nulled out
2056  /// pointes in external halo and haloed schemes
2058 
2059  /// \short Total number of external haloed nodes in this Mesh
2061  {
2062  unsigned n=0;
2063  for (std::map<unsigned,Vector<Node*> >::iterator it=
2064  External_haloed_node_pt.begin();it!=External_haloed_node_pt.end();it++)
2065  {
2066  n+=it->second.size();
2067  }
2068  return n;
2069  }
2070 
2071  /// \short Number of external haloed nodes in this Mesh
2072  /// whose halo (external) counterpart is held on processor p.
2073  unsigned nexternal_haloed_node(const unsigned& p)
2074  {
2075  // Memory saving version of: return External_haloed_node_pt[p].size();
2076  std::map<unsigned, Vector<Node*> >::iterator it=
2077  External_haloed_node_pt.find(p);
2078  if (it==External_haloed_node_pt.end())
2079  {
2080  return 0;
2081  }
2082  return (*it).second.size();
2083  }
2084 
2085  /// \short Access fct to the j-th external haloed node in this Mesh
2086  /// whose halo external counterpart is held on processor p.
2087  Node* &external_haloed_node_pt(const unsigned &p, const unsigned &j)
2088  {
2089  return External_haloed_node_pt[p][j];
2090  }
2091 
2092  /// \short Add external haloed node whose halo (external) counterpart
2093  /// is held on processor p to the storage scheme for haloed nodes.
2094  unsigned add_external_haloed_node_pt(const unsigned& p, Node*& nod_pt);
2095 
2096  /// \short Access fct to vector of external haloed node in this Mesh
2097  /// whose halo external counterpart is held on processor p. (read only)
2099  {
2100  std::map<unsigned, Vector<Node*> >::iterator it=
2101  External_haloed_node_pt.find(p);
2102  if (it==External_haloed_node_pt.end())
2103  {
2104  Vector<Node*> tmp;
2105  return tmp;
2106  }
2107  return (*it).second;
2108  }
2109 
2110  /// \short Set vector of external haloed node in this Mesh
2111  /// whose halo external counterpart is held on processor p.
2112  void set_external_haloed_node_pt(const unsigned& p,
2114  {
2115  External_haloed_node_pt[p]=external_haloed_node_pt;
2116  }
2117 
2118  /// \short Return the set of processors that hold external halo nodes. This is
2119  /// required to avoid having to pass a communicator into the node_update
2120  /// functions for Algebraic-based and MacroElement-based Meshes
2121  std::set<int> external_halo_proc()
2122  {
2123  std::set<int> procs;
2124  for (std::map<unsigned,Vector<Node*> >::iterator it=
2125  External_halo_node_pt.begin();it!=External_halo_node_pt.end();it++)
2126  {
2127  procs.insert((*it).first);
2128  }
2129  return procs;
2130  }
2131 
2132  /// \short Creates the shared boundaries, only used in unstructured meshes
2133  /// In this case with the "TriangleMesh" class
2135  const Vector<unsigned> &element_domain,
2137  &backed_up_el_pt,
2139  &backed_up_f_el_pt,
2140  std::map<Data*,std::set<unsigned> >
2141  &processors_associated_with_data,
2142  const bool&
2143  overrule_keep_as_halo_element_status)
2144  {
2145  std::ostringstream error_stream;
2146  error_stream << "Empty default create_shared_boundaries() method"
2147  << "called.\n";
2148  error_stream << "This should be overloaded in a specific "
2149  << "TriangleMeshBase\n";
2150  throw OomphLibError(error_stream.str(),
2151  "Mesh::create_shared_boundaries()",
2152  OOMPH_EXCEPTION_LOCATION);
2153  }
2154 
2155  // Check if necessary to add the element as haloed or if it has been
2156  // previously added to the haloed scheme
2157  virtual unsigned try_to_add_root_haloed_element_pt(const unsigned& p,
2158  GeneralisedElement*& el_pt)
2159  {
2160  std::ostringstream error_stream;
2161  error_stream << "Empty default try_to_add_root_haloed_element_pt() method"
2162  << "called.\n";
2163  error_stream << "This should be overloaded in a specific "
2164  << "TriangleMeshBase\n";
2165  throw OomphLibError(error_stream.str(),
2166  "Mesh::try_to_add_root_haloed_element_pt()",
2167  OOMPH_EXCEPTION_LOCATION);
2168  }
2169 
2170  // Check if necessary to add the node as haloed or if it has been
2171  // previously added to the haloed scheme
2172  virtual unsigned try_to_add_haloed_node_pt(const unsigned& p, Node*& nod_pt)
2173  {
2174  std::ostringstream error_stream;
2175  error_stream << "Empty default try_to_add_haloed_node_pt() method"
2176  << "called.\n";
2177  error_stream << "This should be overloaded in a specific "
2178  << "TriangleMeshBase\n";
2179  throw OomphLibError(error_stream.str(),
2180  "Mesh::try_to_add_haloed_node_pt()",
2181  OOMPH_EXCEPTION_LOCATION);
2182  }
2183 
2184 #endif
2185 
2186  /// \short Wipe the storage for all externally-based elements
2188 
2189 
2190 
2191 
2192 };
2193 
2194 
2195 
2196 //////////////////////////////////////////////////////////////////////////
2197 //////////////////////////////////////////////////////////////////////////
2198 //////////////////////////////////////////////////////////////////////////
2199 
2200 class SolidICProblem;
2201 
2202 //========================================================================
2203 /// \short General SolidMesh class.
2204 ///
2205 /// Solid meshes contain SolidFiniteElements which contain
2206 /// SolidNodes. This class simply overloads the appropriate access
2207 /// functions from the underlying Mesh class.
2208 //
2209 // Needs to be derived from Mesh with virtual so that
2210 // solid meshes can be derived from general meshes, without
2211 // multiple copies of Mesh objects
2212 //========================================================================
2213 class SolidMesh : public virtual Mesh
2214 {
2215  public:
2216 
2217 
2218  /// \short Default constructor
2220 
2221  /// Broken copy constructor
2222  SolidMesh(const SolidMesh& dummy)
2223  {
2224  BrokenCopy::broken_copy("SolidMesh");
2225  }
2226 
2227  /// Broken assignment operator
2228  void operator=(const SolidMesh&)
2229  {
2230  BrokenCopy::broken_assign("SolidMesh");
2231  }
2232 
2233 
2234  /// \short Constructor builds combined mesh from the meshes specified.
2235  /// Note: This simply merges the meshes' elements and nodes (ignoring
2236  /// duplicates; no boundary information etc. is created).
2237  SolidMesh(const Vector<SolidMesh*>& sub_mesh_pt)
2238  {
2239 #ifdef OOMPH_HAS_MPI
2240  // Mesh hasn't been distributed: Null out pointer to communicator
2241  Comm_pt=0;
2242 #endif
2243 
2244  unsigned n=sub_mesh_pt.size();
2245  Vector<Mesh*> sub_mesh_mesh_pt(n);
2246  for (unsigned i=0;i<n;i++)
2247  {
2248  sub_mesh_mesh_pt[i]=static_cast<Mesh*>(sub_mesh_pt[i]);
2249  }
2250  merge_meshes(sub_mesh_mesh_pt);
2251  }
2252 
2253  /// Return a pointer to the n-th global SolidNode
2254  //Can safely cast the nodes to SolidNodes
2255  SolidNode* node_pt(const unsigned long &n)
2256  {
2257 #ifdef PARANOID
2258  if(!dynamic_cast<SolidNode*>(Node_pt[n]))
2259  {
2260  std::ostringstream error_stream;
2261  error_stream << "Error: Node " << n << "is a "
2262  << typeid(Node_pt[n]).name()
2263  << ", not an SolidNode" << std::endl;
2264  throw OomphLibError(error_stream.str(),
2265  OOMPH_CURRENT_FUNCTION,
2266  OOMPH_EXCEPTION_LOCATION);
2267  }
2268 #endif
2269  //Return a static cast to the Node_pt
2270  return (static_cast<SolidNode*>(Node_pt[n]));
2271  }
2272 
2273  /// Return n-th SolidNodes on b-th boundary
2274  SolidNode* boundary_node_pt(const unsigned &b,
2275  const unsigned &n)
2276  {
2277 #ifdef PARANOID
2278  if(!dynamic_cast<SolidNode*>(Mesh::boundary_node_pt(b,n)))
2279  {
2280  std::ostringstream error_stream;
2281  error_stream
2282  << "Error: Node " << n << "is a "
2283  << typeid(Mesh::boundary_node_pt(b,n)).name()
2284  << ", not an SolidNode" << std::endl;
2285  throw OomphLibError(error_stream.str(),
2286  OOMPH_CURRENT_FUNCTION,
2287  OOMPH_EXCEPTION_LOCATION);
2288  }
2289 #endif
2290  return static_cast<SolidNode*>(Mesh::boundary_node_pt(b,n));
2291  }
2292 
2293  /// \short Return the n-th local SolidNode in elemnet e.
2294  ///This is required to cast the nodes in a solid mesh to be
2295  ///SolidNodes and therefore allow access to the extra SolidNode data
2296  SolidNode* element_node_pt(const unsigned long &e,
2297  const unsigned &n)
2298  {
2299 #ifdef PARANOID
2300  // Try to cast to FiniteElement
2301  FiniteElement* el_pt=dynamic_cast<FiniteElement*>(Element_pt[e]);
2302  if (el_pt==0)
2303  {
2304  //Error
2305  throw OomphLibError("Failed cast to FiniteElement* ",
2306  OOMPH_CURRENT_FUNCTION,
2307  OOMPH_EXCEPTION_LOCATION);
2308  }
2309  if(!dynamic_cast<SolidNode*>(el_pt->node_pt(n)))
2310  {
2311  std::ostringstream error_message;
2312  Node *np = el_pt->node_pt(n);
2313  error_message << "Error: Node " << n << " of element " << e
2314  << "is a " << typeid(*np).name()
2315  << ", not an SolidNode" << std::endl;
2316 
2317  throw OomphLibError(error_message.str(),
2318  OOMPH_CURRENT_FUNCTION,
2319  OOMPH_EXCEPTION_LOCATION);
2320  }
2321 #endif
2322  //Return a cast to an SolidNode
2323  return(static_cast<SolidNode*>(
2324  dynamic_cast<FiniteElement*>(Element_pt[e])->node_pt(n)));
2325  }
2326 
2327  /// \short Make the current configuration the undeformed one by
2328  /// setting the nodal Lagrangian coordinates to their current
2329  /// Eulerian ones
2330  void set_lagrangian_nodal_coordinates();
2331 
2332 
2333  /// \short Scale all nodal coordinates by given factor and re-assign the
2334  /// Lagrangian coordinates
2335  void scale_mesh(const double& factor)
2336  {
2337  Mesh::scale_mesh(factor);
2338 
2339  //Re-assign the Lagrangian coordinates
2340  set_lagrangian_nodal_coordinates();
2341  }
2342  /// \short Static problem that can be used to assign initial conditions
2343  /// on a given solid mesh (need to define this as a static problem
2344  /// somewhere because deleting the problem would wipe out the mesh too!)
2346 
2347 
2348 };
2349 
2350 
2351 
2352 
2353 ///////////////////////////////////////////////////////////////////////////
2354 ///////////////////////////////////////////////////////////////////////////
2355 ///////////////////////////////////////////////////////////////////////////
2356 
2357 
2358 
2359 //===================================================
2360 /// Edge class
2361 //===================================================
2362  class Edge
2363  {
2364 
2365  public:
2366 
2367  /// Constructor: Pass in the two vertex nodes
2368  Edge(Node* node1_pt, Node* node2_pt)
2369  {
2370  if (node1_pt==node2_pt)
2371  {
2372 #ifdef PARANOID
2373  std::ostringstream error_stream;
2374  error_stream << "Edge cannot have two identical vertex nodes\n";
2375  throw OomphLibError(
2376  error_stream.str(),
2377  OOMPH_CURRENT_FUNCTION,
2378  OOMPH_EXCEPTION_LOCATION);
2379 #endif
2380  }
2381 
2382 
2383  // Sort lexicographically based on pointer address of nodes
2384  if (node1_pt>node2_pt)
2385  {
2386  Node1_pt=node1_pt;
2387  Node2_pt=node2_pt;
2388  }
2389  else
2390  {
2391  Node1_pt=node2_pt;
2392  Node2_pt=node1_pt;
2393  }
2394  }
2395 
2396 
2397  /// Access to the first vertex node
2398  Node* node1_pt() const {return Node1_pt;}
2399 
2400  /// Access to the second vertex node
2401  Node* node2_pt() const {return Node2_pt;}
2402 
2403  /// Comparison operator
2404  bool operator==(const Edge& other) const
2405  {
2406  if ((Node1_pt==other.node1_pt())&&
2407  (Node2_pt==other.node2_pt()))
2408 
2409  {
2410  return true;
2411  }
2412  else
2413  {
2414  return false;
2415  }
2416  }
2417 
2418 
2419 
2420  /// Less-than operator
2421  bool operator<(const Edge& other) const
2422  {
2423  if (Node1_pt<other.node1_pt())
2424  {
2425  return true;
2426  }
2427  else if (Node1_pt==other.node1_pt())
2428  {
2429  if (Node2_pt<other.node2_pt())
2430  {
2431  return true;
2432  }
2433  else
2434  {
2435  return false;
2436  }
2437  }
2438  else
2439  {
2440  return false;
2441  }
2442  }
2443 
2444  /// \short Test whether the Edge lies on a boundary. Relatively simple
2445  /// test, based on both vertices lying on (some) boundary.
2446  bool is_on_boundary() const
2447  {
2448  return (Node1_pt->is_on_boundary() && Node2_pt->is_on_boundary() );
2449  }
2450 
2451 
2452  /// \short Test whether the Edge is a boundary edge, i.e. does it
2453  /// connnect two boundary nodes?
2454  bool is_boundary_edge() const
2455  {
2456  return ((dynamic_cast<BoundaryNodeBase*>(Node1_pt)!=0)&&
2457  (dynamic_cast<BoundaryNodeBase*>(Node2_pt)!=0));
2458  }
2459 
2460  private:
2461 
2462  /// First vertex node
2464 
2465  /// Second vertex node
2467  };
2468 
2469 
2470 
2471 ///////////////////////////////////////////////////////////////////////
2472 ///////////////////////////////////////////////////////////////////////
2473 ///////////////////////////////////////////////////////////////////////
2474 
2475 
2476 
2477 //=================================================================
2478 /// Namespace with helper function to check element type in mesh
2479 /// constructors (say).
2480 //=================================================================
2481 namespace MeshChecker
2482 {
2483 
2484 
2485 //=================================================================
2486 /// \short Helper function to assert that finite element of type ELEMENT
2487 /// can be cast to base class of type GEOM_ELEMENT_BASE -- useful
2488 /// to avoid confusion if a mesh that was written for a specific
2489 /// element type (e.g. a QElement) is used with another one (e.g.
2490 /// a TElement. First argument specifies the required spatial dimension
2491 /// of the element (i.e. the number of local coordinates). The optional
2492 /// second argument specifies the required nnode_1d (i.e. the number
2493 /// of nodes along a 1D element edge). Can be omitted if the mesh
2494 /// can handle any number in which case this test is skipped.
2495 //=================================================================
2496  template<class GEOM_ELEMENT_BASE, class ELEMENT>
2497  void assert_geometric_element(const unsigned& dim,
2498  const unsigned& nnode_1d=0)
2499  {
2500  // Only do tests in paranoia mode
2501 #ifndef PARANOID
2502  return;
2503 #endif
2504 
2505  // Instantiate element
2506  ELEMENT* el_pt=new ELEMENT;
2507 
2508  // Can we cast to required geometric element base type
2509  if (dynamic_cast<GEOM_ELEMENT_BASE*>(el_pt)==0)
2510  {
2511  std::stringstream error_message;
2512  error_message
2513  << "You have specified an illegal element type! Element is of type \n\n"
2514  << typeid(el_pt).name()
2515  << "\n\nand cannot be cast to type \n\n "
2516  << typeid(GEOM_ELEMENT_BASE).name()
2517  << "\n\n";
2518  throw OomphLibError(error_message.str(),
2519  OOMPH_CURRENT_FUNCTION,
2520  OOMPH_EXCEPTION_LOCATION);
2521  }
2522 
2523  // Does the dimension match?
2524  if (dim!=el_pt->dim())
2525  {
2526  std::stringstream error_message;
2527  error_message
2528  << "You have specified an illegal element type! Element is of type \n\n"
2529  << typeid(el_pt).name()
2530  << "\n\nand has dimension = " << el_pt->dim()
2531  << " but we need dim = " << dim << std::endl;
2532  throw OomphLibError(error_message.str(),
2533  OOMPH_CURRENT_FUNCTION,
2534  OOMPH_EXCEPTION_LOCATION);
2535 
2536  }
2537 
2538  // Does nnode_1d match?
2539  if (nnode_1d!=0)
2540  {
2541  if (nnode_1d!=el_pt->nnode_1d())
2542  {
2543  std::stringstream error_message;
2544  error_message
2545  << "You have specified an illegal element type! Element is of type \n\n"
2546  << typeid(el_pt).name()
2547  << "\n\nand has nnode_1d = " << el_pt->nnode_1d()
2548  << " but we need nnode_1d = " << nnode_1d << std::endl;
2549  throw OomphLibError(error_message.str(),
2550  OOMPH_CURRENT_FUNCTION,
2551  OOMPH_EXCEPTION_LOCATION);
2552  }
2553  }
2554 
2555  // Clean up
2556  delete el_pt;
2557 
2558  }
2559 
2560 }
2561 
2562 
2563 
2564 ///////////////////////////////////////////////////////////////////////
2565 ///////////////////////////////////////////////////////////////////////
2566 ///////////////////////////////////////////////////////////////////////
2567 
2568 
2569 //=================paraview_helper=================================
2570 /// Namespace for paraview-style output helper functions
2571 //=================================================================
2572 namespace ParaviewHelper
2573 {
2574 
2575  /// Write the pvd file header
2576  extern void write_pvd_header(std::ofstream &pvd_file);
2577 
2578  /// \short Add name of output file and associated continuous time
2579  /// to pvd file.
2580  extern void write_pvd_information(std::ofstream &pvd_file,
2581  const std::string& output_filename,
2582  const double& time);
2583 
2584  /// Write the pvd file footer
2585  extern void write_pvd_footer(std::ofstream &pvd_file);
2586 
2587 }
2588 
2589 ////////////////////////////////////////////////////////////////
2590 ////////////////////////////////////////////////////////////////
2591 ////////////////////////////////////////////////////////////////
2592 
2593 namespace NodeOrdering
2594 {
2595  /// Function for ordering nodes. Return true if first node's position is
2596  /// "before" second nodes. Dimension 0 checked first, then... until they
2597  /// are different (by more than tol=1e-10). If they are both in exactly
2598  /// the same place an error is thrown.
2599  inline bool node_global_position_comparison(Node* nd1_pt, Node* nd2_pt)
2600  {
2601  unsigned ndim = nd1_pt->ndim();
2602 
2603  unsigned j;
2604  for(j=0; j<ndim; j++)
2605  {
2606  if(std::abs(nd1_pt->x(j) - nd2_pt->x(j)) > 1e-10)
2607  {
2608  if(nd1_pt->x(j) < nd2_pt->x(j))
2609  {
2610  return true;
2611  }
2612  else
2613  {
2614  return false;
2615  }
2616  }
2617  // otherwise they are the same in this dimension, check next one.
2618  }
2619 
2620  std::string err = "Nodes are at the same point to ~ 1e-10!";
2621  err += " difference is " +
2622  StringConversion::to_string(std::abs(nd1_pt->x(j) - nd2_pt->x(j)));
2623  throw OomphLibError(err, OOMPH_EXCEPTION_LOCATION,
2624  OOMPH_CURRENT_FUNCTION);
2625  }
2626 }
2627 
2628 
2629 }
2630 
2631 #endif
unsigned nshared_node()
Total number of shared nodes in this Mesh.
Definition: mesh.h:1717
virtual std::string tecplot_zone_string(const unsigned &nplot) const
Return string for tecplot zone header (when plotting nplot points in each "coordinate direction") ...
Definition: elements.h:2990
static bool Suppress_warning_about_empty_mesh_level_time_stepper_function
Boolean used to control warning about empty mesh level timestepper function.
Definition: mesh.h:246
void output_boundaries(const std::string &output_filename)
Definition: mesh.h:970
void assign_local_eqn_numbers(const bool &store_local_dof_pt)
Assign the local equation numbers in all elements If the boolean argument is true then also store poi...
Definition: mesh.cc:702
unsigned nboundary_element(const unsigned &b) const
Return number of finite elements that are adjacent to boundary b.
Definition: mesh.h:852
A Generalised Element class.
Definition: elements.h:76
virtual void distribute(OomphCommunicator *comm_pt, const Vector< unsigned > &element_domain, Vector< GeneralisedElement *> &deleted_element_pt, DocInfo &doc_info, const bool &report_stats, const bool &overrule_keep_as_halo_element_status)
Distribute the problem and doc; make this virtual to allow overloading for particular meshes where fu...
Definition: mesh.cc:4620
void set_communicator_pt(OomphCommunicator *comm_pt)
Definition: mesh.h:1293
Node * haloed_node_pt(const unsigned &p, const unsigned &j)
Access fct to the j-th haloed node in this Mesh whose halo counterpart is held on processor p...
Definition: mesh.h:1673
void doc_boundary_coordinates(const unsigned &b, std::ofstream &the_file)
Output boundary coordinates on boundary b – template argument specifies the bulk element type (neede...
Definition: mesh.h:316
void add_shared_node_pt(const unsigned &p, Node *&nod_pt)
Add shared node whose counterpart is held on processor p to the storage scheme for shared nodes...
Definition: mesh.h:1789
virtual void reset_boundary_element_info(Vector< unsigned > &ntmp_boundary_elements, Vector< Vector< unsigned > > &ntmp_boundary_elements_in_region, Vector< FiniteElement *> &deleted_elements)
Virtual function to perform the reset boundary elements info rutines.
Definition: mesh.h:297
GeneralisedElement *& root_haloed_element_pt(const unsigned &p, const unsigned &e)
Access fct to the e-th root haloed element in this Mesh whose non-halo counterpart is held on process...
Definition: mesh.h:1627
unsigned nexternal_halo_node(const unsigned &p)
Number of external halo nodes in this Mesh whose non-halo (external) counterpart is held on processor...
Definition: mesh.h:2002
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
unsigned ndof_types() const
Return number of dof types in mesh.
Definition: mesh.cc:8395
unsigned nexternal_haloed_node(const unsigned &p)
Number of external haloed nodes in this Mesh whose halo (external) counterpart is held on processor p...
Definition: mesh.h:2073
void disable_resizing_of_halo_nodes()
Function to suppress resizing of halo nodes – optmisation but call it at your own risk! ...
Definition: mesh.h:1691
std::map< unsigned, Vector< Node * > > Shared_node_pt
Definition: mesh.h:127
void write_pvd_footer(std::ofstream &pvd_file)
Write the pvd file footer.
Definition: mesh.cc:9261
Vector< GeneralisedElement * > halo_element_pt(const unsigned &p)
Return vector of halo elements in this Mesh whose non-halo counterpart is held on processor p...
Definition: mesh.h:1406
Vector< Node * > Node_pt
Vector of pointers to nodes.
Definition: mesh.h:194
std::map< unsigned, Vector< GeneralisedElement * > > Root_halo_element_pt
Map of vectors holding the pointers to the root halo elements.
Definition: mesh.h:111
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
Definition: mesh.h:497
unsigned nexternal_halo_element()
Total number of external halo elements in this Mesh.
Definition: mesh.h:1874
std::map< unsigned, Vector< Node * > > Haloed_node_pt
Map of vectors holding the pointers to the haloed nodes.
Definition: mesh.h:120
SolidMesh(const Vector< SolidMesh *> &sub_mesh_pt)
Constructor builds combined mesh from the meshes specified. Note: This simply merges the meshes&#39; elem...
Definition: mesh.h:2237
void convert_to_boundary_node(Node *&node_pt, const Vector< FiniteElement *> &finite_element_pt)
A function that upgrades an ordinary node to a boundary node We shouldn&#39;t ever really use this...
Definition: mesh.cc:2317
SolidMesh(const SolidMesh &dummy)
Broken copy constructor.
Definition: mesh.h:2222
SolidNode * element_node_pt(const unsigned long &e, const unsigned &n)
Return the n-th local SolidNode in elemnet e. This is required to cast the nodes in a solid mesh to b...
Definition: mesh.h:2296
void get_shared_node_pt(const unsigned &p, Vector< Node *> &shared_node_pt)
Get vector of pointers to shared nodes with processor p. Required for faster search in Missing_master...
Definition: mesh.h:1775
void doc_shared_nodes()
Doc shared nodes.
Definition: mesh.h:1729
std::map< unsigned, Vector< GeneralisedElement * > > External_halo_element_pt
Map of vectors holding the pointers to the external halo elements.
Definition: mesh.h:137
void add_boundary_node(const unsigned &b, Node *const &node_pt)
Add a (pointer to) a node to the b-th boundary.
Definition: mesh.cc:246
void add_external_halo_node_pt(const unsigned &p, Node *&nod_pt)
Add external halo node whose non-halo (external) counterpart is held on processor p to the storage sc...
Definition: mesh.h:2016
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
virtual void get_s_plot(const unsigned &i, const unsigned &nplot, Vector< double > &s, const bool &shifted_to_interior=false) const
Get cector of local coordinates of plot point i (when plotting nplot points in each "coordinate direc...
Definition: elements.h:2978
static Steady< 0 > Default_TimeStepper
Default Steady Timestepper, to be used in default arguments to Mesh constructors. ...
Definition: mesh.h:85
SolidMesh()
Default constructor.
Definition: mesh.h:2219
virtual void output(std::ostream &outfile)
Output the element data — typically the values at the nodes in a format suitable for post-processing...
Definition: elements.h:2884
void output_fct(std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt)
Output a given Vector function at f(n_plot) points in each element.
Definition: mesh.cc:1936
Node * node_pt(const unsigned long &n) const
Return pointer to global node n (const version)
Definition: mesh.h:459
std::vector< bool > Boundary_coordinate_exists
Vector of boolean data that indicates whether the boundary coordinates have been set for the boundary...
Definition: mesh.h:201
unsigned add_external_haloed_element_pt(const unsigned &p, GeneralisedElement *&el_pt)
Add external haloed element whose non-halo counterpart is held on processor p to the storage scheme f...
Definition: mesh.cc:9087
Vector< GeneralisedElement * > & element_pt()
Return reference to the Vector of elements.
Definition: mesh.h:473
virtual ~Mesh()
Virtual Destructor to clean up all memory.
Definition: mesh.cc:588
Information for documentation of results: Directory and file number to enable output in the form RESL...
Vector< Node * > external_halo_node_pt(const unsigned &p)
Access fct to vector of external halo node in this Mesh whose non-halo external counterpart is held o...
Definition: mesh.h:2032
void get_external_halo_node_pt(Vector< Node *> &external_halo_node_pt)
Get vector of pointers to all external halo nodes.
Definition: mesh.h:1971
Mesh()
Default constructor.
Definition: mesh.h:249
cstr elem_len * i
Definition: cfortran.h:607
void add_root_haloed_element_pt(const unsigned &p, GeneralisedElement *&el_pt)
Add root haloed element whose non-halo counterpart is held on processor p to the storage scheme for h...
Definition: mesh.h:1638
void add_halo_node_pt(const unsigned &p, Node *&nod_pt)
Add halo node whose non-halo counterpart is held on processor p to the storage scheme for halo nodes...
Definition: mesh.h:1569
void shift_time_values()
Shift time-dependent data along for next timestep: Deal with nodal Data/positions and the element&#39;s i...
Definition: mesh.cc:2059
void describe_local_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the local dofs of the elements. The ostream specifies the output stream to which...
Definition: mesh.cc:683
std::map< unsigned, Vector< Node * > > External_haloed_node_pt
Map of vectors holding the pointers to the external haloed nodes.
Definition: mesh.h:149
GeneralisedElement *& external_halo_element_pt(const unsigned &p, const unsigned &e)
Access fct to the e-th external halo element in this Mesh whose non-halo counterpart is held on proce...
Definition: mesh.h:1902
void add_root_halo_element_pt(const unsigned &p, GeneralisedElement *&el_pt)
Add root halo element whose non-halo counterpart is held on processor p to this Mesh.
Definition: mesh.h:1535
Node * get_some_non_boundary_node() const
Find a node not on any boundary in mesh_pt (useful for pinning a single node in a purely Neumann prob...
Definition: mesh.h:832
The Problem class.
Definition: problem.h:152
unsigned nexternal_halo_node()
Total number of external halo nodes in this Mesh.
Definition: mesh.h:1958
bool Output_halo_elements
Bool for output of halo elements.
Definition: mesh.h:1686
A general Finite Element class.
Definition: elements.h:1274
void enable_output_of_halo_elements()
Function to enable halo element output.
Definition: mesh.h:1711
void(* UnsteadyExactSolutionFctPt)(const double &, const Vector< double > &, Vector< double > &)
Function pointer for function that computes Vector-valued time-dependent function as ...
Definition: elements.h:1729
Node * boundary_node_pt(const unsigned &b, const unsigned &n) const
Return pointer to node n on boundary b.
Definition: mesh.h:501
void get_halo_node_stats(double &av_number, unsigned &max_number, unsigned &min_number)
Get halo node stats for this distributed mesh: Average/max/min number of halo nodes over all processo...
Definition: mesh.cc:4514
void operator=(const Mesh &)
Broken assignment operator.
Definition: mesh.h:408
virtual void set_mesh_level_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Function that can be used to set any additional timestepper data stored at the Mesh (as opposed to no...
Definition: mesh.cc:2132
void unset_keep_all_elements_as_halos()
Calll this function to unset the flag that keeps all elements in the mesh as halo elements...
Definition: mesh.h:1300
double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s. Overloaded to get information from bulk...
Definition: elements.h:4322
FiniteElement * boundary_element_pt(const unsigned &b, const unsigned &e) const
Return pointer to e-th finite element on boundary b.
Definition: mesh.h:814
virtual void scale_mesh(const double &factor)
Scale all nodal coordinates by given factor. Virtual so it can be overloaded in SolidMesh class where...
Definition: mesh.h:386
bool boundary_coordinate_exists(const unsigned &i) const
Indicate whether the i-th boundary has an intrinsic coordinate.
Definition: mesh.h:565
bool is_halo() const
Is this element a halo?
Definition: elements.h:1141
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:852
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
Definition: mesh.h:809
unsigned self_test()
Self-test: Check elements and nodes. Return 0 for OK.
Definition: mesh.cc:715
unsigned nodal_dimension() const
Return number of nodal dimension in mesh.
Definition: mesh.cc:8679
Vector< GeneralisedElement * > haloed_element_pt(const unsigned &p)
Return vector of haloed elements in this Mesh whose haloing counterpart is held on processor p...
Definition: mesh.h:1445
void operator=(const SolidMesh &)
Broken assignment operator.
Definition: mesh.h:2228
GeneralisedElement *& root_halo_element_pt(const unsigned &p, const unsigned &e)
Access fct to the e-th root halo element in this Mesh whose non-halo counterpart is held on processor...
Definition: mesh.h:1526
OomphInfo oomph_info
virtual void dump(std::ofstream &dump_file, const bool &use_old_ordering=true) const
Dump the data in the mesh into a file for restart.
Definition: mesh.cc:1027
void set_elemental_internal_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Set the timestepper associated with the internal data stored within elements in the meah...
Definition: mesh.cc:2262
bool is_hanging() const
Test whether the node is geometrically hanging.
Definition: nodes.h:1207
int face_index_at_boundary(const unsigned &b, const unsigned &e) const
For the e-th finite element on boundary b, return int to indicate the face_index of the face adjacent...
Definition: mesh.h:870
unsigned nroot_haloed_element()
Total number of root haloed elements in this Mesh.
Definition: mesh.h:1584
void output_external_haloed_elements(std::ostream &outfile, const unsigned &n_plot=5)
Output all external haloed elements.
Definition: mesh.h:1844
unsigned nhalo_node(const unsigned &p)
Number of halo nodes in this Mesh whose non-halo counterpart is held on processor p...
Definition: mesh.h:1555
void build_face_mesh(const unsigned &b, Mesh *const &face_mesh_pt)
Constuct a Mesh of FACE_ELEMENTs along the b-th boundary of the mesh (which contains elements of type...
Definition: mesh.h:639
virtual void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, Vector< double > &error, Vector< double > &norm)
Plot error when compared against a given time-depdendent exact solution. Also returns the norm of the...
Definition: mesh.h:1205
e
Definition: cfortran.h:575
void set_boundary_number_in_bulk_mesh(const unsigned &b)
Set function for the boundary number in bulk mesh.
Definition: elements.h:4277
unsigned nnon_halo_element()
Total number of non-halo elements in this mesh (Costly call computes result on the fly) ...
Definition: mesh.h:1483
bool Lookup_for_elements_next_boundary_is_setup
Definition: mesh.h:98
void get_efficiency_of_mesh_distribution(double &av_efficiency, double &max_efficiency, double &min_efficiency)
Get efficiency of mesh distribution: In an ideal distribution without halo overhead, each processor would only hold its own elements. Efficieny per processor = (number of non-halo elements)/ (total number of elements).
Definition: mesh.cc:6050
void check_inverted_elements(bool &mesh_has_inverted_elements)
Check for inverted elements and report outcome.
Definition: mesh.h:727
unsigned nexternal_haloed_element(const unsigned &p)
Number of external haloed elements in this Mesh whose non-halo counterpart is held on processor p...
Definition: mesh.h:1932
double size() const
Definition: elements.cc:4207
void(FiniteElement::* UnsteadyExactSolutionFctPt)(const double &time, const Vector< double > &x, Vector< double > &soln)
Typedef for function pointer to function that computes unsteady exact solution.
Definition: mesh.h:241
void copy_boundary_node_data_from_nodes()
Definition: mesh.h:526
virtual unsigned nplot_points(const unsigned &nplot) const
Return total number of plot points (when plotting nplot points in each "coordinate direction") ...
Definition: elements.h:3017
void get_haloed_node_stats(double &av_number, unsigned &max_number, unsigned &min_number)
Get haloed node stats for this distributed mesh: Average/max/min number of haloed nodes over all proc...
Definition: mesh.cc:4569
void write_pvd_information(std::ofstream &pvd_file, const std::string &output_filename, const double &time)
Add name of output file and associated continuous time to pvd file.
Definition: mesh.cc:9240
void remove_boundary_node(const unsigned &b, Node *const &node_pt)
Definition: mesh.cc:222
virtual void compute_norm(double &norm)
Compute norm of solution – broken virtual can be overloaded by element writer to implement whatever ...
Definition: elements.h:1119
unsigned long nelement() const
Return number of elements in the mesh.
Definition: mesh.h:587
void output(const std::string &output_filename, const unsigned &n_plot)
Output at f(n_plot) points in each element.
Definition: mesh.h:947
GeneralisedElement * element_pt(const unsigned long &e) const
Return pointer to element e (const version)
Definition: mesh.h:466
virtual void classify_halo_and_haloed_nodes(const bool &report_stats=false)
Definition: mesh.h:1379
void output(std::ostream &outfile)
Output for all elements.
Definition: mesh.cc:1761
void assign_initial_values_impulsive()
Assign initial values for an impulsive start.
Definition: mesh.cc:2023
Vector< Node * > external_haloed_node_pt(const unsigned &p)
Access fct to vector of external haloed node in this Mesh whose halo external counterpart is held on ...
Definition: mesh.h:2098
void add_node_pt(Node *const &node_pt)
Add a (pointer to a) node to the mesh.
Definition: mesh.h:602
void output_fct_paraview(std::ofstream &file_out, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt) const
Output in paraview format into specified file. Breaks up each element into sub-elements for plotting ...
Definition: mesh.cc:1465
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:992
void flush_element_storage()
Flush storage for elements (only) by emptying the vectors that store the pointers to them...
Definition: mesh.h:443
SolidNode * node_pt(const unsigned long &n)
Return a pointer to the n-th global SolidNode.
Definition: mesh.h:2255
void scale_mesh(const double &factor)
Scale all nodal coordinates by given factor and re-assign the Lagrangian coordinates.
Definition: mesh.h:2335
virtual void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Return a pointer to set of mesh boundaries that this node occupies; this will be overloaded by Bounda...
Definition: nodes.h:1284
unsigned nexternal_halo_element(const unsigned &p)
Number of external halo elements in this Mesh whose non-halo counterpart is held on processor p...
Definition: mesh.h:1888
void calculate_predictions()
Calculate predictions for all Data and positions associated with the mesh, usually used in adaptive t...
Definition: mesh.cc:2098
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:995
unsigned add_external_haloed_node_pt(const unsigned &p, Node *&nod_pt)
Add external haloed node whose halo (external) counterpart is held on processor p to the storage sche...
Definition: mesh.cc:9128
bool Keep_all_elements_as_halos
bool to indicate whether to keep all elements in a mesh as halos or not
Definition: mesh.h:152
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as ...
Definition: elements.h:1723
void check_inverted_elements(bool &mesh_has_inverted_elements, std::ofstream &inverted_element_file)
Check for inverted elements and report outcome in boolean variable. This visits all elements at their...
Definition: mesh.cc:802
void null_external_halo_node(const unsigned &p, Node *nod_pt)
Null out specified external halo node (used when deleting duplicates)
Definition: mesh.cc:8206
void set_nodal_and_elemental_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Set the timestepper associated with all nodal and elemental data stored in the mesh.
Definition: mesh.h:993
unsigned nhalo_node()
Total number of halo nodes in this Mesh.
Definition: mesh.h:1542
void set_keep_all_elements_as_halos()
Call this function to keep all the elements as halo elements.
Definition: mesh.h:1296
std::map< unsigned, Vector< GeneralisedElement * > > Root_haloed_element_pt
Map of vectors holding the pointers to the root haloed elements.
Definition: mesh.h:114
virtual unsigned try_to_add_root_haloed_element_pt(const unsigned &p, GeneralisedElement *&el_pt)
Definition: mesh.h:2157
std::map< unsigned, Vector< GeneralisedElement * > > External_haloed_element_pt
Map of vectors holding the pointers to the external haloed elements.
Definition: mesh.h:140
void flush_node_storage()
Flush storage for nodes (only) by emptying the vectors that store the pointers to them...
Definition: mesh.h:450
Edge(Node *node1_pt, Node *node2_pt)
Constructor: Pass in the two vertex nodes.
Definition: mesh.h:2368
Mesh(const Mesh &dummy)
Broken copy constructor.
Definition: mesh.h:402
Vector< Vector< int > > Face_index_at_boundary
For the e-th finite element on boundary b, this is the index of the face that lies along that boundar...
Definition: mesh.h:106
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
Definition: mesh.h:462
Node * node2_pt() const
Access to the second vertex node.
Definition: mesh.h:2401
bool operator==(const Edge &other) const
Comparison operator.
Definition: mesh.h:2404
bool is_mesh_distributed() const
Boolean to indicate if Mesh has been distributed.
Definition: mesh.h:1266
unsigned nhaloed_node(const unsigned &p)
Number of haloed nodes in this Mesh whose haloed counterpart is held on processor p...
Definition: mesh.h:1659
Mesh(const Vector< Mesh *> &sub_mesh_pt)
Constructor builds combined mesh from the meshes specified. Note: This simply merges the meshes&#39; elem...
Definition: mesh.h:270
void interpolated_zeta(const Vector< double > &s, Vector< double > &zeta) const
Calculate the interpolated value of zeta, the intrinsic coordinate of the element when viewed as a co...
Definition: elements.cc:4564
Node *& external_halo_node_pt(const unsigned &p, const unsigned &j)
Access fct to the j-th external halo node in this Mesh whose non-halo external counterpart is held on...
Definition: mesh.h:2025
unsigned nexternal_haloed_element()
Total number of external haloed elements in this Mesh.
Definition: mesh.h:1918
void set_halo(const unsigned &non_halo_proc_ID)
Label the element as halo and specify processor that holds non-halo counterpart.
Definition: elements.h:1132
virtual void create_shared_boundaries(OomphCommunicator *comm_pt, const Vector< unsigned > &element_domain, const Vector< GeneralisedElement *> &backed_up_el_pt, const Vector< FiniteElement *> &backed_up_f_el_pt, std::map< Data *, std::set< unsigned > > &processors_associated_with_data, const bool &overrule_keep_as_halo_element_status)
Creates the shared boundaries, only used in unstructured meshes In this case with the "TriangleMesh" ...
Definition: mesh.h:2134
void distribute(OomphCommunicator *comm_pt, const Vector< unsigned > &element_domain, Vector< GeneralisedElement *> &deleted_element_pt, const bool &report_stats=false)
Distribute the problem Add to vector of pointers to deleted elements.
Definition: mesh.h:1314
unsigned nboundary() const
Return number of boundaries.
Definition: mesh.h:806
static char t char * s
Definition: cfortran.h:572
double total_size()
Determine the sum of all "sizes" of the FiniteElements in the mesh (non-FiniteElements are ignored)...
Definition: mesh.h:693
void set_nboundary(const unsigned &nbound)
Set the number of boundaries in the mesh.
Definition: mesh.h:505
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
unsigned nexternal_haloed_node()
Total number of external haloed nodes in this Mesh.
Definition: mesh.h:2060
Tree * tree_pt()
Access function: Pointer to quadtree representation of this element.
Vector< Node * > prune_dead_nodes()
Prune nodes. Nodes that have been marked as obsolete are removed from the mesh (and its boundary-node...
Definition: mesh.cc:900
Node * Node1_pt
First vertex node.
Definition: mesh.h:2463
Node * shared_node_pt(const unsigned &p, const unsigned &j)
Access fct to the j-th shared node in this Mesh who has a counterpart on processor p...
Definition: mesh.h:1766
virtual void write_tecplot_zone_footer(std::ostream &outfile, const unsigned &nplot) const
Add tecplot zone "footer" to output stream (when plotting nplot points in each "coordinate direction"...
Definition: elements.h:3003
bool is_boundary_edge() const
Test whether the Edge is a boundary edge, i.e. does it connnect two boundary nodes?
Definition: mesh.h:2454
void output_boundaries(std::ostream &outfile)
Output the nodes on the boundaries (into separate tecplot zones)
Definition: mesh.cc:1001
virtual void compute_norm(double &norm)
Compute norm of solution by summing contributions of compute_norm(...) for all constituent elements i...
Definition: mesh.h:1029
void set_nodal_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Set the timestepper associated with the nodal data in the mesh.
Definition: mesh.cc:2244
virtual void setup_boundary_element_info(std::ostream &outfile)
Setup lookup schemes which establish whic elements are located next to mesh&#39;s boundaries. Doc in outfile (if it&#39;s open). (Empty virtual function – implement this for specific Mesh classes)
Definition: mesh.h:294
Vector< GeneralisedElement * > root_halo_element_pt(const unsigned &p)
Vector of pointers to root halo elements in this Mesh whose non-halo counterpart is held on processor...
Definition: mesh.h:1518
A class that represents a collection of data; each Data object may contain many different individual ...
Definition: nodes.h:89
void add_haloed_node_pt(const unsigned &p, Node *&nod_pt)
Add haloed node whose halo counterpart is held on processor p to the storage scheme for haloed nodes...
Definition: mesh.h:1680
void remove_null_pointers_from_external_halo_node_storage()
Consolidate external halo node storage by removing nulled out pointes in external halo and haloed sch...
Definition: mesh.cc:8226
void prune_halo_elements_and_nodes(Vector< GeneralisedElement *> &deleted_element_pt, const bool &report_stats=false)
(Irreversibly) prune halo(ed) elements and nodes, usually after another round of refinement, to get rid of excessively wide halo layers. Note that the current mesh will be now regarded as the base mesh and no unrefinement relative to it will be possible once this function has been called.
Definition: mesh.h:1333
virtual void get_node_reordering(Vector< Node *> &reordering, const bool &use_old_ordering=true) const
Get a reordering of the nodes in the order in which they appear in elements – can be overloaded for ...
Definition: mesh.cc:500
Vector< GeneralisedElement * > Element_pt
Vector of pointers to generalised elements.
Definition: mesh.h:197
void set_external_haloed_node_pt(const unsigned &p, const Vector< Node *> &external_haloed_node_pt)
Set vector of external haloed node in this Mesh whose halo external counterpart is held on processor ...
Definition: mesh.h:2112
Node *& external_haloed_node_pt(const unsigned &p, const unsigned &j)
Access fct to the j-th external haloed node in this Mesh whose halo external counterpart is held on p...
Definition: mesh.h:2087
void check_halo_schemes(DocInfo &doc_info, double &max_permitted_error_for_halo_check)
Check halo and shared schemes on the mesh.
Definition: mesh.cc:6551
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2109
unsigned nhaloed_node()
Total number of haloed nodes in this Mesh.
Definition: mesh.h:1645
std::map< unsigned, Vector< Node * > > Halo_node_pt
Map of vectors holding the pointers to the halo nodes.
Definition: mesh.h:117
Edge class.
Definition: mesh.h:2362
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Definition: mesh.h:456
GeneralisedTimestepper used to store the arclength derivatives and pervious solutions required in con...
Vector< Vector< FiniteElement * > > Boundary_element_pt
Vector of Vector of pointers to elements on the boundaries: Boundary_element_pt(b,e)
Definition: mesh.h:102
Vector< GeneralisedElement * > root_haloed_element_pt(const unsigned &p)
Vector of pointers to root haloed elements in this Mesh whose non-halo counterpart is held on process...
Definition: mesh.h:1612
void doc_mesh_distribution(DocInfo &doc_info)
Doc the mesh distribution, to be processed with tecplot macros.
Definition: mesh.cc:6123
bool Resize_halo_nodes_not_required
Set this to true to suppress resizing of halo nodes (at your own risk!)
Definition: mesh.h:155
unsigned long nnode() const
Return number of nodes in the mesh.
Definition: mesh.h:590
unsigned nroot_haloed_element(const unsigned &p)
Number of root haloed elements in this Mesh whose non-halo counterpart is held on processor p...
Definition: mesh.h:1597
void output_external_haloed_elements(const unsigned &p, std::ostream &outfile, const unsigned &n_plot=5)
Output all external haloed elements with processor p.
Definition: mesh.h:1857
std::map< unsigned, Vector< Node * > > External_halo_node_pt
Map of vectors holding the pointers to the external halo nodes.
Definition: mesh.h:146
General SolidMesh class.
Definition: mesh.h:2213
void output_external_halo_elements(const unsigned &p, std::ostream &outfile, const unsigned &n_plot=5)
Output all external halo elements with processor p.
Definition: mesh.h:1827
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition: mesh.h:477
void merge_meshes(const Vector< Mesh *> &sub_mesh_pt)
Merge meshes. Note: This simply merges the meshes&#39; elements and nodes (ignoring duplicates; no bounda...
Definition: mesh.cc:69
void set_halo(const unsigned &non_halo_proc_ID)
Label the node as halo and specify processor that holds non-halo counterpart.
Definition: nodes.h:481
void disable_doc()
Disable documentation.
void set_external_halo_node_pt(const unsigned &p, const Vector< Node *> &external_halo_node_pt)
Set vector of external halo node in this Mesh whose non-halo external counterpart is held on processo...
Definition: mesh.h:2046
void output(const std::string &output_filename)
Output for all elements.
Definition: mesh.h:938
virtual void node_update(const bool &update_all_solid_nodes=false)
Update nodal positions in response to changes in the domain shape. Uses the FiniteElement::get_x(...) function for FiniteElements and doesn&#39;t do anything for other element types. If a MacroElement pointer has been set for a FiniteElement, the MacroElement representation is used to update the nodal positions; if not get_x(...) uses the FE interpolation and thus leaves the nodal positions unchanged. Virtual, so it can be overloaded by specific meshes, such as AlgebraicMeshes or SpineMeshes. Generally, this function updates the position of all nodes in response to changes in the boundary position. However, we ignore all SolidNodes since their position is computed as part of the solution – unless the bool flag is set to true. Such calls are typically made when the initial mesh is created and/or after a mesh has been refined repeatedly before the start of the computation.
Definition: mesh.cc:290
A Class for nodes that deform elastically (i.e. position is an unknown in the problem). The idea is that the Eulerian positions are stored in a Data object and the Lagrangian coordinates are stored in addition. The pointer that addresses the Eulerian positions is set to the pointer to Value in the Data object. Hence, SolidNode uses knowledge of the internal structure of Data and must be a friend of the Data class. In order to allow a mesh to deform via an elastic-style equation in deforming-domain problems, the positions are stored separately from the values, so that elastic problems may be combined with any other type of problem.
Definition: nodes.h:1569
unsigned nroot_halo_element()
Total number of root halo elements in this Mesh.
Definition: mesh.h:1496
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
void dump(const std::string &dump_file_name, const bool &use_old_ordering=true) const
Dump the data in the mesh into a file for restart.
Definition: mesh.h:889
Vector< Vector< Node * > > Boundary_node_pt
Vector of Vector of pointers to nodes on the boundaries: Boundary_node_pt(b,n). Note that this is pri...
Definition: mesh.h:94
void synchronise_shared_nodes(const bool &report_stats)
Synchronise shared node lookup schemes to cater for the the case where: (1) a certain node on the cur...
Definition: mesh.cc:2618
void set_consistent_pinned_values_for_continuation(ContinuationStorageScheme *const &continuation_stepper_pt)
Set consistent values for pinned data in continuation.
Definition: mesh.cc:2167
void max_and_min_element_size(double &max_size, double &min_size)
Determine max and min area for all FiniteElements in the mesh (non-FiniteElements are ignored) ...
Definition: mesh.h:676
bool operator<(const Edge &other) const
Less-than operator.
Definition: mesh.h:2421
void output_external_halo_elements(std::ostream &outfile, const unsigned &n_plot=5)
Output all external halo elements.
Definition: mesh.h:1814
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn&#39;t been defined.
unsigned check_for_repeated_nodes(const double &epsilon=1.0e-12)
Check for repeated nodes within a given spatial tolerance. Return (0/1) for (pass/fail).
Definition: mesh.h:737
bool does_pointer_correspond_to_mesh_data(double *const &parameter_pt)
Does the double pointer correspond to any mesh data.
Definition: mesh.cc:2201
void get_all_halo_data(std::map< unsigned, double *> &map_of_halo_data)
Get all the halo data stored in the mesh and add pointers to the data to the map, indexed by global e...
Definition: mesh.cc:4418
virtual void setup_boundary_element_info()
Interface for function that is used to setup the boundary information (Empty virtual function – impl...
Definition: mesh.h:288
static SolidICProblem Solid_IC_problem
Static problem that can be used to assign initial conditions on a given solid mesh (need to define th...
Definition: mesh.h:2345
Node * node1_pt() const
Access to the first vertex node.
Definition: mesh.h:2398
void add_element_pt(GeneralisedElement *const &element_pt)
Add a (pointer to) an element to the mesh.
Definition: mesh.h:605
virtual void reorder_nodes(const bool &use_old_ordering=true)
Re-order nodes in the order in which they appear in elements – can be overloaded for more efficient ...
Definition: mesh.cc:483
bool node_global_position_comparison(Node *nd1_pt, Node *nd2_pt)
Definition: mesh.h:2599
unsigned nroot_halo_element(const unsigned &p)
Number of root halo elements in this Mesh whose non-halo counterpart is held on processor p...
Definition: mesh.h:1510
virtual bool is_on_boundary() const
Test whether the Node lies on a boundary. The "bulk" Node cannot lie on a boundary, so return false. This will be overloaded by BoundaryNodes.
Definition: nodes.h:1290
bool is_on_boundary() const
Test whether the Edge lies on a boundary. Relatively simple test, based on both vertices lying on (so...
Definition: mesh.h:2446
unsigned elemental_dimension() const
Return number of elemental dimension in mesh.
Definition: mesh.cc:8539
const Vector< GeneralisedElement * > & element_pt() const
Return reference to the Vector of elements.
Definition: mesh.h:470
unsigned nshared_node(const unsigned &p)
Number of shared nodes in this Mesh who have a counterpart on processor p.
Definition: mesh.h:1752
void describe_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the dofs of the Mesh. The ostream specifies the output stream to which the descr...
Definition: mesh.cc:648
virtual void compute_error(std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, Vector< double > &error, Vector< double > &norm)
Plot error when compared against a given time-depdendent exact solution. Also returns the norm of the...
Definition: mesh.h:1140
Node * Node2_pt
Second vertex node.
Definition: mesh.h:2466
void disable_output_of_halo_elements()
Function to disable halo element output.
Definition: mesh.h:1705
void assert_geometric_element(const unsigned &dim, const unsigned &nnode_1d=0)
Helper function to assert that finite element of type ELEMENT can be cast to base class of type GEOM_...
Definition: mesh.h:2497
unsigned long assign_global_eqn_numbers(Vector< double *> &Dof_pt)
Assign the global equation numbers in the Data stored at the nodes and also internal element Data...
Definition: mesh.cc:614
virtual void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
Plot error when compared against a given time-depdendent exact solution. Also returns the norm of the...
Definition: mesh.h:1099
void flush_element_and_node_storage()
Flush storage for elements and nodes by emptying the vectors that store the pointers to them...
Definition: mesh.h:427
void enable_resizing_of_halo_nodes()
Function to (re-)enable resizing of halo nodes – this returns things to the default behaviour...
Definition: mesh.h:1699
virtual unsigned try_to_add_haloed_node_pt(const unsigned &p, Node *&nod_pt)
Definition: mesh.h:2172
OomphCommunicator * communicator_pt() const
Definition: mesh.h:1278
void stick_leaves_into_vector(Vector< Tree * > &)
Traverse tree and stick pointers to leaf "nodes" (only) into Vector.
Definition: tree.cc:255
virtual bool is_a_copy() const
Return a boolean to indicate whether the Data objact contains any copied values. A base Data object c...
Definition: nodes.h:255
void add_external_halo_element_pt(const unsigned &p, GeneralisedElement *&el_pt)
Add external halo element whose non-halo counterpart is held on processor p to this Mesh...
Definition: mesh.h:1910
SolidNode * boundary_node_pt(const unsigned &b, const unsigned &n)
Return n-th SolidNodes on b-th boundary.
Definition: mesh.h:2274
std::set< int > external_halo_proc()
Return the set of processors that hold external halo nodes. This is required to avoid having to pass ...
Definition: mesh.h:2121
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
Definition: timesteppers.h:219
virtual void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
Plot the error when compared against a given exact solution . Also calculates the norm of the error a...
Definition: elements.h:3033
void delete_all_external_storage()
Wipe the storage for all externally-based elements.
Definition: mesh.cc:8816
OomphCommunicator * Comm_pt
Pointer to communicator – set to NULL if mesh is not distributed.
Definition: mesh.h:130
virtual void compute_error(std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, double &error, double &norm)
Plot error when compared against a given exact solution. Also returns the norm of the error and that ...
Definition: mesh.h:1057
A general mesh class.
Definition: mesh.h:74
GeneralisedElement *& external_haloed_element_pt(const unsigned &p, const unsigned &e)
Access fct to the e-th external haloed element in this Mesh whose non-halo counterpart is held on pro...
Definition: mesh.h:1946
void(FiniteElement::* SteadyExactSolutionFctPt)(const Vector< double > &x, Vector< double > &soln)
Typedef for function pointer to function that computes steady exact solution.
Definition: mesh.h:236
IC problem for an elastic body discretised on a given (sub)-mesh. We switch the elements&#39; residuals a...
void remove_boundary_nodes()
Clear all pointers to boundary nodes.
Definition: mesh.cc:208
Node * halo_node_pt(const unsigned &p, const unsigned &j)
Access fct to the j-th halo node in this Mesh whose non-halo counterpart is held on processor p...
Definition: mesh.h:1577
std::string to_string(T object, unsigned float_precision=8)
Conversion function that should work for anything with operator<< defined (at least all basic types)...
void output_paraview(std::ofstream &file_out, const unsigned &nplot) const
Output in paraview format into specified file. Breaks up each element into sub-elements for plotting ...
Definition: mesh.cc:1167
void setup_shared_node_scheme()
Setup shared node scheme.
Definition: mesh.cc:2438
virtual void read(std::ifstream &restart_file)
Read solution from restart file.
Definition: mesh.cc:1070
void write_pvd_header(std::ofstream &pvd_file)
Write the pvd file header.
Definition: mesh.cc:9230
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
Definition: communicator.h:57