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