1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2020 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 
18 
19 
20 #ifndef LIBMESH_NODE_H
21 #define LIBMESH_NODE_H
22 
23 // Local includes
24 #include "libmesh/point.h"
25 #include "libmesh/dof_object.h"
26 #include "libmesh/reference_counted_object.h"
27 #include "libmesh/auto_ptr.h" // libmesh_make_unique
28 
29 // C++ includes
30 #include <iostream>
31 #include <vector>
32 
33 namespace libMesh
34 {
35 
36 // forward declarations
37 class Node;
38 class MeshBase;
39 class MeshRefinement;
40 
41 /**
42  * A \p Node is like a \p Point, but with more information.  A \p Node
43  * is located in space and is associated with some \p (x,y,z)
44  * coordinates.  Additionally, a \p Node may be enumerated with a
45  * global \p id.  Finally, a \p Node may have an arbitrary number of
46  * degrees of freedom associated with it.
47  *
48  * \author Benjamin S. Kirk
49  * \date 2003
50  * \brief A geometric point in (x,y,z) space associated with a DOF.
51  */
52 class Node : public Point,
53              public DofObject,
54              public ReferenceCountedObject<Node>
55 {
56 
57 public:
58 
59   /**
60    * Constructor.  By default sets all entries to 0.  Gives the point 0 in
61    * \p LIBMESH_DIM dimensions with an \p id of \p Node::invalid_id.
62    */
63   explicit
64   Node  (const Real x=0,
65          const Real y=0,
66          const Real z=0,
67          const dof_id_type id = invalid_id);
68 
69   /**
70    * "Copy"-constructor: deliberately slices the source Node and only
71    * copies its' Point information, since copying anything else would
72    * likely be a bug.
73    *
74    * \deprecated - the constructor from Point is what we really want.
75    */
76 #ifdef LIBMESH_ENABLE_DEPRECATED
77   Node (const Node & n);
78 #else
79   Node (const Node & n) = delete;
80 #endif
81 
82   /**
83    * Copy-constructor from a \p Point.  Optionally assigned the \p id.
84    */
85   explicit Node (const Point & p,
86                  const dof_id_type id = invalid_id);
87 
88   /**
89    * Disambiguate constructing from non-Real scalars
90    */
91   template <typename T,
92             typename = typename
93               boostcopy::enable_if_c<ScalarTraits<T>::value,void>::type>
Node(const T x)94   explicit Node (const T x) :
95     Point (x,0,0)
96   { this->set_id() = invalid_id; }
97 
98   /**
99    * Destructor.
100    */
101   ~Node ();
102 
103   /**
104    * Assign to a node from a point.
105    */
106   Node & operator= (const Point & p);
107 
108   /**
109    * \returns A \p Node copied from \p n and wrapped in a smart pointer.
110    *
111    * \deprecated - anyone copying a Node would almost certainly be
112    * better off copying the much cheaper Point or taking a reference
113    * to the Node.
114    */
115 #ifdef LIBMESH_ENABLE_DEPRECATED
116   static std::unique_ptr<Node> build (const Node & n);
117 #endif
118 
119   /**
120    * \returns A \p Node copied from \p p with id == \p id and wrapped in a smart pointer.
121    */
122   static std::unique_ptr<Node> build (const Point & p,
123                                       const dof_id_type id);
124 
125   /**
126    * \returns A \p Node created from the specified (x,y,z) positions
127    * with id == \p id and wrapped in a smart pointer.
128    */
129   static std::unique_ptr<Node> build (const Real x,
130                                       const Real y,
131                                       const Real z,
132                                       const dof_id_type id);
133 
134   /**
135    * \returns \p true if the node is active.  An active node is
136    * defined as one for which \p id() is not \p Node::invalid_id.
137    * Inactive nodes are nodes that are in the mesh but are not
138    * connected to any elements.
139    */
140   bool active () const;
141 
142 
143   /**
144    * \returns \p true if this node equals rhs, false otherwise.
145    */
146   bool operator ==(const Node & rhs) const;
147 
148   /**
149    * Prints relevant information about the node.
150    */
151   void print_info (std::ostream & os=libMesh::out) const;
152 
153   /**
154    * Prints relevant information about the node to a string.
155    */
156   std::string get_info () const;
157 
158 #ifdef LIBMESH_HAVE_MPI
packed_size()159   unsigned int packed_size() const
160   {
161     const unsigned int header_size = 2;
162 
163     // use "(a+b-1)/b" trick to get a/b to round up
164     static const unsigned int idtypes_per_Real =
165       (sizeof(Real) + sizeof(largest_id_type) - 1) / sizeof(largest_id_type);
166 
167     return header_size + LIBMESH_DIM*idtypes_per_Real +
168       this->packed_indexing_size();
169   }
170 
171 #endif // #ifdef LIBMESH_HAVE_MPI
172 
173   /**
174    * \returns The number of nodes connected with this node.
175    * Currently, this value is invalid (zero) except for
176    * subdivision meshes.
177    */
valence()178   unsigned int valence() const
179   {
180 #ifdef LIBMESH_ENABLE_NODE_VALENCE
181     return _valence;
182 #else
183     libmesh_not_implemented();
184     return libMesh::invalid_uint;
185 #endif
186   }
187 
188   /**
189    * Sets the number of nodes connected with this node.
190    */
191   void set_valence(unsigned int val);
192 
193   /**
194    * Return which of pid1 and pid2 would be preferred by the current
195    * load-balancing heuristic applied to this node.
196    */
197   processor_id_type choose_processor_id(processor_id_type pid1, processor_id_type pid2) const;
198 
199 private:
200 
201   /**
202    * This class need access to the node key information,
203    * but no one else should be able to mess with it.
204    */
205   friend class MeshRefinement;
206   friend class Elem;
207 
208 #ifdef LIBMESH_ENABLE_NODE_VALENCE
209   /**
210    * Type used to store node valence.
211    */
212   typedef unsigned char valence_idx_t;
213 
214   /**
215    * The number of nodes connected with this node.
216    * Currently, this value is invalid (zero) except for
217    * subdivision meshes.
218    */
219   valence_idx_t _valence;
220 #endif
221 };
222 
223 
224 
225 // ------------------------------------------------------------
226 // Global Node functions
227 
228 inline
229 std::ostream & operator << (std::ostream & os, const Node & n)
230 {
231   n.print_info(os);
232   return os;
233 }
234 
235 
236 
237 //------------------------------------------------------
238 // Inline functions
239 inline
Node(const Real x,const Real y,const Real z,const dof_id_type dofid)240 Node::Node (const Real x,
241             const Real y,
242             const Real z,
243             const dof_id_type dofid) :
244   Point(x,y,z)
245 #ifdef LIBMESH_ENABLE_NODE_VALENCE
246   ,
247   _valence(0)
248 #endif
249 {
250   this->set_id() = dofid;
251 }
252 
253 
254 #ifdef LIBMESH_ENABLE_DEPRECATED
255 inline
Node(const Node & n)256 Node::Node (const Node & n) :
257   Point(n),
258   DofObject(), // Deliberately slicing!
259   ReferenceCountedObject<Node>()
260 #ifdef LIBMESH_ENABLE_NODE_VALENCE
261   ,
262   _valence(0)
263 #endif
264 {
265   libmesh_deprecated(); // Cast to Point first!
266 }
267 #endif // LIBMESH_ENABLE_DEPRECATED
268 
269 
270 
271 inline
Node(const Point & p,const dof_id_type dofid)272 Node::Node (const Point & p,
273             const dof_id_type dofid) :
274   Point(p)
275 #ifdef LIBMESH_ENABLE_NODE_VALENCE
276   ,
277   _valence(0)
278 #endif
279 {
280   // optionally assign the id.  We have
281   // to do it like this otherwise
282   // Node n = Point p would erase
283   // the id!
284   if (dofid != invalid_id)
285     this->set_id() = dofid;
286 }
287 
288 
289 
290 inline
~Node()291 Node::~Node ()
292 {
293 }
294 
295 
296 
297 inline
298 Node & Node::operator= (const Point & p)
299 {
300   (*this)(0) = p(0);
301 #if LIBMESH_DIM > 1
302   (*this)(1) = p(1);
303 #endif
304 #if LIBMESH_DIM > 2
305   (*this)(2) = p(2);
306 #endif
307 
308   return *this;
309 }
310 
311 
312 
313 #ifdef LIBMESH_ENABLE_DEPRECATED
314 inline
build(const Node & n)315 std::unique_ptr<Node> Node::build(const Node & n)
316 {
317   libmesh_deprecated();
318   return libmesh_make_unique<Node>(n);
319 }
320 #endif
321 
322 
323 
324 inline
build(const Point & p,const dof_id_type id)325 std::unique_ptr<Node> Node::build(const Point & p,
326                                   const dof_id_type id)
327 {
328   return libmesh_make_unique<Node>(p,id);
329 }
330 
331 
332 
333 inline
build(const Real x,const Real y,const Real z,const dof_id_type id)334 std::unique_ptr<Node> Node::build(const Real x,
335                                   const Real y,
336                                   const Real z,
337                                   const dof_id_type id)
338 {
339   return libmesh_make_unique<Node>(x,y,z,id);
340 }
341 
342 
343 
344 inline
active()345 bool Node::active () const
346 {
347   return (this->id() != Node::invalid_id);
348 }
349 
350 
351 
352 #ifdef LIBMESH_ENABLE_NODE_VALENCE
353 
354 inline
set_valence(unsigned int val)355 void Node::set_valence (unsigned int val)
356 {
357   _valence = cast_int<valence_idx_t>(val);
358 }
359 
360 #else
361 
362 inline
set_valence(unsigned int)363 void Node::set_valence (unsigned int)
364 {
365   libmesh_not_implemented();
366 }
367 
368 #endif // #ifdef LIBMESH_ENABLE_NODE_VALENCE
369 
370 } // namespace libMesh
371 
372 
373 #endif // LIBMESH_NODE_H
374