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 
27 // C++ includes
28 #include <map>
29 #include <sstream>
30 
31 
32 
33 //-----------------------------------------------
34 // anonymous namespace for implementation details
35 namespace
36 {
37  using namespace libMesh;
38 
39  namespace ElemDataStrings
40  {
41 #include "reference_elem.data"
42  }
43 
44  typedef Threads::spin_mutex InitMutex;
45 
46  // Mutex for thread safety.
47  InitMutex init_mtx;
48 
49  // map from ElemType to reference element file system object name
50  typedef std::map<ElemType, const char*> FileMapType;
51  FileMapType ref_elem_file;
52  Elem* ref_elem_map[INVALID_ELEM];
53 
54 
55 
56  class SingletonCache : public libMesh::Singleton
57  {
58  public:
59  ~SingletonCache()
60  {
61  for (unsigned int e=0; e<elem_list.size(); e++)
62  if (elem_list[e])
63  {
64  delete elem_list[e];
65  elem_list[e] = NULL;
66  }
67 
68  elem_list.clear();
69 
70  for (unsigned int n=0; n<node_list.size(); n++)
71  if (node_list[n])
72  {
73  delete node_list[n];
74  node_list[n] = NULL;
75  }
76 
77  node_list.clear();
78  }
79 
80  std::vector<Node*> node_list;
81  std::vector<Elem*> elem_list;
82  };
83 
84  // singleton object, dynamically created and then
85  // removed at program exit
86  SingletonCache *singleton_cache = NULL;
87 
88 
89 
90  Elem* read_ref_elem (const ElemType Type,
91  std::istream &in)
92  {
93  libmesh_assert (singleton_cache != NULL);
94 
95  static const unsigned int comm_len = 1024;
96  char comm[comm_len];
97 
98  std::string foo;
99  unsigned int n_elem, n_nodes, elem_type, nn;
100  double x, y, z;
101 
102  in >> foo;
103  in >> n_elem; in.getline (comm, comm_len); libmesh_assert_equal_to (n_elem, 1);
104  in >> n_nodes; in.getline (comm, comm_len);
105  in >> foo; in.getline (comm, comm_len);
106  in >> foo; in.getline (comm, comm_len);
107  in >> foo; in.getline (comm, comm_len);
108  in >> foo; in.getline (comm, comm_len);
109  in >> n_elem; in.getline (comm, comm_len); libmesh_assert_equal_to (n_elem, 1);
110 
111  in >> elem_type;
112 
113  libmesh_assert_less (elem_type, INVALID_ELEM);
114  libmesh_assert_equal_to (elem_type, Type);
115  libmesh_assert_equal_to (n_nodes, Elem::type_to_n_nodes_map[elem_type]);
116 
117  // Construct the elem
118  Elem *elem = Elem::build(static_cast<ElemType>(elem_type)).release();
119 
120  // We are expecing 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  elem->set_node(n) = node;
135  }
136 
137 
138  // it is entirely possible we ran out of file or encountered
139  // another error. If so, cleanly abort.
140  if (!in)
141  {
142  delete elem;
143  elem = NULL;
144  libMesh::err << "ERROR while creating element singleton!\n";
145  libmesh_error();
146  }
147 
148  else
149  singleton_cache->elem_list.push_back (elem);
150 
151  ref_elem_map[Type] = elem;
152 
153  return elem;
154  }
155 
156 
157 
158  void init_ref_elem_table()
159  {
160  // ouside mutex - if this pointer is set, we can trust it.
161  if (singleton_cache != NULL) return;
162 
163  // playing with fire here - lock before touching shared
164  // data structures
165  InitMutex::scoped_lock lock(init_mtx);
166 
167  // inside mutex - pointer may have changed while waiting
168  // for the lock to acquire, check it again.
169  if (singleton_cache != NULL) return;
170 
171  // OK, if we get here we have the lock and we are not
172  // initialized. populate singleton.
173  singleton_cache = new SingletonCache;
174 
175  // initialize the reference file table
176  {
177  ref_elem_file.clear();
178 
179  // // 1D elements
180  ref_elem_file[EDGE2] = ElemDataStrings::one_edge;
181  ref_elem_file[EDGE3] = ElemDataStrings::one_edge3;
182  ref_elem_file[EDGE4] = ElemDataStrings::one_edge4;
183 
184  // 2D elements
185  ref_elem_file[TRI3] = ElemDataStrings::one_tri;
186  ref_elem_file[TRI6] = ElemDataStrings::one_tri6;
187 
188  ref_elem_file[QUAD4] = ElemDataStrings::one_quad;
189  ref_elem_file[QUAD8] = ElemDataStrings::one_quad8;
190  ref_elem_file[QUAD9] = ElemDataStrings::one_quad9;
191 
192  // 3D elements
193  ref_elem_file[HEX8] = ElemDataStrings::one_hex;
194  ref_elem_file[HEX20] = ElemDataStrings::one_hex20;
195  ref_elem_file[HEX27] = ElemDataStrings::one_hex27;
196 
197  ref_elem_file[TET4] = ElemDataStrings::one_tet;
198  ref_elem_file[TET10] = ElemDataStrings::one_tet10;
199 
200  ref_elem_file[PRISM6] = ElemDataStrings::one_prism;
201  ref_elem_file[PRISM15] = ElemDataStrings::one_prism15;
202  ref_elem_file[PRISM18] = ElemDataStrings::one_prism18;
203 
204  ref_elem_file[PYRAMID5] = ElemDataStrings::one_pyramid;
205  ref_elem_file[PYRAMID14] = ElemDataStrings::one_pyramid14;
206  }
207 
208  // Read'em
209  for (FileMapType::const_iterator it=ref_elem_file.begin();
210  it != ref_elem_file.end(); ++it)
211  {
212  std::istringstream stream(it->second);
213 
214  read_ref_elem(it->first,
215  stream);
216  }
217  }
218 
219 
220  // no reason to do this at startup -
221  // data structures will get initialized *if*
222  // ReferenceElem::get() is ever called.
223  // // Class to setup singleton data
224  // class ReferenceElemSetup : public Singleton::Setup
225  // {
226  // void setup ()
227  // {
228  // init_ref_elem_table();
229  // }
230  // } reference_elem_setup;
231 
232 } // anonymous namespace
233 
234 
235 
236 //----------------------------------------------------------------------------
237 // external API Implementation
238 namespace libMesh
239 {
240  namespace ReferenceElem
241  {
242  const Elem & get (const ElemType Type)
243  {
244  libmesh_assert_less (Type, INVALID_ELEM);
245 
246  init_ref_elem_table();
247 
248  libmesh_assert (ref_elem_map[Type] != NULL);
249 
250  return *ref_elem_map[Type];
251  }
252  } // namespace ReferenceElem
253 } // namespace libMesh

Site Created By: libMesh Developers
Last modified: February 07 2014 16:57:07 UTC

Hosted By:
SourceForge.net Logo