libMesh
reference_elem.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2013 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 // Local includes
21 #include "libmesh/node.h"
22 #include "libmesh/elem.h"
23 #include "libmesh/reference_elem.h"
24 #include "libmesh/libmesh_singleton.h"
25 #include "libmesh/threads.h"
26 #include "libmesh/string_to_enum.h"
27 
28 // C++ includes
29 #include <map>
30 #include <sstream>
31 
32 
33 
34 //-----------------------------------------------
35 // anonymous namespace for implementation details
36 namespace
37 {
38 using namespace libMesh;
39 
40 namespace ElemDataStrings
41 {
42 // GCC 5.2.0 warns about overlength strings in the auto-generated
43 // reference_elem.data file.
44 #pragma GCC diagnostic ignored "-Woverlength-strings"
45 #include "reference_elem.data"
46 #pragma GCC diagnostic warning "-Woverlength-strings"
47 }
48 
49 typedef Threads::spin_mutex InitMutex;
50 
51 // Mutex for thread safety.
52 InitMutex init_mtx;
53 
54 // map from ElemType to reference element file system object name
55 typedef std::map<ElemType, const char *> FileMapType;
56 FileMapType ref_elem_file;
57 Elem * ref_elem_map[INVALID_ELEM];
58 
59 
60 
61 class SingletonCache : public libMesh::Singleton
62 {
63 public:
64  ~SingletonCache()
65  {
66  for (std::size_t e=0; e<elem_list.size(); e++)
67  {
68  delete elem_list[e];
69  elem_list[e] = libmesh_nullptr;
70  }
71 
72  elem_list.clear();
73 
74  for (std::size_t n=0; n<node_list.size(); n++)
75  {
76  delete node_list[n];
77  node_list[n] = libmesh_nullptr;
78  }
79 
80  node_list.clear();
81  }
82 
83  std::vector<Node *> node_list;
84  std::vector<Elem *> elem_list;
85 };
86 
87 // singleton object, dynamically created and then
88 // removed at program exit
89 SingletonCache * singleton_cache = libmesh_nullptr;
90 
91 
92 
93 void read_ref_elem (const ElemType type_in,
94  std::istream & in)
95 {
96  libmesh_assert (singleton_cache != libmesh_nullptr);
97 
98  std::string dummy;
99  unsigned int n_elem, n_nodes, elem_type_read, nn;
100  double x, y, z;
101 
102  in >> dummy;
103  in >> n_elem; std::getline (in, dummy); libmesh_assert_equal_to (n_elem, 1);
104  in >> n_nodes; std::getline (in, dummy);
105  in >> dummy; std::getline (in, dummy);
106  in >> dummy; std::getline (in, dummy);
107  in >> dummy; std::getline (in, dummy);
108  in >> dummy; std::getline (in, dummy);
109  in >> n_elem; std::getline (in, dummy); libmesh_assert_equal_to (n_elem, 1);
110 
111  in >> elem_type_read;
112 
113  libmesh_assert_less (elem_type_read, INVALID_ELEM);
114  libmesh_assert_equal_to (elem_type_read, static_cast<unsigned int>(type_in));
115  libmesh_assert_equal_to (n_nodes, Elem::type_to_n_nodes_map[elem_type_read]);
116 
117  // Construct elem of appropriate type
118  UniquePtr<Elem> uelem = Elem::build(type_in);
119 
120  // We are expecting an identity map, so assert it!
121  for (unsigned int n=0; n<n_nodes; n++)
122  {
123  in >> nn;
124  libmesh_assert_equal_to (n,nn);
125  }
126 
127  for (unsigned int n=0; n<n_nodes; n++)
128  {
129  in >> x >> y >> z;
130 
131  Node * node = new Node(x,y,z,n);
132  singleton_cache->node_list.push_back(node);
133 
134  uelem->set_node(n) = node;
135  }
136 
137  // it is entirely possible we ran out of file or encountered
138  // another error. If so, throw an error.
139  if (!in)
140  libmesh_error_msg("ERROR while creating element singleton!");
141 
142  // Release the pointer into the care of the singleton_cache
143  else
144  singleton_cache->elem_list.push_back (uelem.release());
145 
146  // Also store it in the array.
147  ref_elem_map[type_in] = singleton_cache->elem_list.back();
148 }
149 
150 
151 
152 void init_ref_elem_table()
153 {
154  // outside mutex - if this pointer is set, we can trust it.
155  if (singleton_cache != libmesh_nullptr)
156  return;
157 
158  // playing with fire here - lock before touching shared
159  // data structures
160  InitMutex::scoped_lock lock(init_mtx);
161 
162  // inside mutex - pointer may have changed while waiting
163  // for the lock to acquire, check it again.
164  if (singleton_cache != libmesh_nullptr)
165  return;
166 
167  // OK, if we get here we have the lock and we are not
168  // initialized. populate singleton.
169  singleton_cache = new SingletonCache;
170 
171  // initialize the reference file table
172  {
173  ref_elem_file.clear();
174 
175  // 1D elements
176  ref_elem_file[EDGE2] = ElemDataStrings::one_edge;
177  ref_elem_file[EDGE3] = ElemDataStrings::one_edge3;
178  ref_elem_file[EDGE4] = ElemDataStrings::one_edge4;
179 
180  // 2D elements
181  ref_elem_file[TRI3] = ElemDataStrings::one_tri;
182  ref_elem_file[TRI6] = ElemDataStrings::one_tri6;
183 
184  ref_elem_file[QUAD4] = ElemDataStrings::one_quad;
185  ref_elem_file[QUAD8] = ElemDataStrings::one_quad8;
186  ref_elem_file[QUAD9] = ElemDataStrings::one_quad9;
187 
188  // 3D elements
189  ref_elem_file[HEX8] = ElemDataStrings::one_hex;
190  ref_elem_file[HEX20] = ElemDataStrings::one_hex20;
191  ref_elem_file[HEX27] = ElemDataStrings::one_hex27;
192 
193  ref_elem_file[TET4] = ElemDataStrings::one_tet;
194  ref_elem_file[TET10] = ElemDataStrings::one_tet10;
195 
196  ref_elem_file[PRISM6] = ElemDataStrings::one_prism;
197  ref_elem_file[PRISM15] = ElemDataStrings::one_prism15;
198  ref_elem_file[PRISM18] = ElemDataStrings::one_prism18;
199 
200  ref_elem_file[PYRAMID5] = ElemDataStrings::one_pyramid;
201  ref_elem_file[PYRAMID13] = ElemDataStrings::one_pyramid13;
202  ref_elem_file[PYRAMID14] = ElemDataStrings::one_pyramid14;
203  }
204 
205  // Read'em
206  for (FileMapType::const_iterator it=ref_elem_file.begin();
207  it != ref_elem_file.end(); ++it)
208  {
209  std::istringstream stream(it->second);
210 
211  read_ref_elem(it->first,
212  stream);
213  }
214 }
215 
216 
217 // no reason to do this at startup -
218 // data structures will get initialized *if*
219 // ReferenceElem::get() is ever called.
220 // // Class to setup singleton data
221 // class ReferenceElemSetup : public Singleton::Setup
222 // {
223 // void setup ()
224 // {
225 // init_ref_elem_table();
226 // }
227 // } reference_elem_setup;
228 
229 } // anonymous namespace
230 
231 
232 
233 //----------------------------------------------------------------------------
234 // external API Implementation
235 namespace libMesh
236 {
237 namespace ReferenceElem
238 {
239 const Elem & get (const ElemType type_in)
240 {
241  ElemType base_type = type_in;
242 
243  // For shell elements, use non shell type as the base type
244  if (type_in == TRISHELL3)
245  base_type = TRI3;
246 
247  if (type_in == QUADSHELL4)
248  base_type = QUAD4;
249 
250  if (type_in == QUADSHELL8)
251  base_type = QUAD8;
252 
253  init_ref_elem_table();
254 
255  // Throw an error if the user asked for an ElemType that we don't
256  // have a reference element for.
257  if (ref_elem_map[base_type] == libmesh_nullptr || type_in == INVALID_ELEM)
258  libmesh_error_msg("No reference elem data available for ElemType " << type_in << " = " << Utility::enum_to_string(type_in) << ".");
259 
260  return *ref_elem_map[base_type];
261 }
262 } // namespace ReferenceElem
263 } // namespace libMesh
Base class for all library singleton objects.
A Node is like a Point, but with more information.
Definition: node.h:52
static UniquePtr< Elem > build(const ElemType type, Elem *p=libmesh_nullptr)
Definition: elem.C:238
dof_id_type n_elem(const MeshBase::const_element_iterator &begin, const MeshBase::const_element_iterator &end)
Count up the number of elements of a specific type (as defined by an iterator range).
Definition: mesh_tools.C:656
ElemType
Defines an enum for geometric element types.
This is the base class from which all geometric element types are derived.
Definition: elem.h:89
const class libmesh_nullptr_t libmesh_nullptr
The libMesh namespace provides an interface to certain functionality in the library.
static const unsigned int type_to_n_nodes_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of nodes in the element...
Definition: elem.h:564
libmesh_assert(j)
std::unique_ptr< T > UniquePtr
Definition: auto_ptr.h:46
const dof_id_type n_nodes
Definition: tecplot_io.C:67
PetscErrorCode Vec x
std::string enum_to_string(const T e)