MFEM  v3.3
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
ncmesh.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 #ifndef MFEM_NCMESH
13 #define MFEM_NCMESH
14 
15 #include "../config/config.hpp"
16 #include "../general/hash.hpp"
17 #include "../linalg/densemat.hpp"
18 #include "element.hpp"
19 #include "vertex.hpp"
20 #include "../fem/geom.hpp"
21 
22 #include <vector>
23 #include <map>
24 #include <iostream>
25 
26 namespace mfem
27 {
28 
29 /** Represents the index of an element to refine, plus a refinement type.
30  The refinement type is needed for anisotropic refinement of quads and hexes.
31  Bits 0,1 and 2 of 'ref_type' specify whether the element should be split
32  in the X, Y and Z directions, respectively (Z is ignored for quads). */
33 struct Refinement
34 {
35  int index; ///< Mesh element number
36  char ref_type; ///< refinement XYZ bit mask (7 = full isotropic)
37 
38  Refinement(int index, int type = 7) : index(index), ref_type(type) {}
39 };
40 
41 /// Defines the position of a fine element within a coarse element.
42 struct Embedding
43 {
44  int parent; ///< element index in the coarse mesh
45  int matrix; ///< index into CoarseFineTransformations::point_matrices
46 
47  Embedding(int elem, int matrix = 0) : parent(elem), matrix(matrix) {}
48 };
49 
50 /// Defines the coarse-fine transformations of all fine elements.
52 {
53  DenseTensor point_matrices; ///< matrices for IsoparametricTransformation
54  Array<Embedding> embeddings; ///< fine element positions in their parents
55  void Clear() { point_matrices.Clear(); embeddings.DeleteAll(); }
56 };
57 
58 
59 /** \brief A class for non-conforming AMR on higher-order hexahedral,
60  * quadrilateral or triangular meshes.
61  *
62  * The class is used as follows:
63  *
64  * 1. NCMesh is constructed from elements of an existing Mesh. The elements
65  * are copied and become roots of the refinement hierarchy.
66  *
67  * 2. Some elements are refined with the Refine() method. Both isotropic and
68  * anisotropic refinements of quads/hexes are supported.
69  *
70  * 3. A new Mesh is created from NCMesh containing the leaf elements.
71  * This new mesh may have non-conforming (hanging) edges and faces.
72  *
73  * 4. FiniteElementSpace asks NCMesh for a list of conforming, master and
74  * slave edges/faces and creates the conforming interpolation matrix P.
75  *
76  * 5. A continuous/conforming solution is obtained by solving P'*A*P x = P'*b.
77  *
78  * 6. Repeat from step 2.
79  */
80 class NCMesh
81 {
82 protected:
83  struct Element; // forward
84 
85 public:
86 
87  /** Initialize with elements from 'mesh'. If an already nonconforming mesh
88  is being loaded, 'vertex_parents' must point to a stream at the appropriate
89  section of the mesh file which contains the vertex hierarchy. */
90  NCMesh(const Mesh *mesh, std::istream *vertex_parents = NULL);
91 
92  /// Deep copy of 'other'.
93  NCMesh(const NCMesh &other);
94 
95  virtual ~NCMesh();
96 
97  int Dimension() const { return Dim; }
98  int SpaceDimension() const { return spaceDim; }
99 
100  /** Perform the given batch of refinements. Please note that in the presence
101  of anisotropic splits additional refinements may be necessary to keep
102  the mesh consistent. However, the function always performs at least the
103  requested refinements. */
104  virtual void Refine(const Array<Refinement> &refinements);
105 
106  /** Check the mesh and potentially refine some elements so that the maximum
107  difference of refinement levels between adjacent elements is not greater
108  than 'max_nc_level'. */
109  virtual void LimitNCLevel(int max_nc_level);
110 
111  /** Return a list of derefinement opportunities. Each row of the table
112  contains Mesh indices of existing elements that can be derefined to form
113  a single new coarse element. Row numbers are then passed to Derefine.
114  This function works both in serial and parallel. */
115  const Table &GetDerefinementTable();
116 
117  /** Check derefinements returned by GetDerefinementTable and mark those that
118  can be done safely so that the maximum NC level condition is not violated.
119  On return, level_ok.Size() == deref_table.Size() and contains 0/1s. */
120  virtual void CheckDerefinementNCLevel(const Table &deref_table,
121  Array<int> &level_ok, int max_nc_level);
122 
123  /** Perform a subset of the possible derefinements (see GetDerefinementTable).
124  Note that if anisotropic refinements are present in the mesh, some of the
125  derefinements may have to be skipped to preserve mesh consistency. */
126  virtual void Derefine(const Array<int> &derefs);
127 
128 
129  // master/slave lists
130 
131  /// Identifies a vertex/edge/face in both Mesh and NCMesh.
132  struct MeshId
133  {
134  int index; ///< Mesh number
135  int local; ///< local number within 'element'
136  Element* element; ///< NCMesh::Element containing this vertex/edge/face
137 
138  MeshId(int index = -1, Element* element = NULL, int local = -1)
140  };
141 
142  /** Nonconforming edge/face that has more than one neighbor. The neighbors
143  are stored in NCList::slaves[i], slaves_begin <= i < slaves_end. */
144  struct Master : public MeshId
145  {
146  int slaves_begin, slaves_end; ///< slave faces
147 
148  Master(int index, Element* element, int local, int sb, int se)
149  : MeshId(index, element, local), slaves_begin(sb), slaves_end(se) {}
150  };
151 
152  /** Nonconforming edge/face within a bigger edge/face.
153  NOTE: only the 'index' member of MeshId is currently valid for slaves. */
154  struct Slave : public MeshId
155  {
156  int master; ///< master number (in Mesh numbering)
157  int edge_flags; ///< edge orientation flags
158  DenseMatrix point_matrix; ///< position within the master edge/face
159 
161  : MeshId(index, element, local), master(-1), edge_flags(0) {}
162 
163  /// Return the point matrix oriented according to the master and slave edges
164  void OrientedPointMatrix(DenseMatrix &oriented_matrix) const;
165  };
166 
167  /// Lists all edges/faces in the nonconforming mesh.
168  struct NCList
169  {
170  std::vector<MeshId> conforming;
171  std::vector<Master> masters;
172  std::vector<Slave> slaves;
173  // TODO: switch to Arrays when fixed for non-POD types
174  // TODO: make a list of unique slave matrices to save memory (+ time later)
175 
176  void Clear() { conforming.clear(); masters.clear(); slaves.clear(); }
177  bool Empty() const { return !conforming.size() && !masters.size(); }
178  long MemoryUsage() const;
179  };
180 
181  /// Return the current list of conforming and nonconforming faces.
183  {
184  if (face_list.Empty()) { BuildFaceList(); }
185  return face_list;
186  }
187 
188  /// Return the current list of conforming and nonconforming edges.
190  {
191  if (edge_list.Empty()) { BuildEdgeList(); }
192  return edge_list;
193  }
194 
195 
196  // coarse/fine transforms
197 
198  /** Remember the current layer of leaf elements before the mesh is refined.
199  Needed by GetRefinementTransforms(), must be called before Refine(). */
200  void MarkCoarseLevel();
201 
202  /** After refinement, calculate the relation of each fine element to its
203  parent coarse element. Note that Refine() or LimitNCLevel() can be called
204  multiple times between MarkCoarseLevel() and this function. */
206 
207  /** After derefinement, calculate the relations of previous fine elements
208  (some of which may no longer exist) to the current leaf elements.
209  Unlike for refinement, Derefine() may only be called once before this
210  function so there is no MarkFineLevel(). */
212 
213  /// Free all internal data created by the above three functions.
214  void ClearTransforms();
215 
216 
217  // utility
218 
219  /** Given an edge (by its vertex indices v1 and v2) return the first
220  (geometric) parent edge that exists in the Mesh or -1 if there is no such
221  parent. */
222  int GetEdgeMaster(int v1, int v2) const;
223 
224  /** Get a list of vertices (2D/3D) and edges (3D) that coincide with boundary
225  elements with the specified attributes (marked in 'bdr_attr_is_ess').
226  In 3D this function also reveals "hidden" boundary edges. In parallel it
227  helps identifying boundary vertices/edges affected by non-local boundary
228  elements. */
229  virtual void GetBoundaryClosure(const Array<int> &bdr_attr_is_ess,
230  Array<int> &bdr_vertices,
231  Array<int> &bdr_edges);
232 
233  /// Return the type of elements in the mesh.
234  int GetElementGeometry() const { return root_elements[0]->geom; }
235 
236  /// Return the distance of leaf 'i' from the root.
237  int GetElementDepth(int i) const;
238 
239  /// I/O: Print the "vertex_parents" section of the mesh file (ver. >= 1.1).
240  void PrintVertexParents(std::ostream &out) const;
241 
242  /// I/O: Print the "coarse_elements" section of the mesh file (ver. >= 1.1).
243  void PrintCoarseElements(std::ostream &out) const;
244 
245  /** I/O: Load the vertex parent hierarchy from a mesh file. NOTE: called
246  indirectly through the constructor. */
247  void LoadVertexParents(std::istream &input);
248 
249  /// I/O: Load the element refinement hierarchy from a mesh file.
250  void LoadCoarseElements(std::istream &input);
251 
252  /// I/O: Set positions of all vertices (used by mesh loader).
253  void SetVertexPositions(const Array<mfem::Vertex> &vertices);
254 
255  /// Return total number of bytes allocated.
256  long MemoryUsage() const;
257 
258  void PrintMemoryDetail() const;
259 
260 
261 protected: // interface for Mesh to be able to construct itself from NCMesh
262 
263  friend class Mesh;
264 
265  /// Return the basic Mesh arrays for the current finest level.
266  void GetMeshComponents(Array<mfem::Vertex>& vertices,
267  Array<mfem::Element*>& elements,
268  Array<mfem::Element*>& boundary) const;
269 
270  /** Get edge and face numbering from 'mesh' (i.e., set all Edge::index and
271  Face::index) after a new mesh was created from us. */
272  virtual void OnMeshUpdated(Mesh *mesh);
273 
274 
275 protected: // implementation
276 
277  int Dim, spaceDim; ///< dimensions of the elements and the vertex coordinates
278  bool Iso; ///< true if the mesh only contains isotropic refinements
279 
280  Element* CopyHierarchy(Element* elem);
281  void DeleteHierarchy(Element* elem);
282 
283 
284  // primary data
285 
286  /** We want vertices and edges to autodestruct when elements stop using
287  (i.e., referencing) them. This base class does the reference counting. */
288  struct RefCount
289  {
291 
292  RefCount() : ref_count(0) {}
293 
294  int Ref()
295  {
296  return ++ref_count;
297  }
298  int Unref()
299  {
300  int ret = --ref_count;
301  if (!ret) { delete this; }
302  return ret;
303  }
304  };
305 
306  /** A vertex in the NC mesh. Elements point to vertices indirectly through
307  their Nodes. */
308  struct Vertex : public RefCount
309  {
310  int index; ///< vertex number in the Mesh
311  double pos[3]; ///< 3D position
312 
313  Vertex() {}
314  Vertex(double x, double y, double z) : index(-1)
315  { pos[0] = x, pos[1] = y, pos[2] = z; }
316  Vertex(const Vertex& other) { std::memcpy(this, &other, sizeof(*this)); }
317  };
318 
319  /** An NC mesh edge. Edges don't do much more than just exist. */
320  struct Edge : public RefCount
321  {
322  int attribute; ///< boundary element attribute, -1 if internal edge (2D)
323  int index; ///< edge number in the Mesh
324 
325  Edge() : attribute(-1), index(-1) {}
326  Edge(const Edge &other) { std::memcpy(this, &other, sizeof(*this)); }
327 
328  bool Boundary() const { return attribute >= 0; }
329  };
330 
331  /** A Node can hold a Vertex, an Edge, or both. Elements directly point to
332  their corner nodes, but edge nodes also exist and can be accessed using
333  a hash-table given their two end-point node IDs. All nodes can be
334  accessed in this way, with the exception of top-level vertex nodes.
335  When an element is being refined, the mid-edge nodes are readily
336  available with this mechanism. The new elements "sign in" into the nodes
337  to have vertices and edges created for them or to just have their
338  reference counts increased. The parent element "signs off" its nodes,
339  which decrements the vertex and edge reference counts. Vertices and edges
340  are destroyed when their reference count drops to zero. */
341  struct Node : public Hashed2<Node>
342  {
345 
346  Node(int id) : Hashed2<Node>(id), vertex(NULL), edge(NULL) {}
347  Node(const Node &other);
348  ~Node();
349 
350  // Bump ref count on a vertex or an edge, or create them. Used when an
351  // element starts using a vertex or an edge.
352  void RefVertex();
353  void RefEdge();
354 
355  // Decrement ref on vertex or edge when an element is not using them
356  // anymore. The vertex, edge or the whole Node can autodestruct.
357  // (The hash-table pointer needs to be known then to remove the node.)
359  // Implement as a static method since we check if node == NULL.
360  static void UnrefEdge(Node *node, HashTable<Node>& nodes);
361  };
362 
363  /** Similarly to nodes, faces can be accessed by hashing their four vertex
364  node IDs. A face knows about the one or two elements that are using it.
365  A face that is not on the boundary and only has one element referencing
366  it is either a master or a slave face. */
367  struct Face : public RefCount, public Hashed4<Face>
368  {
369  int attribute; ///< boundary element attribute, -1 if internal face
370  int index; ///< face number in the Mesh
371  Element* elem[2]; ///< up to 2 elements sharing the face
372 
373  Face(int id);
374  Face(const Face& other);
375 
376  bool Boundary() const { return attribute >= 0; }
377 
378  // add or remove an element from the 'elem[2]' array
379  void RegisterElement(Element* e);
380  void ForgetElement(Element* e);
381 
382  /// Return one of elem[0] or elem[1] and make sure the other is NULL.
383  Element* GetSingleElement() const;
384 
385  // overloaded Unref without auto-destruction
386  int Unref() { return --ref_count; }
387  };
388 
389  /** This is an element in the refinement hierarchy. Each element has
390  either been refined and points to its children, or is a leaf and points
391  to its vertex nodes. */
392  struct Element
393  {
394  char geom; ///< Geometry::Type of the element
395  char ref_type; ///< bit mask of X,Y,Z refinements (bits 0,1,2 respectively)
396  char flag; ///< generic flag/marker, can be used by algorithms
397  int index; ///< element number in the Mesh, -1 if refined
398  int rank; ///< processor number (ParNCMesh)
400  union
401  {
402  Node* node[8]; ///< element corners (if ref_type == 0)
403  Element* child[8]; ///< 2-8 children (if ref_type != 0)
404  };
405  Element* parent; ///< parent element, NULL if this is a root element
406 
407  Element(int geom, int attr);
408  Element(const Element& other) { std::memcpy(this, &other, sizeof(*this)); }
409  };
410 
411  // TODO: use MemAlloc or similar to store Element, Face, Node, etc., replace
412  // most pointers with indices (ints) into the allocators to save memory;
413  // ref_count and attributes could be chars
414 
415  Array<Element*> root_elements; // coarsest mesh, initialized by constructor
416 
417  HashTable<Node> nodes; // associative container holding all Nodes
418  HashTable<Face> faces; // associative container holding all Faces
419 
420 
421  // secondary data
422 
423  /** Apart from the primary data structure, which is the element/node/face
424  hierarchy, there is secondary data that is derived from the primary
425  data and needs to be updated when the primary data changes. Update()
426  takes care of that and needs to be called after refinement and
427  derefinement. Secondary data includes: leaf_elements, vertex_nodeId,
428  face_list, edge_list, and everything in ParNCMesh. */
429  virtual void Update();
430 
431  Array<Element*> leaf_elements; // finest level, updated by UpdateLeafElements
432 
433  Array<int> vertex_nodeId; // vertex-index to node-id map, see UpdateVertices
434 
435  NCList face_list; ///< lazy-initialized list of faces, see GetFaceList
436  NCList edge_list; ///< lazy-initialized list of edges, see GetEdgeList
437 
438  Array<Face*> boundary_faces; ///< subset of all faces, set by BuildFaceList
439  Array<Node*> boundary_edges; ///< subset of all edges, set by BuildEdgeList
440 
441  Table element_vertex; ///< leaf-element to vertex table, see FindSetNeighbors
442  int num_vertices; ///< width of the table
443 
444  virtual void UpdateVertices(); ///< update Vertex::index and vertex_nodeId
445 
446  void CollectLeafElements(Element* elem, int state);
447  void UpdateLeafElements();
448 
449  virtual void AssignLeafIndices();
450 
451  virtual bool IsGhost(const Element* elem) const { return false; }
452  virtual int GetNumGhosts() const { return 0; }
453 
454 
455  // refinement/derefinement
456 
457  struct ElemRefType
458  {
460  int ref_type;
461 
463  : elem(elem), ref_type(type) {}
464  };
465 
466  Array<ElemRefType> ref_stack; ///< stack of scheduled refinements (temporary)
467 
468  Table derefinements; ///< possible derefinements, see GetDerefinementTable
469 
470  void RefineElement(Element* elem, char ref_type);
471  void DerefineElement(Element* elem);
472 
473  Element* NewHexahedron(Node* n0, Node* n1, Node* n2, Node* n3,
474  Node* n4, Node* n5, Node* n6, Node* n7,
475  int attr,
476  int fattr0, int fattr1, int fattr2,
477  int fattr3, int fattr4, int fattr5);
478 
479  Element* NewQuadrilateral(Node* n0, Node* n1, Node* n2, Node* n3,
480  int attr,
481  int eattr0, int eattr1, int eattr2, int eattr3);
482 
483  Element* NewTriangle(Node* n0, Node* n1, Node* n2,
484  int attr, int eattr0, int eattr1, int eattr2);
485 
486  Vertex* NewVertex(Node* v1, Node* v2);
487 
488  mfem::Element* NewMeshElement(int geom) const;
489 
490  Node* GetMidEdgeVertex(Node* v1, Node* v2);
492  Node* GetMidFaceVertex(Node* e1, Node* e2, Node* e3, Node* e4);
493 
494  int FaceSplitType(Node* v1, Node* v2, Node* v3, Node* v4,
495  Node* mid[4] = NULL /* optional output of mid-edge nodes*/)
496  const;
497 
498  void ForceRefinement(Node* v1, Node* v2, Node* v3, Node* v4);
499 
500  void CheckAnisoFace(Node* v1, Node* v2, Node* v3, Node* v4,
501  Node* mid12, Node* mid34, int level = 0);
502 
503  void CheckIsoFace(Node* v1, Node* v2, Node* v3, Node* v4,
504  Node* e1, Node* e2, Node* e3, Node* e4, Node* midf);
505 
506  void RefElementNodes(Element *elem);
507  void UnrefElementNodes(Element *elem);
508  Face* GetFace(Element* elem, int face_no);
509  void RegisterFaces(Element* elem, int *fattr = NULL);
510 
511  Node* PeekAltParents(Node* v1, Node* v2);
512 
513  bool NodeSetX1(Node* node, Node** n);
514  bool NodeSetX2(Node* node, Node** n);
515  bool NodeSetY1(Node* node, Node** n);
516  bool NodeSetY2(Node* node, Node** n);
517  bool NodeSetZ1(Node* node, Node** n);
518  bool NodeSetZ2(Node* node, Node** n);
519 
521 
522  // face/edge lists
523 
524  static int find_node(Element* elem, Node* node);
525  static int find_node(Element* elem, int node_id);
526  static int find_element_edge(Element* elem, int v0, int v1);
527  static int find_hex_face(int a, int b, int c);
528 
529  int ReorderFacePointMat(Node* v0, Node* v1, Node* v2, Node* v3,
530  Element* elem, DenseMatrix& mat) const;
531  struct PointMatrix;
532 
533  void TraverseFace(Node* v0, Node* v1, Node* v2, Node* v3,
534  const PointMatrix& pm, int level);
535 
536  void TraverseEdge(Node* v0, Node* v1, double t0, double t1, int flags,
537  int level);
538 
539  virtual void BuildFaceList();
540  virtual void BuildEdgeList();
541 
542  virtual void ElementSharesEdge(Element* elem, Edge* edge) {} // ParNCMesh
543  virtual void ElementSharesFace(Element* elem, Face* face) {} // ParNCMesh
544 
545 
546  // neighbors / element_vertex table
547 
548  /** Return all vertex-, edge- and face-neighbors of a set of elements.
549  The neighbors are returned as a list (neighbors != NULL), as a set
550  (neighbor_set != NULL), or both. The sizes of the set arrays must match
551  that of leaf_elements. The function is intended to be used for large
552  sets of elements and its complexity is linear in the number of leaf
553  elements in the mesh. */
554  void FindSetNeighbors(const Array<char> &elem_set,
555  Array<Element*> *neighbors, /* append */
556  Array<char> *neighbor_set = NULL);
557 
558  /** Return all vertex-, edge- and face-neighbors of a single element.
559  You can limit the number of elements being checked using 'search_set'.
560  The complexity of the function is linear in the size of the search set.*/
561  void FindNeighbors(const Element* elem,
562  Array<Element*> &neighbors, /* append */
563  const Array<Element*> *search_set = NULL);
564 
565  /** Expand a set of elements by all vertex-, edge- and face-neighbors.
566  The output array 'expanded' will contain all items from 'elements'
567  (provided they are in 'search_set') plus their neighbors. The neighbor
568  search can be limited to the optional search set. The complexity is
569  linear in the sum of the sizes of 'elements' and 'search_set'. */
570  void NeighborExpand(const Array<Element*> &elements,
571  Array<Element*> &expanded,
572  const Array<Element*> *search_set = NULL);
573 
574 
575  void CollectEdgeVertices(Node *v0, Node *v1, Array<int> &indices);
576  void CollectFaceVertices(Node* v0, Node* v1, Node* v2, Node* v3,
577  Array<int> &indices);
579 
581  {
583  }
584 
585 
586  // coarse/fine transformations
587 
588  struct Point
589  {
590  int dim;
591  double coord[3];
592 
593  Point() { dim = 0; }
594 
595  Point(double x, double y)
596  { dim = 2; coord[0] = x; coord[1] = y; }
597 
598  Point(double x, double y, double z)
599  { dim = 3; coord[0] = x; coord[1] = y; coord[2] = z; }
600 
601  Point(const Point& p0, const Point& p1)
602  {
603  dim = p0.dim;
604  for (int i = 0; i < dim; i++)
605  {
606  coord[i] = (p0.coord[i] + p1.coord[i]) * 0.5;
607  }
608  }
609 
610  Point(const Point& p0, const Point& p1, const Point& p2, const Point& p3)
611  {
612  dim = p0.dim;
613  MFEM_ASSERT(p1.dim == dim && p2.dim == dim && p3.dim == dim, "");
614  for (int i = 0; i < dim; i++)
615  {
616  coord[i] = (p0.coord[i] + p1.coord[i] + p2.coord[i] + p3.coord[i])
617  * 0.25;
618  }
619  }
620 
621  Point& operator=(const Point& src)
622  {
623  dim = src.dim;
624  for (int i = 0; i < dim; i++) { coord[i] = src.coord[i]; }
625  return *this;
626  }
627  };
628 
629  struct PointMatrix
630  {
631  int np;
633 
634  PointMatrix(const Point& p0, const Point& p1, const Point& p2)
635  { np = 3; points[0] = p0; points[1] = p1; points[2] = p2; }
636 
637  PointMatrix(const Point& p0, const Point& p1, const Point& p2, const Point& p3)
638  { np = 4; points[0] = p0; points[1] = p1; points[2] = p2; points[3] = p3; }
639 
640  PointMatrix(const Point& p0, const Point& p1, const Point& p2,
641  const Point& p3, const Point& p4, const Point& p5,
642  const Point& p6, const Point& p7)
643  {
644  np = 8;
645  points[0] = p0; points[1] = p1; points[2] = p2; points[3] = p3;
646  points[4] = p4; points[5] = p5; points[6] = p6; points[7] = p7;
647  }
648 
649  Point& operator()(int i) { return points[i]; }
650  const Point& operator()(int i) const { return points[i]; }
651 
652  void GetMatrix(DenseMatrix& point_matrix) const;
653  };
654 
658 
659  static const PointMatrix& GetGeomIdentity(int geom);
660 
661  void GetPointMatrix(int geom, const char* ref_path, DenseMatrix& matrix);
662 
663  typedef std::map<std::string, int> RefPathMap;
664 
665  void TraverseRefinements(Element* elem, int coarse_index,
666  std::string &ref_path, RefPathMap &map);
667 
668  /// storage for data returned by Get[De]RefinementTransforms()
670 
671  /// state of leaf_elements before Refine(), set by MarkCoarseLevel()
673 
674  void InitDerefTransforms();
675  void SetDerefMatrixCodes(Element* parent, Array<Element*> &coarse);
676 
677 
678  // utility
679 
680  Node* GetEdgeMaster(Node* node) const;
681 
682  static void find_face_nodes(const Face *face, Node* node[4]);
683 
684  int EdgeSplitLevel(Node* v1, Node* v2) const;
685  void FaceSplitLevel(Node* v1, Node* v2, Node* v3, Node* v4,
686  int& h_level, int& v_level) const;
687 
688  void CountSplits(Element* elem, int splits[3]) const;
689  void GetLimitRefinements(Array<Refinement> &refinements, int max_level);
690 
691  int CountElements(Element* elem) const;
692 
693  int PrintElements(std::ostream &out, Element* elem, int &coarse_id) const;
694 
695  void CountObjects(int &nelem, int &nvert, int &nedges) const;
696 
697 
698 public: // TODO: maybe make this part of mfem::Geometry?
699 
700  /** This holds in one place the constants about the geometries we support
701  (triangles, quads, cubes) */
702  struct GeomInfo
703  {
704  int nv, ne, nf, nfv; // number of: vertices, edges, faces, face vertices
705  int edges[12][2]; // edge vertices (up to 12 edges)
706  int faces[6][4]; // face vertices (up to 6 faces)
707 
709  GeomInfo() : initialized(false) {}
710  void Initialize(const mfem::Element* elem);
711  };
712 
714 
715 #ifdef MFEM_DEBUG
716 public:
717  void DebugNeighbors(Array<char> &elem_set);
718 
719  /// Print the space-filling curve formed by the sequence of leaf elements.
720  void DebugLeafOrder() const;
721 #endif
722 
723  friend class ParNCMesh/*::ElementSet*/;
724 };
725 
726 }
727 
728 #endif
NCList face_list
lazy-initialized list of faces, see GetFaceList
Definition: ncmesh.hpp:435
NCList edge_list
lazy-initialized list of edges, see GetEdgeList
Definition: ncmesh.hpp:436
NCMesh(const Mesh *mesh, std::istream *vertex_parents=NULL)
Definition: ncmesh.cpp:68
Element * NewHexahedron(Node *n0, Node *n1, Node *n2, Node *n3, Node *n4, Node *n5, Node *n6, Node *n7, int attr, int fattr0, int fattr1, int fattr2, int fattr3, int fattr4, int fattr5)
Definition: ncmesh.cpp:491
CoarseFineTransformations transforms
storage for data returned by Get[De]RefinementTransforms()
Definition: ncmesh.hpp:669
void FindNeighbors(const Element *elem, Array< Element * > &neighbors, const Array< Element * > *search_set=NULL)
Definition: ncmesh.cpp:2280
char ref_type
refinement XYZ bit mask (7 = full isotropic)
Definition: ncmesh.hpp:36
const CoarseFineTransformations & GetDerefinementTransforms()
Definition: ncmesh.cpp:2813
int index
edge number in the Mesh
Definition: ncmesh.hpp:323
char flag
generic flag/marker, can be used by algorithms
Definition: ncmesh.hpp:396
Array< Element * > coarse_elements
state of leaf_elements before Refine(), set by MarkCoarseLevel()
Definition: ncmesh.hpp:672
int PrintElements(std::ostream &out, Element *elem, int &coarse_id) const
Definition: ncmesh.cpp:3183
PointMatrix(const Point &p0, const Point &p1, const Point &p2)
Definition: ncmesh.hpp:634
Point(const Point &p0, const Point &p1)
Definition: ncmesh.hpp:601
static const int NumGeom
Definition: geom.hpp:34
Slave(int index, Element *element, int local)
Definition: ncmesh.hpp:160
void PrintVertexParents(std::ostream &out) const
I/O: Print the &quot;vertex_parents&quot; section of the mesh file (ver. &gt;= 1.1).
Definition: ncmesh.cpp:3121
void GetPointMatrix(int geom, const char *ref_path, DenseMatrix &matrix)
Definition: ncmesh.cpp:2436
Node * PeekAltParents(Node *v1, Node *v2)
Definition: ncmesh.cpp:424
virtual void LimitNCLevel(int max_nc_level)
Definition: ncmesh.cpp:3106
void PrintMemoryDetail() const
Definition: ncmesh.cpp:3360
int index
element number in the Mesh, -1 if refined
Definition: ncmesh.hpp:397
PointMatrix(const Point &p0, const Point &p1, const Point &p2, const Point &p3)
Definition: ncmesh.hpp:637
const Geometry::Type geom
virtual int GetNumGhosts() const
Definition: ncmesh.hpp:452
int GetElementGeometry() const
Return the type of elements in the mesh.
Definition: ncmesh.hpp:234
PointMatrix(const Point &p0, const Point &p1, const Point &p2, const Point &p3, const Point &p4, const Point &p5, const Point &p6, const Point &p7)
Definition: ncmesh.hpp:640
Lists all edges/faces in the nonconforming mesh.
Definition: ncmesh.hpp:168
void DebugLeafOrder() const
Print the space-filling curve formed by the sequence of leaf elements.
Definition: ncmesh.cpp:3386
int attribute
boundary element attribute, -1 if internal edge (2D)
Definition: ncmesh.hpp:322
void ClearTransforms()
Free all internal data created by the above three functions.
Definition: ncmesh.cpp:2856
bool Boundary() const
Definition: ncmesh.hpp:328
Table derefinements
possible derefinements, see GetDerefinementTable
Definition: ncmesh.hpp:468
Data type dense matrix using column-major storage.
Definition: densemat.hpp:22
void InitDerefTransforms()
Definition: ncmesh.cpp:1436
void RefElementNodes(Element *elem)
Definition: ncmesh.cpp:306
char geom
Geometry::Type of the element.
Definition: ncmesh.hpp:394
static int find_node(Element *elem, Node *node)
Definition: ncmesh.cpp:1745
void SetDerefMatrixCodes(Element *parent, Array< Element * > &coarse)
Definition: ncmesh.cpp:1451
int FaceSplitType(Node *v1, Node *v2, Node *v3, Node *v4, Node *mid[4]=NULL) const
Definition: ncmesh.cpp:1717
virtual void ElementSharesFace(Element *elem, Face *face)
Definition: ncmesh.hpp:543
void OrientedPointMatrix(DenseMatrix &oriented_matrix) const
Return the point matrix oriented according to the master and slave edges.
Definition: ncmesh.cpp:2059
static PointMatrix pm_tri_identity
Definition: ncmesh.hpp:655
int index
vertex number in the Mesh
Definition: ncmesh.hpp:310
void NeighborExpand(const Array< Element * > &elements, Array< Element * > &expanded, const Array< Element * > *search_set=NULL)
Definition: ncmesh.cpp:2342
MeshId(int index=-1, Element *element=NULL, int local=-1)
Definition: ncmesh.hpp:138
void CountObjects(int &nelem, int &nvert, int &nedges) const
Definition: ncmesh.cpp:3323
const Point & operator()(int i) const
Definition: ncmesh.hpp:650
std::vector< MeshId > conforming
Definition: ncmesh.hpp:170
Point & operator()(int i)
Definition: ncmesh.hpp:649
void GetLimitRefinements(Array< Refinement > &refinements, int max_level)
Definition: ncmesh.cpp:3076
Element * parent
parent element, NULL if this is a root element
Definition: ncmesh.hpp:405
double coord[3]
Definition: ncmesh.hpp:591
Vertex * NewVertex(Node *v1, Node *v2)
Definition: ncmesh.cpp:570
bool NodeSetY1(Node *node, Node **n)
Definition: ncmesh.cpp:626
int spaceDim
dimensions of the elements and the vertex coordinates
Definition: ncmesh.hpp:277
Array< int > vertex_nodeId
Definition: ncmesh.hpp:433
int attribute
boundary element attribute, -1 if internal face
Definition: ncmesh.hpp:369
int index
Mesh element number.
Definition: ncmesh.hpp:35
int master
master number (in Mesh numbering)
Definition: ncmesh.hpp:156
Element * element
NCMesh::Element containing this vertex/edge/face.
Definition: ncmesh.hpp:136
const NCList & GetFaceList()
Return the current list of conforming and nonconforming faces.
Definition: ncmesh.hpp:182
virtual void OnMeshUpdated(Mesh *mesh)
Definition: ncmesh.cpp:1671
A parallel extension of the NCMesh class.
Definition: pncmesh.hpp:65
Element * NewQuadrilateral(Node *n0, Node *n1, Node *n2, Node *n3, int attr, int eattr0, int eattr1, int eattr2, int eattr3)
Definition: ncmesh.cpp:519
void DebugNeighbors(Array< char > &elem_set)
Definition: ncmesh.cpp:2385
void CollectEdgeVertices(Node *v0, Node *v1, Array< int > &indices)
Definition: ncmesh.cpp:2083
virtual bool IsGhost(const Element *elem) const
Definition: ncmesh.hpp:451
bool Empty() const
Definition: ncmesh.hpp:177
Point(const Point &p0, const Point &p1, const Point &p2, const Point &p3)
Definition: ncmesh.hpp:610
Vertex(double x, double y, double z)
Definition: ncmesh.hpp:314
int num_vertices
width of the table
Definition: ncmesh.hpp:442
Refinement(int index, int type=7)
Definition: ncmesh.hpp:38
int index
face number in the Mesh
Definition: ncmesh.hpp:370
const Table & GetDerefinementTable()
Definition: ncmesh.cpp:1356
Table element_vertex
leaf-element to vertex table, see FindSetNeighbors
Definition: ncmesh.hpp:441
DenseTensor point_matrices
matrices for IsoparametricTransformation
Definition: ncmesh.hpp:53
int local
local number within &#39;element&#39;
Definition: ncmesh.hpp:135
Element * elem[2]
up to 2 elements sharing the face
Definition: ncmesh.hpp:371
static void UnrefEdge(Node *node, HashTable< Node > &nodes)
Definition: ncmesh.cpp:284
void GetMatrix(DenseMatrix &point_matrix) const
Definition: ncmesh.cpp:2400
void CheckAnisoFace(Node *v1, Node *v2, Node *v3, Node *v4, Node *mid12, Node *mid34, int level=0)
Definition: ncmesh.cpp:673
virtual void Derefine(const Array< int > &derefs)
Definition: ncmesh.cpp:1400
void RegisterFaces(Element *elem, int *fattr=NULL)
Definition: ncmesh.cpp:399
std::vector< Master > masters
Definition: ncmesh.hpp:171
virtual void UpdateVertices()
update Vertex::index and vertex_nodeId
Definition: ncmesh.cpp:1469
void RegisterElement(Element *e)
Definition: ncmesh.cpp:377
int ReorderFacePointMat(Node *v0, Node *v1, Node *v2, Node *v3, Element *elem, DenseMatrix &mat) const
Definition: ncmesh.cpp:1795
Element * CopyHierarchy(Element *elem)
Definition: ncmesh.cpp:198
void RefineElement(Element *elem, char ref_type)
Definition: ncmesh.cpp:756
void FaceSplitLevel(Node *v1, Node *v2, Node *v3, Node *v4, int &h_level, int &v_level) const
Definition: ncmesh.cpp:2996
Element(int geom, int attr)
Definition: ncmesh.cpp:478
Array< Embedding > embeddings
fine element positions in their parents
Definition: ncmesh.hpp:54
virtual void BuildEdgeList()
Definition: ncmesh.cpp:1987
const CoarseFineTransformations & GetRefinementTransforms()
Definition: ncmesh.cpp:2776
void LoadCoarseElements(std::istream &input)
I/O: Load the element refinement hierarchy from a mesh file.
Definition: ncmesh.cpp:3230
Identifies a vertex/edge/face in both Mesh and NCMesh.
Definition: ncmesh.hpp:132
void MarkCoarseLevel()
Definition: ncmesh.cpp:2733
virtual void ElementSharesEdge(Element *elem, Edge *edge)
Definition: ncmesh.hpp:542
int Size() const
Returns the number of TYPE I elements.
Definition: table.hpp:86
A class for non-conforming AMR on higher-order hexahedral, quadrilateral or triangular meshes...
Definition: ncmesh.hpp:80
bool NodeSetX1(Node *node, Node **n)
Definition: ncmesh.cpp:620
virtual ~NCMesh()
Definition: ncmesh.cpp:254
virtual void GetBoundaryClosure(const Array< int > &bdr_attr_is_ess, Array< int > &bdr_vertices, Array< int > &bdr_edges)
Definition: ncmesh.cpp:2933
Embedding(int elem, int matrix=0)
Definition: ncmesh.hpp:47
static GeomInfo GI[Geometry::NumGeom]
Definition: ncmesh.hpp:713
void DeleteHierarchy(Element *elem)
Definition: ncmesh.cpp:224
int slaves_end
slave faces
Definition: ncmesh.hpp:146
Vertex * vertex
Definition: ncmesh.hpp:343
bool Iso
true if the mesh only contains isotropic refinements
Definition: ncmesh.hpp:278
void TraverseEdge(Node *v0, Node *v1, double t0, double t1, int flags, int level)
Definition: ncmesh.cpp:1951
Point(double x, double y, double z)
Definition: ncmesh.hpp:598
void DerefineElement(Element *elem)
Definition: ncmesh.cpp:1211
std::map< std::string, int > RefPathMap
Definition: ncmesh.hpp:663
Array< Node * > boundary_edges
subset of all edges, set by BuildEdgeList
Definition: ncmesh.hpp:439
void FindSetNeighbors(const Array< char > &elem_set, Array< Element * > *neighbors, Array< char > *neighbor_set=NULL)
Definition: ncmesh.cpp:2196
int SpaceDimension() const
Definition: ncmesh.hpp:98
std::vector< Slave > slaves
Definition: ncmesh.hpp:172
virtual void BuildFaceList()
Definition: ncmesh.cpp:1876
void ForceRefinement(Node *v1, Node *v2, Node *v3, Node *v4)
Definition: ncmesh.cpp:639
void SetVertexPositions(const Array< mfem::Vertex > &vertices)
I/O: Set positions of all vertices (used by mesh loader).
Definition: ncmesh.cpp:3169
int edge_flags
edge orientation flags
Definition: ncmesh.hpp:157
bool Boundary() const
Definition: ncmesh.hpp:376
double pos[3]
3D position
Definition: ncmesh.hpp:311
static const PointMatrix & GetGeomIdentity(int geom)
Definition: ncmesh.cpp:2423
Element * child[8]
2-8 children (if ref_type != 0)
Definition: ncmesh.hpp:403
Face * GetFace(Element *elem, int face_no)
Definition: ncmesh.cpp:391
Array< Element * > leaf_elements
Definition: ncmesh.hpp:431
mfem::Element * NewMeshElement(int geom) const
Definition: ncmesh.cpp:1583
void UpdateLeafElements()
Definition: ncmesh.cpp:1560
Vertex(const Vertex &other)
Definition: ncmesh.hpp:316
bool NodeSetZ1(Node *node, Node **n)
Definition: ncmesh.cpp:632
Node * GetMidEdgeVertexSimple(Node *v1, Node *v2)
Definition: ncmesh.cpp:593
long MemoryUsage() const
Definition: ncmesh.cpp:3308
void BuildElementToVertexTable()
Definition: ncmesh.cpp:2119
HashTable< Node > nodes
Definition: ncmesh.hpp:417
Edge(const Edge &other)
Definition: ncmesh.hpp:326
void UnrefElementNodes(Element *elem)
Definition: ncmesh.cpp:335
Master(int index, Element *element, int local, int sb, int se)
Definition: ncmesh.hpp:148
static PointMatrix pm_quad_identity
Definition: ncmesh.hpp:656
void CheckIsoFace(Node *v1, Node *v2, Node *v3, Node *v4, Node *e1, Node *e2, Node *e3, Node *e4, Node *midf)
Definition: ncmesh.cpp:739
Node * GetMidFaceVertex(Node *e1, Node *e2, Node *e3, Node *e4)
Definition: ncmesh.cpp:602
Element(const Element &other)
Definition: ncmesh.hpp:408
void CollectFaceVertices(Node *v0, Node *v1, Node *v2, Node *v3, Array< int > &indices)
Definition: ncmesh.cpp:2095
bool NodeSetZ2(Node *node, Node **n)
Definition: ncmesh.cpp:635
void Initialize(const mfem::Element *elem)
Definition: ncmesh.cpp:29
bool NodeSetX2(Node *node, Node **n)
Definition: ncmesh.cpp:623
void GetMeshComponents(Array< mfem::Vertex > &vertices, Array< mfem::Element * > &elements, Array< mfem::Element * > &boundary) const
Return the basic Mesh arrays for the current finest level.
Definition: ncmesh.cpp:1595
Node * node[8]
element corners (if ref_type == 0)
Definition: ncmesh.hpp:402
void CollectLeafElements(Element *elem, int state)
Definition: ncmesh.cpp:1520
Element * NewTriangle(Node *n0, Node *n1, Node *n2, int attr, int eattr0, int eattr1, int eattr2)
Definition: ncmesh.cpp:546
int parent
element index in the coarse mesh
Definition: ncmesh.hpp:44
Point(double x, double y)
Definition: ncmesh.hpp:595
virtual void AssignLeafIndices()
Definition: ncmesh.cpp:1574
static PointMatrix pm_hex_identity
Definition: ncmesh.hpp:657
static int find_hex_face(int a, int b, int c)
Definition: ncmesh.cpp:1779
int Dimension() const
Definition: ncmesh.hpp:97
virtual void CheckDerefinementNCLevel(const Table &deref_table, Array< int > &level_ok, int max_nc_level)
Definition: ncmesh.cpp:1371
Array< ElemRefType > ref_stack
stack of scheduled refinements (temporary)
Definition: ncmesh.hpp:466
static void find_face_nodes(const Face *face, Node *node[4])
Definition: ncmesh.cpp:2913
Array< Element * > root_elements
Definition: ncmesh.hpp:415
virtual void Update()
Definition: ncmesh.cpp:187
long MemoryUsage() const
Return total number of bytes allocated.
Definition: ncmesh.cpp:3337
Node * GetMidEdgeVertex(Node *v1, Node *v2)
Definition: ncmesh.cpp:584
int EdgeSplitLevel(Node *v1, Node *v2) const
Definition: ncmesh.cpp:2989
Element * GetSingleElement() const
Return one of elem[0] or elem[1] and make sure the other is NULL.
Definition: ncmesh.cpp:410
void PrintCoarseElements(std::ostream &out) const
I/O: Print the &quot;coarse_elements&quot; section of the mesh file (ver. &gt;= 1.1).
Definition: ncmesh.cpp:3212
static int find_element_edge(Element *elem, int v0, int v1)
Definition: ncmesh.cpp:1763
Defines the coarse-fine transformations of all fine elements.
Definition: ncmesh.hpp:51
const NCList & GetEdgeList()
Return the current list of conforming and nonconforming edges.
Definition: ncmesh.hpp:189
void TraverseFace(Node *v0, Node *v1, Node *v2, Node *v3, const PointMatrix &pm, int level)
Definition: ncmesh.cpp:1827
void UpdateElementToVertexTable()
Definition: ncmesh.hpp:580
int GetElementDepth(int i) const
Return the distance of leaf &#39;i&#39; from the root.
Definition: ncmesh.cpp:2901
void CountSplits(Element *elem, int splits[3]) const
Definition: ncmesh.cpp:3029
void ForgetElement(Element *e)
Definition: ncmesh.cpp:384
char ref_type
bit mask of X,Y,Z refinements (bits 0,1,2 respectively)
Definition: ncmesh.hpp:395
ElemRefType(Element *elem, int type)
Definition: ncmesh.hpp:462
bool NodeSetY2(Node *node, Node **n)
Definition: ncmesh.cpp:629
int index
Mesh number.
Definition: ncmesh.hpp:134
void LoadVertexParents(std::istream &input)
Definition: ncmesh.cpp:3149
Rank 3 tensor (array of matrices)
Definition: densemat.hpp:593
int CountElements(Element *elem) const
Definition: ncmesh.cpp:3295
Abstract data type element.
Definition: element.hpp:27
Point & operator=(const Point &src)
Definition: ncmesh.hpp:621
Array< Face * > boundary_faces
subset of all faces, set by BuildFaceList
Definition: ncmesh.hpp:438
void TraverseRefinements(Element *elem, int coarse_index, std::string &ref_path, RefPathMap &map)
Definition: ncmesh.cpp:2747
int rank
processor number (ParNCMesh)
Definition: ncmesh.hpp:398
void CollectDerefinements(Element *elem, Array< Connection > &list)
Definition: ncmesh.cpp:1320
DenseMatrix point_matrix
position within the master edge/face
Definition: ncmesh.hpp:158
HashTable< Face > faces
Definition: ncmesh.hpp:418
Defines the position of a fine element within a coarse element.
Definition: ncmesh.hpp:42
virtual void Refine(const Array< Refinement > &refinements)
Definition: ncmesh.cpp:1169
int matrix
index into CoarseFineTransformations::point_matrices
Definition: ncmesh.hpp:45
int GetEdgeMaster(int v1, int v2) const
Definition: ncmesh.cpp:2892
void UnrefVertex(HashTable< Node > &nodes)
Definition: ncmesh.cpp:277