Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
LagrangeElement.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_LagrangeElement_H_
9#define model_LagrangeElement_H_
10
11#include <vector>
12#include <map>
13#include <deque>
14
15#include <Eigen/Dense>
16
17#include <TypeTraits.h>
20#include <StarsAndBars.h>
21#include <BarycentricTraits.h>
23#include <LagrangeNode.h>
25#include <Simplex.h>
26
27
28namespace model
29{
30
31 /**************************************************************************/
32 /**************************************************************************/
57 template<int _dim,int degree, template<typename T> class MappingType=IsoparametricMapping>
58 class LagrangeElement : private std::vector<LagrangeNode<LagrangeElement<_dim,degree,MappingType>>*>
59 {
60
62
63 public:
64
65 constexpr static int dim=_dim;
66 constexpr static int order=degree;
68 constexpr static int dofPerNode(int c) { return c; }
69
71 typedef Eigen::Matrix<double,1,dim+1> BaryType;
72
73 private:
74
75 /**********************************************************************/
76 static Eigen::Matrix<double,1,Eigen::Dynamic> shapeFunctionCoeff(const int& N)
77 {
82 Eigen::Matrix<int,1,Eigen::Dynamic> prod(1,1);
83 prod<<1; // initialize the polynomial
84 int f(1); // initialize the factorial
85
86 for (int n=0;n<N;++n)
87 {
88 Eigen::Matrix<int,1,2> temp2(-n,degree);
89 Eigen::Matrix<int,1,Eigen::Dynamic> temp1(1,prod.cols()+1);
90 temp1.setZero();
91 for (int i = 0;i < prod.cols();++i)
92 {
93 for (int j = 0;j < temp2.cols();++j)
94 {
95 temp1(i + j) += prod(i) * temp2(j); // convolution
96 }
97 }
98 prod=temp1; // overwrite product
99 if (n>0)
100 {
101 f*=n; // compute factorial
102 }
103 }
104 if (N>0)
105 {
106 f*=N; // add last term to factorial
107 }
108 return prod.cast<double>()/f;
109 }
110
111 /**********************************************************************/
112 static Eigen::Matrix<double,dim+1,degree+1> getSFcoeffs(const Eigen::Matrix<int,1,dim+1>& bary)
113 {
117 Eigen::Matrix<double,dim+1,degree+1> temp(Eigen::Matrix<double,dim+1,degree+1>::Zero());
118 for (int k=0;k<dim+1;++k)
119 {
120 temp.row(k).segment(0,bary(k)+1)=shapeFunctionCoeff(bary(k));
121 }
122 return temp;
123 }
124
125 /**********************************************************************/
126 static std::vector<Eigen::Matrix<double,dim+1,degree+1>> get_sfCoeffsVector()
127 {
130 std::vector<Eigen::Matrix<double,dim+1,degree+1>> temp;
131 for (int n=0;n<nodesPerElement;++n)
132 {
133 temp.push_back(getSFcoeffs(baryStarsAndBars.row(n)));
134 }
135 return temp;
136 }
137
138 /**********************************************************************/
139 static Eigen::Matrix<double,1,dim+1> sfcTimesBary(const int& n, const BaryType& bary)
140 {
141 Eigen::Matrix<double,1,dim+1> temp(Eigen::Matrix<double,1,dim+1>::Zero());
142 for(int d=0;d<dim+1;++d) // this loop can be parallelized
143 {
144 Eigen::Matrix<double,degree+1,1> bPow(Eigen::Matrix<double,degree+1,1>::Ones());
145 for (int p=1;p<degree+1;++p) // start at 1 since bPow(0)=1 from initialization
146 {
147 // bPow(p)=std::pow(bary(d),p);
148 bPow(p)=bPow(p-1)*bary(d);
149 }
150 temp(d)=sfCoeffsVector[n].row(d).dot(bPow);
151 }
152 return temp;
153 }
154
155 /**********************************************************************/
156 static Eigen::Matrix<double,1,dim+1> sfcTimesBaryDiff(const int& n, const BaryType& bary)
157 {
158 Eigen::Matrix<double,1,dim+1> temp(Eigen::Matrix<double,1,dim+1>::Zero());
159 for(int d=0;d<dim+1;++d) // this loop can be parallelized
160 {
161
162 Eigen::Matrix<double,degree+1,1> bPow(Eigen::Matrix<double,degree+1,1>::Ones());
163 for (int p=2;p<degree+1;++p) // start at 1 since bPow(0)=0 (unused) and bPow(1)=1 from initialization
164 {
165 bPow(p)=p*std::pow(bary(d),p-1);
166 }
167 // temp(d)=sfCoeffs.row(d).dot(bPow);
168 temp(d)=sfCoeffsVector[n].template block<1,degree>(d,1).dot(bPow.template segment<degree>(1));
169 }
170 return temp;
171 }
172
173 /**********************************************************************/
174 static Eigen::Matrix<double,dim,dim> get_FL(const Simplex<dim,dim>& s)
175 {
176 Eigen::Matrix<double,dim,dim> temp;
177
178 const typename SimplexTraits<dim,0>::SimplexIDType last(std::set<size_t>{s.xID(dim)});
179// last<<s.xID(dim); // a 1x1 matrix
180// last[0]=s.xID(dim); // a 1x1 matrix
181
183 for (int k=0;k<dim;++k)
184 {
185 const typename SimplexTraits<dim,0>::SimplexIDType current(std::set<size_t>{s.xID(k)});
186// current<<s.xID(k); // a 1x1 matrix
187// current[0]=s.xID(k); // a 1x1 matrix
188 temp.col(k) << s.mesh->template simplexFactory<0>().getRef(current).P0 - s.mesh->template simplexFactory<0>().getRef(last).P0;
189 }
190 return temp;
191 }
192
193
194 public:
195
196
197 static const Eigen::Matrix<int ,CombinationWithRepetition<_dim+1,degree>::value,_dim+1> baryStarsAndBars;
198 static const Eigen::Matrix<double,CombinationWithRepetition<_dim+1,degree>::value,_dim+1> baryNodalCoordinates;
199 static const std::vector<Eigen::Matrix<double,_dim+1,degree+1>> sfCoeffsVector;
200
203
205 Eigen::Matrix<double,_dim,nodesPerElement> Xe; // this should be private
206
207
208 /**********************************************************************/
210 std::deque<NodeType>& nodeContainer,
211 std::map<Eigen::Matrix<double,dim,1>, NodeType* const,
213 std::map<size_t,const NodeType* const>& mesh2femIDmap) :
214 /* init list */ simplex(s)
215 {
217
218 const typename SimplexTraits<dim,0>::SimplexIDType last(std::set<size_t>{s.xID(dim)});
219// last<<s.xID(dim); // a 1x1 matrix
220// last[0]=s.xID(dim); // a 1x1 matrix
221
222 const Eigen::Matrix<double,dim,dim> FL(get_FL(simplex));
223
224
225 for (int n=0;n<nodesPerElement;++n)
226 {
227 // Place nodes linearly
228 const Eigen::Matrix<double,dim,1> P(FL*BarycentricTraits<dim>::l2x(baryNodalCoordinates.row(n))+s.mesh->template simplexFactory<0>().getRef(last).P0);
229
230 typename std::map<Eigen::Matrix<double,dim,1>, NodeType* const, CompareVectorsByComponent<double,dim,float> >::const_iterator nIter(nodeFinder.find(P));
231
232 NodeType* pN;
233
234 if (nIter!=nodeFinder.end())
235 {// A node already exists at P.
236 pN=nIter->second; // grab its pointer.
237 }
238 else
239 {// No nodes exist at P.
240 nodeContainer.emplace_back(P,nodeContainer.size()); // create a new one in nodeContainer
241 pN=&*nodeContainer.rbegin(); // grab node pointer
242
243 const bool success(nodeFinder.insert(std::make_pair(P,pN)).second); // insert pointer in nodeFinder
244 if(!success)
245 {
246 throw std::runtime_error("NODE NOT INSERTED in nodeFinder");
247 }
248
249 size_t maxID=0;
250 const double maxVal(baryNodalCoordinates.row(n).maxCoeff(&maxID));
251 if(maxVal==1.0)
252 {// A FEM node coinciding with a mesh node
253 mesh2femIDmap.emplace(simplex.vertices()[maxID]->xID(0),pN);
254 }
255 else
256 {
257// std::cout<<"maxVal="<<maxVal<<std::endl;
258 }
259
260 }
261
262 this->emplace_back(pN); // add node to this
263
264 Xe.col(n)=P; // insert node poision in matrix Xe
265
266
267
268
269 }
270
271 }
272
273// /**********************************************************************/
274// ~LagrangeElement()
275// {
276// for(int n=0;n<this->size();++n)
277// {
278// int nErased=this->operator[](n)->erase(this);
279// assert(nErased==1);
280// }
281// }
282
283 /**********************************************************************/
284 //template<typename TrialFunctionType>
285 static Eigen::Matrix<double,1,nodesPerElement> sf(const BaryType& bary)
286 {
293 Eigen::Matrix<double,1,nodesPerElement> temp;
294 for(int n=0;n<nodesPerElement;++n)
295 {
296 temp(n)=sfcTimesBary(n,bary).prod();
297 }
298 return temp;
299 }
300
301 /**********************************************************************/
302 template<typename TrialFunctionType>
313
314 /**********************************************************************/
315 static Eigen::Matrix<double,dim+1,nodesPerElement> diff(const BaryType& bary)
316 {
323 Eigen::Matrix<double,dim+1,nodesPerElement> temp(Eigen::Matrix<double,dim+1,nodesPerElement>::Zero());
324 for (int n=0;n<nodesPerElement;++n)
325 {
326 const Eigen::Matrix<double,1,dim+1> temp1(sfcTimesBary(n,bary));
327 const Eigen::Matrix<double,1,dim+1> temp2(sfcTimesBaryDiff(n,bary));
328
329 for(int d=0;d<dim+1;++d)
330 {
331 Eigen::Matrix<double,1,dim+1> temp3(temp1);
332 temp3(d)=temp2(d);
333 temp(d,n)=temp3.prod();
334 }
335 }
336 return temp;
337 }
338
339 /**********************************************************************/
340 static Eigen::Matrix<double,dim,nodesPerElement> gradS(const BaryType& bary)
341 {
348 return BarycentricTraits<dim>::dLdX.transpose()*diff(bary);
349 }
350
351 /**********************************************************************/
352 template<typename TrialFunctionType>
354 {
361 Eigen::Matrix<double,dim,nodesPerElement> temp(Gs(bary).transpose()*gradS(bary));
363 }
364
365
366 /**********************************************************************/
367 template<typename TrialFunctionType>
369 {
373 static_assert(TypeTraits<TrialFunctionType>::nComponents==dim,"SYMMETRIC GRADIENT (DEF) CAN ONLY BE COMPUTED IF nComponents==dim.");
374 Eigen::Matrix<double,dim,nodesPerElement> temp(Gs(bary).transpose()*gradS(bary));
376 }
377
378 /**********************************************************************/
379 const NodeType& node(const size_t& n) const
380 {
383 assert(n<nodesPerElement && "NODE ID EXCEEDS nodesPerElement");
384 return *this->operator[](n);
385 }
386
387 /**********************************************************************/
388 NodeType& node(const size_t& n)
389 {
392 assert(n<nodesPerElement && "NODE ID EXCEEDS nodesPerElement");
393 return *this->operator[](n);
394 }
395
396 /**********************************************************************/
397 Eigen::Matrix<double,dim,1> position(const BaryType& bary) const
398 {
401 return MappingType<ElementType>(*this).position(bary);
402 }
403
404 /**********************************************************************/
405 Eigen::Matrix<double,_dim,_dim> Fs(const BaryType& bary) const
406 {
409 return MappingType<ElementType>(*this).Fs(bary);
410 }
411
412 /**********************************************************************/
413 double absJ(const BaryType& bary) const
414 {
418 return MappingType<ElementType>(*this).absJ(bary);
419 }
420
421 /**********************************************************************/
422 Eigen::Matrix<double,_dim,_dim> Gs(const BaryType& bary) const
423 {
426 return MappingType<ElementType>(*this).Gs(bary);
427 }
428
429 /**********************************************************************/
430 Eigen::Matrix<double,dim,1> jGN(const BaryType& bary, const int& n) const
431 {
432 return MappingType<ElementType>(*this).jGN(bary,n);
433 }
434
435 /**********************************************************************/
436 bool isBoundaryElement() const
437 {
439 return simplex.isBoundarySimplex();
440 }
441
442 /**********************************************************************/
443 std::vector<int> boundaryFaces() const
444 {
446 return simplex.boundaryFaces();
447 }
448
449 };
450
451
452
453
454 // Declare static data members
455 template<int dim,int degree, template<typename T> class MappingType>
456 const Eigen::Matrix<int,CombinationWithRepetition<dim+1,degree>::value,dim+1> LagrangeElement<dim,degree,MappingType>::baryStarsAndBars=StarsAndBars<dim+1,degree>::sAb();
457
458 template<int dim,int degree, template<typename T> class MappingType>
459 const Eigen::Matrix<double,CombinationWithRepetition<dim+1,degree>::value,dim+1> LagrangeElement<dim,degree,MappingType>::baryNodalCoordinates=LagrangeElement<dim,degree>::baryStarsAndBars.template cast<double>()/degree;
460
461 template<int dim,int degree, template<typename T> class MappingType>
462 const std::vector<Eigen::Matrix<double,dim+1,degree+1>> LagrangeElement<dim,degree,MappingType>::sfCoeffsVector=LagrangeElement<dim,degree,MappingType>::get_sfCoeffsVector();
463
464} // close namespace
465#endif
466
467
468
Class template that defines the isoparametric coordinate transformation between actual and standared ...
Eigen::Matrix< double, dim, 1 > jGN(const BaryType &bary, const int &n) const
LagrangeNode< ElementType > NodeType
TypeTraits< TrialFunctionType >::ShapeFunctionGradMatrixType sfmGrad(const BaryType &bary) const
TypeTraits< TrialFunctionType >::ShapeFunctionDefMatrixType sfmDef(const BaryType &bary) const
static const Eigen::Matrix< int,CombinationWithRepetition< _dim+1, degree >::value, _dim+1 > baryStarsAndBars
Eigen::Matrix< double, _dim, _dim > Fs(const BaryType &bary) const
Eigen::Matrix< double, _dim, nodesPerElement > Xe
static const Eigen::Matrix< double, CombinationWithRepetition< _dim+1, degree >::value, _dim+1 > baryNodalCoordinates
Eigen::Matrix< double, dim, 1 > position(const BaryType &bary) const
LagrangeElement(const Simplex< dim, dim > &s, std::deque< NodeType > &nodeContainer, std::map< Eigen::Matrix< double, dim, 1 >, NodeType *const, CompareVectorsByComponent< double, dim, float > > &nodeFinder, std::map< size_t, const NodeType *const > &mesh2femIDmap)
Eigen::Matrix< double, _dim, _dim > Gs(const BaryType &bary) const
static Eigen::Matrix< double, 1, nodesPerElement > sf(const BaryType &bary)
static TypeTraits< TrialFunctionType >::ShapeFunctionMatrixType sfm(const BaryType &bary)
static constexpr int nodesPerElement
static constexpr int dofPerNode(int c)
const NodeType & node(const size_t &n) const
static Eigen::Matrix< double, dim, nodesPerElement > gradS(const BaryType &bary)
double absJ(const BaryType &bary) const
const Simplex< dim, dim > & simplex
Eigen::Matrix< double, 1, dim+1 > BaryType
static Eigen::Matrix< double, dim+1, nodesPerElement > diff(const BaryType &bary)
NodeType & node(const size_t &n)
static const std::vector< Eigen::Matrix< double, _dim+1, degree+1 > > sfCoeffsVector
std::vector< int > boundaryFaces() const
c
Definition int_R.m:15
function int_R syms a b c u real f
Definition int_R.m:4
static const MatrixHigherDimDimD dLdX
static VectorDimD l2x(const VectorHigherDimD &L)
SimplexID< nVertices > SimplexIDType
static Eigen::Matrix< int, r1+r2, N > sAb()
int j
vertex p[3]
int k
enum insertvertexresult success
int i
vertex temp
int current