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