$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2013 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 // Local includes 00021 #include "libmesh/node.h" 00022 #include "libmesh/elem.h" 00023 #include "libmesh/reference_elem.h" 00024 #include "libmesh/libmesh_singleton.h" 00025 #include "libmesh/threads.h" 00026 00027 // C++ includes 00028 #include <map> 00029 #include <sstream> 00030 00031 00032 00033 //----------------------------------------------- 00034 // anonymous namespace for implementation details 00035 namespace 00036 { 00037 using namespace libMesh; 00038 00039 namespace ElemDataStrings 00040 { 00041 #include "reference_elem.data" 00042 } 00043 00044 typedef Threads::spin_mutex InitMutex; 00045 00046 // Mutex for thread safety. 00047 InitMutex init_mtx; 00048 00049 // map from ElemType to reference element file system object name 00050 typedef std::map<ElemType, const char*> FileMapType; 00051 FileMapType ref_elem_file; 00052 Elem* ref_elem_map[INVALID_ELEM]; 00053 00054 00055 00056 class SingletonCache : public libMesh::Singleton 00057 { 00058 public: 00059 ~SingletonCache() 00060 { 00061 for (unsigned int e=0; e<elem_list.size(); e++) 00062 { 00063 delete elem_list[e]; 00064 elem_list[e] = NULL; 00065 } 00066 00067 elem_list.clear(); 00068 00069 for (unsigned int n=0; n<node_list.size(); n++) 00070 { 00071 delete node_list[n]; 00072 node_list[n] = NULL; 00073 } 00074 00075 node_list.clear(); 00076 } 00077 00078 std::vector<Node*> node_list; 00079 std::vector<Elem*> elem_list; 00080 }; 00081 00082 // singleton object, dynamically created and then 00083 // removed at program exit 00084 SingletonCache *singleton_cache = NULL; 00085 00086 00087 00088 Elem* read_ref_elem (const ElemType Type, 00089 std::istream &in) 00090 { 00091 libmesh_assert (singleton_cache != NULL); 00092 00093 static const unsigned int comm_len = 1024; 00094 char comm[comm_len]; 00095 00096 std::string foo; 00097 unsigned int n_elem, n_nodes, elem_type, nn; 00098 double x, y, z; 00099 00100 in >> foo; 00101 in >> n_elem; in.getline (comm, comm_len); libmesh_assert_equal_to (n_elem, 1); 00102 in >> n_nodes; in.getline (comm, comm_len); 00103 in >> foo; in.getline (comm, comm_len); 00104 in >> foo; in.getline (comm, comm_len); 00105 in >> foo; in.getline (comm, comm_len); 00106 in >> foo; in.getline (comm, comm_len); 00107 in >> n_elem; in.getline (comm, comm_len); libmesh_assert_equal_to (n_elem, 1); 00108 00109 in >> elem_type; 00110 00111 libmesh_assert_less (elem_type, INVALID_ELEM); 00112 libmesh_assert_equal_to (elem_type, static_cast<unsigned int>(Type)); 00113 libmesh_assert_equal_to (n_nodes, Elem::type_to_n_nodes_map[elem_type]); 00114 00115 // Construct the elem 00116 Elem *elem = Elem::build(static_cast<ElemType>(elem_type)).release(); 00117 00118 // We are expecing an identity map, so assert it! 00119 for (unsigned int n=0; n<n_nodes; n++) 00120 { 00121 in >> nn; 00122 libmesh_assert_equal_to (n,nn); 00123 } 00124 00125 for (unsigned int n=0; n<n_nodes; n++) 00126 { 00127 in >> x >> y >> z; 00128 00129 Node *node = new Node(x,y,z,n); 00130 singleton_cache->node_list.push_back(node); 00131 00132 elem->set_node(n) = node; 00133 } 00134 00135 00136 // it is entirely possible we ran out of file or encountered 00137 // another error. If so, cleanly abort. 00138 if (!in) 00139 { 00140 delete elem; 00141 elem = NULL; 00142 libmesh_error_msg("ERROR while creating element singleton!"); 00143 } 00144 00145 else 00146 singleton_cache->elem_list.push_back (elem); 00147 00148 ref_elem_map[Type] = elem; 00149 00150 return elem; 00151 } 00152 00153 00154 00155 void init_ref_elem_table() 00156 { 00157 // ouside mutex - if this pointer is set, we can trust it. 00158 if (singleton_cache != NULL) return; 00159 00160 // playing with fire here - lock before touching shared 00161 // data structures 00162 InitMutex::scoped_lock lock(init_mtx); 00163 00164 // inside mutex - pointer may have changed while waiting 00165 // for the lock to acquire, check it again. 00166 if (singleton_cache != NULL) return; 00167 00168 // OK, if we get here we have the lock and we are not 00169 // initialized. populate singleton. 00170 singleton_cache = new SingletonCache; 00171 00172 // initialize the reference file table 00173 { 00174 ref_elem_file.clear(); 00175 00176 // // 1D elements 00177 ref_elem_file[EDGE2] = ElemDataStrings::one_edge; 00178 ref_elem_file[EDGE3] = ElemDataStrings::one_edge3; 00179 ref_elem_file[EDGE4] = ElemDataStrings::one_edge4; 00180 00181 // 2D elements 00182 ref_elem_file[TRI3] = ElemDataStrings::one_tri; 00183 ref_elem_file[TRI6] = ElemDataStrings::one_tri6; 00184 00185 ref_elem_file[QUAD4] = ElemDataStrings::one_quad; 00186 ref_elem_file[QUAD8] = ElemDataStrings::one_quad8; 00187 ref_elem_file[QUAD9] = ElemDataStrings::one_quad9; 00188 00189 // 3D elements 00190 ref_elem_file[HEX8] = ElemDataStrings::one_hex; 00191 ref_elem_file[HEX20] = ElemDataStrings::one_hex20; 00192 ref_elem_file[HEX27] = ElemDataStrings::one_hex27; 00193 00194 ref_elem_file[TET4] = ElemDataStrings::one_tet; 00195 ref_elem_file[TET10] = ElemDataStrings::one_tet10; 00196 00197 ref_elem_file[PRISM6] = ElemDataStrings::one_prism; 00198 ref_elem_file[PRISM15] = ElemDataStrings::one_prism15; 00199 ref_elem_file[PRISM18] = ElemDataStrings::one_prism18; 00200 00201 ref_elem_file[PYRAMID5] = ElemDataStrings::one_pyramid; 00202 ref_elem_file[PYRAMID13] = ElemDataStrings::one_pyramid13; 00203 ref_elem_file[PYRAMID14] = ElemDataStrings::one_pyramid14; 00204 } 00205 00206 // Read'em 00207 for (FileMapType::const_iterator it=ref_elem_file.begin(); 00208 it != ref_elem_file.end(); ++it) 00209 { 00210 std::istringstream stream(it->second); 00211 00212 read_ref_elem(it->first, 00213 stream); 00214 } 00215 } 00216 00217 00218 // no reason to do this at startup - 00219 // data structures will get initialized *if* 00220 // ReferenceElem::get() is ever called. 00221 // // Class to setup singleton data 00222 // class ReferenceElemSetup : public Singleton::Setup 00223 // { 00224 // void setup () 00225 // { 00226 // init_ref_elem_table(); 00227 // } 00228 // } reference_elem_setup; 00229 00230 } // anonymous namespace 00231 00232 00233 00234 //---------------------------------------------------------------------------- 00235 // external API Implementation 00236 namespace libMesh 00237 { 00238 namespace ReferenceElem 00239 { 00240 const Elem & get (const ElemType Type) 00241 { 00242 libmesh_assert_less (Type, INVALID_ELEM); 00243 00244 init_ref_elem_table(); 00245 00246 libmesh_assert (ref_elem_map[Type] != NULL); 00247 00248 return *ref_elem_map[Type]; 00249 } 00250 } // namespace ReferenceElem 00251 } // namespace libMesh