@@ -237,13 +237,25 @@ class Elem : public ReferenceCountedObject<Elem>,
237237 */
238238 static const subdomain_id_type invalid_subdomain_id;
239239
240+ /* *
241+ * \returns true iff this element type can vary in topology (e.g.
242+ * have different numbers of sides and/or nodes) at runtime. For
243+ * such general polygons or polyhedra, APIs which assume a fixed
244+ * topology are not safe to use.
245+ */
246+ virtual bool runtime_topology () const { return false ; }
247+
240248 /* *
241249 * \returns A pointer to the "reference element" associated
242250 * with this element. The reference element is the image of this
243251 * element in reference parametric space. Importantly, it is *not*
244252 * an actual element in the mesh, but rather a Singleton-type
245253 * object, so for example all \p Quad4 elements share the same
246254 * \p reference_elem().
255+ *
256+ * If the element is of a type that can admit multiple topologies,
257+ * such as a Polygon subtype, then there is no reference element;
258+ * for such types this method should not be used.
247259 */
248260 const Elem * reference_elem () const ;
249261
@@ -608,6 +620,10 @@ class Elem : public ReferenceCountedObject<Elem>,
608620 /* *
609621 * This array maps the integer representation of the \p ElemType enum
610622 * to the number of nodes in the element.
623+ *
624+ * This is only usable for simple types for which the node number
625+ * is fixed; for more general types like Polygon subclasses an actual
626+ * instantiated Elem must be queried.
611627 */
612628 static const unsigned int type_to_n_nodes_map[INVALID_ELEM];
613629
@@ -639,6 +655,10 @@ class Elem : public ReferenceCountedObject<Elem>,
639655 /* *
640656 * This array maps the integer representation of the \p ElemType enum
641657 * to the number of sides on the element.
658+ *
659+ * This is only usable for simple types for which the node number
660+ * is fixed; for more general types like Polygon subclasses an actual
661+ * instantiated Elem must be queried.
642662 */
643663 static const unsigned int type_to_n_sides_map[INVALID_ELEM];
644664
@@ -693,6 +713,10 @@ class Elem : public ReferenceCountedObject<Elem>,
693713 /* *
694714 * This array maps the integer representation of the \p ElemType enum
695715 * to the number of edges on the element.
716+ *
717+ * This is only usable for simple types for which the node number
718+ * is fixed; for more general types like Polygon subclasses an actual
719+ * instantiated Elem must be queried.
696720 */
697721 static const unsigned int type_to_n_edges_map[INVALID_ELEM];
698722
@@ -1057,8 +1081,8 @@ class Elem : public ReferenceCountedObject<Elem>,
10571081 { libmesh_not_implemented (); return std::make_pair (0 .,0 .); }
10581082
10591083 /* *
1060- * \returns \p true if the point p is contained in this element,
1061- * false otherwise.
1084+ * \returns \p true if the physical point p is contained in this
1085+ * element, false otherwise.
10621086 *
10631087 * For linear elements, performs an initial tight bounding box check
10641088 * (as an optimization step) and (if that passes) then uses the
@@ -1844,14 +1868,12 @@ class Elem : public ReferenceCountedObject<Elem>,
18441868
18451869#endif
18461870
1847-
1848-
1849-
18501871 /* *
18511872 * \returns An Elem of type \p type wrapped in a smart pointer.
18521873 */
18531874 static std::unique_ptr<Elem> build (const ElemType type,
18541875 Elem * p=nullptr );
1876+
18551877 /* *
18561878 * Calls the build() method above with a nullptr parent, and
18571879 * additionally sets the newly-created Elem's id. This can be useful
@@ -1860,6 +1882,20 @@ class Elem : public ReferenceCountedObject<Elem>,
18601882 static std::unique_ptr<Elem> build_with_id (const ElemType type,
18611883 dof_id_type id);
18621884
1885+ /* *
1886+ * \returns An Elem of the same type as \p this, wrapped in a smart
1887+ * pointer.
1888+ *
1889+ * This is not a complete clone() method (since e.g. it does not set
1890+ * node pointers; the standard use case reassigns node pointers from
1891+ * a different mesh), but it is necessary to use this instead of
1892+ * build() for runtime-polymorphic elements like Polygon subtypes
1893+ * whose "type" depends on more than their type(), and it is useful
1894+ * to use this for elements whose id, unique_id, extra integers,
1895+ * etc. should be preserved in the near-clone.
1896+ */
1897+ virtual std::unique_ptr<Elem> disconnected_clone () const ;
1898+
18631899 /* *
18641900 * Returns the number of independent permutations of element nodes -
18651901 * e.g. a cube can be reoriented to put side 0 where side N is (for
@@ -2310,7 +2346,8 @@ Elem::Elem(const unsigned int nn,
23102346 // If this ever legitimately fails we need to increase max_n_nodes
23112347 libmesh_assert_less_equal (nn, max_n_nodes);
23122348
2313- // Initialize the nodes data structure
2349+ // Initialize the nodes data structure if we're given a pointer to
2350+ // memory for it.
23142351 if (_nodes)
23152352 {
23162353 for (unsigned int n=0 ; n<nn; n++)
@@ -2320,27 +2357,31 @@ Elem::Elem(const unsigned int nn,
23202357 // Initialize the neighbors/parent data structure
23212358 // _elemlinks = new Elem *[ns+1];
23222359
2323- // We now require that we get allocated data from a subclass
2324- libmesh_assert (_elemlinks);
2325-
2326- _elemlinks[0 ] = p;
2360+ // Initialize the elements data structure if we're given a pointer
2361+ // to memory for it. If we *weren't* given memory for it, e.g.
2362+ // because a subclass like an arbitrary Polygon needs to
2363+ // heap-allocate this memory, then that subclass will have to handle
2364+ // this initialization too.
2365+ if (_elemlinks)
2366+ {
2367+ _elemlinks[0 ] = p;
23272368
2328- for (unsigned int n=1 ; n<ns+1 ; n++)
2329- _elemlinks[n] = nullptr ;
2369+ for (unsigned int n=1 ; n<ns+1 ; n++)
2370+ _elemlinks[n] = nullptr ;
23302371
2331- // Optionally initialize data from the parent
2332- if (this ->parent () != nullptr )
2333- {
2334- this ->subdomain_id () = this ->parent ()->subdomain_id ();
2335- this ->processor_id () = this ->parent ()->processor_id ();
2336- _map_type = this ->parent ()->_map_type ;
2337- _map_data = this ->parent ()->_map_data ;
2338- }
2372+ // Optionally initialize data from the parent
2373+ if (this ->parent ())
2374+ {
2375+ this ->subdomain_id () = this ->parent ()->subdomain_id ();
2376+ this ->processor_id () = this ->parent ()->processor_id ();
2377+ _map_type = this ->parent ()->_map_type ;
2378+ _map_data = this ->parent ()->_map_data ;
23392379
23402380#ifdef LIBMESH_ENABLE_AMR
2341- if (this ->parent ())
2342- this ->set_p_level (this ->parent ()->p_level ());
2381+ this ->set_p_level (this ->parent ()->p_level ());
23432382#endif
2383+ }
2384+ }
23442385}
23452386
23462387
0 commit comments