Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
FiniteElement.h
Go to the documentation of this file.
1/* This file is part of MoDELib, the Mechanics Of Defects Evolution Library.
2 *
3 *
4 * MoDELib is distributed without any warranty under the
5 * GNU General Public License (GPL) v2 <http://www.gnu.org/licenses/>.
6 */
7
8#ifndef model_FiniteElement_H_
9#define model_FiniteElement_H_
10
11#include <deque>
12#include <map>
13#include <list>
14#include <stdexcept> // std::out_of_range
15#include <type_traits> // std::is_same
16
17
18#include <Eigen/Dense>
19
20#include <TrialFunctionTraits.h>
21//#include <AreSameType.h>
22#include <SimplicialMesh.h>
23#include <TerminalColors.h>
25#include <SimplicialMesh.h>
26#include <LagrangeElement.h>
28#include <TrialFunction.h>
29#include <TrialSum.h>
30#include <LinearWeakForm.h>
31#include <BilinearWeakForm.h>
32#include <IntegrationDomain.h>
33#include <EntireDomain.h>
35#include <ExternalBoundary.h>
36//#include <NodeList.h>
37
38namespace model
39{
40
41 template<typename _ElementType>
42 class FiniteElement : public std::enable_shared_from_this<FiniteElement<_ElementType>>,
43// /* inherits */ public std::map<Eigen::Matrix<size_t,_ElementType::dim+1,1>, // key
44// /* */ _ElementType, // value
45// /* */ CompareVectorsByComponent<size_t,_ElementType::dim+1> // key compare
46// /* */ >, // element container
47 /* inherits */ public std::map<typename SimplexTraits<_ElementType::dim,_ElementType::dim>::SimplexIDType, // key
48 /* */ _ElementType>, // value
49// /* */ CompareVectorsByComponent<size_t,_ElementType::dim+1> // key compare
50// /* */ >, // element container
51 /* inherits */ public std::deque<typename _ElementType::NodeType>, // node container
52 /* inherits */ public std::map<Eigen::Matrix<double,_ElementType::dim,1>, // key
53 /* */ typename _ElementType::NodeType* const, // value
54 /* */ CompareVectorsByComponent<double,_ElementType::dim,float> // key compare
55 /* */ >, // nodefinder
56 /* inherits */ private std::map<size_t,std::deque<const typename _ElementType::NodeType*>>,// node-list container
57 /* inherits */ private std::map<size_t,const typename _ElementType::NodeType* const>
58 {
59
60 private:
61 std::shared_ptr<const SimplicialMesh<_ElementType::dim>> meshOwner;
62 std::shared_ptr<const int> lifetime=std::make_shared<const int>(0);
63 std::weak_ptr<const int> meshLifetime;
64 Eigen::Matrix<double,_ElementType::dim,1> _xMin;
65 Eigen::Matrix<double,_ElementType::dim,1> _xMax;
66 Eigen::Matrix<double,_ElementType::dim,1> _xMean;
67
68 size_t nodeListID;
70
71
72 public:
73
74 typedef _ElementType ElementType;
76 typedef typename ElementType::NodeType NodeType;
77// typedef std::list<const NodeType*> NodeListType;
78// typedef std::map<size_t,NodeListType> NodeMapType;
79 typedef std::deque<const NodeType*> NodeListType;
80 typedef std::map<size_t,NodeListType> NodeListContainerType;
81
82 constexpr static int dim=ElementType::dim;
83 constexpr static int nodesPerElement=ElementType::nodesPerElement;
85// typedef std::map<Eigen::Matrix<size_t,_ElementType::dim+1,1>, // key
86// /* */ _ElementType, // value
87// /* */ CompareVectorsByComponent<size_t,_ElementType::dim+1> // key compare
88// /* */ > ElementContainerType;
89 typedef std::map<typename SimplexTraits<_ElementType::dim,_ElementType::dim>::SimplexIDType, // key
90 /* */ _ElementType> ElementContainerType;
91 typedef std::deque<typename _ElementType::NodeType> NodeContainerType;
92 typedef std::map<Eigen::Matrix<double,_ElementType::dim,1>, // key
93 /* */ typename _ElementType::NodeType* const, // value
96
97 const MeshType& mesh;
98
99 /**********************************************************************/
101 /* init list */ _xMin(Eigen::Matrix<double,dim,1>::Zero()),
102 /* init list */ _xMax(Eigen::Matrix<double,dim,1>::Zero()),
103 /* init list */ nodeListID(0),
104 /* init list */ mesh(m)
105 {
106 meshLifetime=m.lifetimeToken();
110
111 std::cout<<greenBoldColor<<"Creating FiniteElement:\n"<<defaultColor<<std::flush;
112
113 // THIS IS NECESSARY TO AVOID "STATIC INITIALIZATION FIASCO"
114 std::cout<<"Element barycentric coordinates:\n"<<ElementType::baryNodalCoordinates<<std::endl;
115
116 // Insert elements
117 for (const auto& simpl : mesh.simplices())
118 {
119 auto temp=ElementContainerType::emplace(simpl.first,ElementType(*simpl.second,*this,*this,mesh2femIDmap()));
120// assert(temp.second && "UNABLE TO INSERT ELEMENT IN ELEMENT CONTAINER.");
121 if(!temp.second)
122 {
123 throw std::runtime_error("UNABLE TO INSERT ELEMENT IN ELEMENT CONTAINER.");
124 }
125
126 // Add element pointer to each of its nodes
127 for(int n=0;n<ElementType::nodesPerElement;++n)
128 {
129 auto temp1=temp.first->second.node(n).emplace(&temp.first->second);
130 if(!temp1.second)
131 {
132 throw std::runtime_error("UNABLE TO INSERT ELEMENT IN NODE.");
133 }
134// assert(temp1.second && "UNABLE TO INSERT ELEMENT IN NODE.");
135 }
136 }
137
138 if(std::is_same<ElementType,LagrangeElement<ElementType::dim,ElementType::order>>::value)
139 {
140 if(mesh2femIDmap().size()!=mesh.template simplexFactory<0>().liveSimplices().size())
141 {
142 std::cout<<"mesh2femIDmap().size()="<<mesh2femIDmap().size()<<std::endl;
143 std::cout<<"mesh.template simplexFactory<0>().liveSimplices().size()="<<mesh.template simplexFactory<0>().liveSimplices().size()<<std::endl;
144 throw std::runtime_error("mesh2femIDmap has wrong size.");
145 }
146// assert((mesh2femIDmap().size()==mesh.template simplexFactory<0>().liveSimplices().size()) && "mesh2femIDmap has wrong size.");
147
148 }
149
150 // Check that node[k].gID==k;
151 for(size_t n=0;n<nodes().size();++n)
152 {
153 if(node(n).gID!=n)
154 {
155 throw std::runtime_error("node(n).gID!=n");
156 }
157// assert(node(n).gID==n);
158 }
159
160 // Compute _xMin and _xMax
161
162 if(nodeSize())
163 {
164 _xMin=node(0).P0;
165 _xMax=node(0).P0;
166
167 for (size_t n=0;n<nodeSize();++n)
168 {
169 for(int d=0;d<dim;++d)
170 {
171 if (node(n).P0(d)<_xMin(d))
172 {
173 _xMin(d)=node(n).P0(d);
174 }
175 if (node(n).P0(d)>_xMax(d))
176 {
177 _xMax(d)=node(n).P0(d);
178 }
179 }
180 }
181 _xMean=0.5*(_xMin+_xMax);
182
183 }
184
185 updatePeriodicNodePairs();
186 std::cout<<" # elements: "<<elementSize() <<"\n";
187 std::cout<<" # nodes: " <<nodeSize() <<"\n";
188 std::cout<<" xMin= " <<_xMin.transpose()<<"\n";
189 std::cout<<" xMax= " <<_xMax.transpose()<<std::endl;
190 }
191
192 /**********************************************************************/
193 explicit FiniteElement(std::shared_ptr<const MeshType> m): FiniteElement(requireMesh(m))
194 {
195 meshOwner=std::move(m);
196 }
197 static const MeshType& requireMesh(const std::shared_ptr<const MeshType>& m)
198 {
199 if(!m)
200 {
201 throw std::invalid_argument("Null FEM mesh.");
202 }
203 return *m;
204 }
207 std::weak_ptr<const int> lifetimeToken() const
208 {
209 return lifetime;
210 }
212 {
213 if(meshLifetime.expired())
214 {
215 throw std::runtime_error("FEM space outlived its borrowed mesh. Use an owning mesh constructor.");
216 }
217 }
218
219 // Rebuild explicitly if mesh active periodicity changes after FE creation.
221 {
222 if constexpr(std::is_same_v<ElementType,LagrangeElement<dim,ElementType::order>>)
223 {
225 _periodicNodes=std::move(staged);
226 }
227 else
228 {
229 // Discontinuous spaces do not acquire strong periodic ties.
230 _periodicNodes.representatives.resize(nodeSize());
231 _periodicNodes.shifts.assign(nodeSize(),Eigen::Matrix<double,dim,1>::Zero());
232 for(size_t i=0;i<nodeSize();++i)
233 {
234 _periodicNodes.representatives[i]=i;
235 }
236 }
237 }
238 const auto& periodicNodePairs() const
239 {
240 return _periodicNodes.pairs;
241 }
242 size_t periodicRepresentative(size_t nodeID) const
243 {
244 return _periodicNodes.representatives.at(nodeID);
245 }
246 const Eigen::Matrix<double,dim,1>& periodicShift(size_t nodeID) const
247 {
248 return _periodicNodes.shifts.at(nodeID);
249 }
250
251 template<int nComponents>
252 auto trial()
253 {
254 return std::make_shared<TrialFunction<'u',nComponents,FiniteElementType>>(*this);
255 }
256
257 template <char name,int nComponents>
258 auto trial() // made non-const only to allow fe.createNodeList
259 {
260 return std::make_shared<TrialFunction<name,nComponents,FiniteElementType>>(*this);
261 }
262
263 /**********************************************************************/
265 {
266 return *this;
267 }
268
269 /**********************************************************************/
270 size_t elementSize() const
271 {
273 return ElementContainerType::size();
274 }
275
276 /**********************************************************************/
278 {
279 return *this;
280 }
281
282 /**********************************************************************/
283 size_t nodeSize() const
284 {
285 return NodeContainerType::size();
286 }
287
288 /**********************************************************************/
289 const NodeType& node(const size_t& n) const
290 {
293 return NodeContainerType::operator[](n);
294 }
295
296 /**********************************************************************/
298 {
299 return *this;
300 }
301
302 /**********************************************************************/
303 const Eigen::Matrix<double,dim,1>& xMin() const
304 {
305 return _xMin;
306 }
307
308 /**********************************************************************/
309 const double& xMin(const int& k) const
310 {
311 return _xMin(k);
312 }
313
314 /**********************************************************************/
315 const Eigen::Matrix<double,dim,1>& xMax() const
316 {
317 return _xMax;
318 }
319
320 /**********************************************************************/
321 const double& xMax(const int& k) const
322 {
323 return _xMax(k);
324 }
325
326 /**********************************************************************/
327 const Eigen::Matrix<double,dim,1>& xMean() const
328 {
329 return _xMean;
330 }
331
332 /**********************************************************************/
333 const double& xMean(const int& k) const
334 {
335 return _xMean(k);
336 }
337
338 /**********************************************************************/
339 template <typename BndType, int qOrder, template <short unsigned int, size_t> class QuadratureRule>
344
345 /**********************************************************************/
346 template <typename DomainType, int qOrder, template <short unsigned int, size_t> class QuadratureRule>
351
352 /**********************************************************************/
353 const std::map<size_t,const typename _ElementType::NodeType* const>& mesh2femIDmap() const
354 {
355 return *this;
356 }
357
358 /**********************************************************************/
359 std::map<size_t,const typename _ElementType::NodeType* const>& mesh2femIDmap()
360 {
361 return *this;
362 }
363
364 /**********************************************************************/
365 template <typename NodeSelectorType, typename... NodeSelectorArgs>
366 size_t createNodeList(const NodeSelectorArgs&... args)
367 {
368 //const size_t nodeListID_old(nodeListID);
369 auto pair=NodeListContainerType::emplace(nodeListID,NodeListType());
370 assert(pair.second);
371 const NodeSelectorType nodeSelector(*this,args...);
372 for(auto& node : nodes())
373 {
374 if(nodeSelector(node))
375 {
376 pair.first->second.emplace_back(&node);
377 }
378 }
379 nodeListID++;
380 return pair.first->first;
381 }
382
383 /**********************************************************************/
385 {
386 return NodeListContainerType::clear();
387 }
388
389 /**********************************************************************/
390 const NodeListType& nodeList(const size_t& k) const
391 {
392 try
393 {
394 return NodeListContainerType::at(k);
395 }
396 catch (const std::out_of_range& oor)
397 {
398 std::cerr << "FiniteElement::nodeList(), out_of_range error: " << oor.what() << "\n";
399 return NodeListContainerType::at(k);
400 }
401 }
402
403 /**********************************************************************/
404 std::pair<bool,const ElementType*> search(const Eigen::Matrix<double,dim,1>& P) const
405 {
413 return searchWithGuess(P,&(elements().begin()->second.simplex));
414 }
415
416 /**********************************************************************/
417 std::pair<bool,const ElementType*> searchWithGuess(const Eigen::Matrix<double,dim,1>& P, const Simplex<dim,dim>* const guess) const
418 {
425 const std::pair<bool,const Simplex<dim,dim>*> temp(mesh.searchWithGuess(P,guess));
426 const typename ElementContainerType::const_iterator eIter(ElementContainerType::find(temp.second->xID));
427// const typename ElementContainerType::const_iterator eIter(ElementContainerType::find(Eigen::Map<const Eigen::Matrix<size_t,_ElementType::dim+1,1>>(temp.second->xID.data())));
428 assert(eIter!=elements().end() && "ELEMENT NOT FOUND");
429 return std::pair<bool,const ElementType*>(temp.first,&(eIter->second));
430 }
431
432 };
433
434} // close namespace
435#endif
std::pair< bool, const ElementType * > searchWithGuess(const Eigen::Matrix< double, dim, 1 > &P, const Simplex< dim, dim > *const guess) const
const double & xMean(const int &k) const
const Eigen::Matrix< double, dim, 1 > & xMin() const
const auto & periodicNodePairs() const
std::map< typename SimplexTraits< ElementType::dim, ElementType::dim >::SimplexIDType, ElementType > ElementContainerType
FiniteElement(FiniteElement &&)=delete
std::deque< const NodeType * > NodeListType
static constexpr int nodesPerElement
const NodeContainerType & nodes() const
FiniteElement< ElementType > FiniteElementType
std::map< size_t, NodeListType > NodeListContainerType
size_t periodicRepresentative(size_t nodeID) const
size_t createNodeList(const NodeSelectorArgs &... args)
FiniteElement(std::shared_ptr< const MeshType > m)
IntegrationDomain< FiniteElementType, 1, qOrder, QuadratureRule > boundary() const
const NodeListType & nodeList(const size_t &k) const
const Eigen::Matrix< double, dim, 1 > & xMean() const
const NodeFinderType & nodeFinder() const
size_t elementSize() const
FiniteElement(const SimplicialMesh< dim > &m)
std::map< size_t, const typename _ElementType::NodeType *const > & mesh2femIDmap()
const std::map< size_t, const typename _ElementType::NodeType *const > & mesh2femIDmap() const
std::weak_ptr< const int > lifetimeToken() const
std::deque< typename ElementType::NodeType > NodeContainerType
std::map< Eigen::Matrix< double, ElementType::dim, 1 >, typename ElementType::NodeType *const, CompareVectorsByComponent< double, ElementType::dim, float > > NodeFinderType
std::pair< bool, const ElementType * > search(const Eigen::Matrix< double, dim, 1 > &P) const
static const MeshType & requireMesh(const std::shared_ptr< const MeshType > &m)
const ElementContainerType & elements() const
const double & xMax(const int &k) const
const Eigen::Matrix< double, dim, 1 > & xMax() const
IntegrationDomain< FiniteElementType, 0, qOrder, QuadratureRule > domain() const
const NodeType & node(const size_t &n) const
const double & xMin(const int &k) const
FiniteElement(const FiniteElement &)=delete
const Eigen::Matrix< double, dim, 1 > & periodicShift(size_t nodeID) const
void validateMeshLifetime() const
static std::string greenBoldColor
static std::string defaultColor
int end[2]
int elements
int k
int i
vertex temp
void t struct mesh * m