Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
DiscontinuousLagrangeElement.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_DiscontinuousLagrangeElement_H_
9#define model_DiscontinuousLagrangeElement_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 DiscontinuousLagrangeElement : private std::vector<LagrangeNode<DiscontinuousLagrangeElement<_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
74 private:
75
76 /**********************************************************************/
77 static Eigen::Matrix<double,1,Eigen::Dynamic> shapeFunctionCoeff(const int& N)
78 {
83 Eigen::Matrix<int,1,Eigen::Dynamic> prod(1,1);
84 prod<<1; // initialize the polynomial
85 int f(1); // initialize the factorial
86
87 for (int n=0;n<N;++n)
88 {
89 Eigen::Matrix<int,1,2> temp2(-n,degree);
90 Eigen::Matrix<int,1,Eigen::Dynamic> temp1(1,prod.cols()+1);
91 temp1.setZero();
92 for (int i = 0;i < prod.cols();++i)
93 {
94 for (int j = 0;j < temp2.cols();++j)
95 {
96 temp1(i + j) += prod(i) * temp2(j); // convolution
97 }
98 }
99 prod=temp1; // overwrite product
100 if (n>0)
101 {
102 f*=n; // compute factorial
103 }
104 }
105 if (N>0)
106 {
107 f*=N; // add last term to factorial
108 }
109 return prod.cast<double>()/f;
110 }
111
112 /**********************************************************************/
113 static Eigen::Matrix<double,dim+1,degree+1> getSFcoeffs(const Eigen::Matrix<int,1,dim+1>& bary)
114 {
118 Eigen::Matrix<double,dim+1,degree+1> temp(Eigen::Matrix<double,dim+1,degree+1>::Zero());
119 for (int k=0;k<dim+1;++k)
120 {
121 temp.row(k).segment(0,bary(k)+1)=shapeFunctionCoeff(bary(k));
122 }
123 return temp;
124 }
125
126 /**********************************************************************/
127 static std::vector<Eigen::Matrix<double,dim+1,degree+1>> get_sfCoeffsVector()
128 {
131 std::vector<Eigen::Matrix<double,dim+1,degree+1>> temp;
132 for (int n=0;n<nodesPerElement;++n)
133 {
134 temp.push_back(getSFcoeffs(baryStarsAndBars.row(n)));
135 }
136 return temp;
137 }
138
139 /**********************************************************************/
140 static Eigen::Matrix<double,1,dim+1> sfcTimesBary(const int& n, const BaryType& bary)
141 {
142 Eigen::Matrix<double,1,dim+1> temp(Eigen::Matrix<double,1,dim+1>::Zero());
143 for(int d=0;d<dim+1;++d) // this loop can be parallelized
144 {
145 Eigen::Matrix<double,degree+1,1> bPow(Eigen::Matrix<double,degree+1,1>::Ones());
146 for (int p=1;p<degree+1;++p) // start at 1 since bPow(0)=1 from initialization
147 {
148 // bPow(p)=std::pow(bary(d),p);
149 bPow(p)=bPow(p-1)*bary(d);
150 }
151 temp(d)=sfCoeffsVector[n].row(d).dot(bPow);
152 }
153 return temp;
154 }
155
156 /**********************************************************************/
157 static Eigen::Matrix<double,1,dim+1> sfcTimesBaryDiff(const int& n, const BaryType& bary)
158 {
159 Eigen::Matrix<double,1,dim+1> temp(Eigen::Matrix<double,1,dim+1>::Zero());
160 for(int d=0;d<dim+1;++d) // this loop can be parallelized
161 {
162
163 Eigen::Matrix<double,degree+1,1> bPow(Eigen::Matrix<double,degree+1,1>::Ones());
164 for (int p=2;p<degree+1;++p) // start at 1 since bPow(0)=0 (unused) and bPow(1)=1 from initialization
165 {
166 bPow(p)=p*std::pow(bary(d),p-1);
167 }
168 // temp(d)=sfCoeffs.row(d).dot(bPow);
169 temp(d)=sfCoeffsVector[n].template block<1,degree>(d,1).dot(bPow.template segment<degree>(1));
170 }
171 return temp;
172 }
173
174 /**********************************************************************/
175 static Eigen::Matrix<double,dim,dim> get_FL(const Simplex<dim,dim>& s)
176 {
177 Eigen::Matrix<double,dim,dim> temp;
178
180 last[0]=s.xID(dim); // a 1x1 matrix
181
183 for (int k=0;k<dim;++k)
184 {
186 current[0]=s.xID(k); // a 1x1 matrix
187 temp.col(k) << s.mesh->template simplexFactory<0>().getRef(current).P0 - s.mesh->template simplexFactory<0>().getRef(last).P0;
188 }
189 return temp;
190 }
191
192
193 public:
194
195
196 static const Eigen::Matrix<int ,CombinationWithRepetition<_dim+1,degree>::value,_dim+1> baryStarsAndBars;
197 static const Eigen::Matrix<double,CombinationWithRepetition<_dim+1,degree>::value,_dim+1> baryNodalCoordinates;
198 static const std::vector<Eigen::Matrix<double,_dim+1,degree+1>> sfCoeffsVector;
199
202
204 Eigen::Matrix<double,_dim,nodesPerElement> Xe; // this should be private
205
206
207 /**********************************************************************/
209 std::deque<NodeType>& nodeContainer,
210 std::map<Eigen::Matrix<double,dim,1>, NodeType* const,
212 std::map<size_t,const NodeType* const>&) :
213 /* init list */ simplex(s)
214 {
216
218 last[0]=s.xID(dim); // a 1x1 matrix
219
220 const Eigen::Matrix<double,dim,dim> FL(get_FL(simplex));
221
222
223 for (int n=0;n<nodesPerElement;++n)
224 {
225 // Place nodes linearly
226 const Eigen::Matrix<double,dim,1> P(FL*BarycentricTraits<dim>::l2x(baryNodalCoordinates.row(n))+s.mesh->template simplexFactory<0>().getRef(last).P0);
227
228// typename std::map<Eigen::Matrix<double,dim,1>, NodeType* const, CompareVectorsByComponent<double,dim,float> >::const_iterator nIter(nodeFinder.find(P));
229
230// NodeType* pN;
231
232// if (nIter!=nodeFinder.end())
233// {// A node already exists at P.
234// pN=nIter->second; // grab its pointer.
235// }
236// else
237// {// No nodes exist at P.
238 nodeContainer.emplace_back(P,nodeContainer.size()); // create a new one in nodeContainer
239 NodeType* pN=&*nodeContainer.rbegin(); // grab node pointer
240
241// const bool success(nodeFinder.insert(std::make_pair(P,pN)).second); // insert pointer in nodeFinder
242// assert(success && "NODE NOT INSERTED");
243
244// size_t maxID=0;
245// const double maxVal(baryNodalCoordinates.row(n).maxCoeff(&maxID));
246// if(maxVal==1.0)
247// {
248// mesh2femIDmap.emplace(simplex.vertices()[maxID]->xID(0),pN);
249// }
250
251// }
252
253 this->emplace_back(pN); // add node to this
254
255 Xe.col(n)=P; // insert node poision in matrix Xe
256
257
258
259
260 }
261
262 }
263
264// /**********************************************************************/
265// ~LagrangeElement()
266// {
267// for(int n=0;n<this->size();++n)
268// {
269// int nErased=this->operator[](n)->erase(this);
270// assert(nErased==1);
271// }
272// }
273
274 /**********************************************************************/
275 //template<typename TrialFunctionType>
276 static Eigen::Matrix<double,1,nodesPerElement> sf(const BaryType& bary)
277 {
284 Eigen::Matrix<double,1,nodesPerElement> temp;
285 for(int n=0;n<nodesPerElement;++n)
286 {
287 temp(n)=sfcTimesBary(n,bary).prod();
288 }
289 return temp;
290 }
291
292 /**********************************************************************/
293 template<typename TrialFunctionType>
304
305 /**********************************************************************/
306 static Eigen::Matrix<double,dim+1,nodesPerElement> diff(const BaryType& bary)
307 {
314 Eigen::Matrix<double,dim+1,nodesPerElement> temp(Eigen::Matrix<double,dim+1,nodesPerElement>::Zero());
315 for (int n=0;n<nodesPerElement;++n)
316 {
317 const Eigen::Matrix<double,1,dim+1> temp1(sfcTimesBary(n,bary));
318 const Eigen::Matrix<double,1,dim+1> temp2(sfcTimesBaryDiff(n,bary));
319
320 for(int d=0;d<dim+1;++d)
321 {
322 Eigen::Matrix<double,1,dim+1> temp3(temp1);
323 temp3(d)=temp2(d);
324 temp(d,n)=temp3.prod();
325 }
326 }
327 return temp;
328 }
329
330 /**********************************************************************/
331 static Eigen::Matrix<double,dim,nodesPerElement> gradS(const BaryType& bary)
332 {
339 return BarycentricTraits<dim>::dLdX.transpose()*diff(bary);
340 }
341
342 /**********************************************************************/
343 template<typename TrialFunctionType>
345 {
352 Eigen::Matrix<double,dim,nodesPerElement> temp(Gs(bary).transpose()*gradS(bary));
354 }
355
356
357 /**********************************************************************/
358 template<typename TrialFunctionType>
360 {
364 static_assert(TypeTraits<TrialFunctionType>::nComponents==dim,"SYMMETRIC GRADIENT (DEF) CAN ONLY BE COMPUTED IF nComponents==dim.");
365 Eigen::Matrix<double,dim,nodesPerElement> temp(Gs(bary).transpose()*gradS(bary));
367 }
368
369 /**********************************************************************/
370 const NodeType& node(const size_t& n) const
371 {
374 assert(n<nodesPerElement && "NODE ID EXCEEDS nodesPerElement");
375 return *this->operator[](n);
376 }
377
378 /**********************************************************************/
379 NodeType& node(const size_t& n)
380 {
383 assert(n<nodesPerElement && "NODE ID EXCEEDS nodesPerElement");
384 return *this->operator[](n);
385 }
386
387 /**********************************************************************/
388 Eigen::Matrix<double,dim,1> position(const BaryType& bary) const
389 {
392 return MappingType<ElementType>(*this).position(bary);
393 }
394
395 /**********************************************************************/
396 Eigen::Matrix<double,_dim,_dim> Fs(const BaryType& bary) const
397 {
400 return MappingType<ElementType>(*this).Fs(bary);
401 }
402
403 /**********************************************************************/
404 double absJ(const BaryType& bary) const
405 {
409 return MappingType<ElementType>(*this).absJ(bary);
410 }
411
412 /**********************************************************************/
413 Eigen::Matrix<double,_dim,_dim> Gs(const BaryType& bary) const
414 {
417 return MappingType<ElementType>(*this).Gs(bary);
418 }
419
420 /**********************************************************************/
421 Eigen::Matrix<double,dim,1> jGN(const BaryType& bary, const int& n) const
422 {
423 return MappingType<ElementType>(*this).jGN(bary,n);
424 }
425
426 /**********************************************************************/
427 bool isBoundaryElement() const
428 {
430 return simplex.isBoundarySimplex();
431 }
432
433 /**********************************************************************/
434 std::vector<int> boundaryFaces() const
435 {
437 return simplex.boundaryFaces();
438 }
439
440 };
441
442
443 // Declare static data members
444 template<int dim,int degree, template<typename T> class MappingType>
445 const Eigen::Matrix<int,CombinationWithRepetition<dim+1,degree>::value,dim+1> DiscontinuousLagrangeElement<dim,degree,MappingType>::baryStarsAndBars=StarsAndBars<dim+1,degree>::sAb();
446
447 template<int dim,int degree, template<typename T> class MappingType>
448 const Eigen::Matrix<double,CombinationWithRepetition<dim+1,degree>::value,dim+1> DiscontinuousLagrangeElement<dim,degree,MappingType>::baryNodalCoordinates=DiscontinuousLagrangeElement<dim,degree>::baryStarsAndBars.template cast<double>()/degree;
449
450 template<int dim,int degree, template<typename T> class MappingType>
451 const std::vector<Eigen::Matrix<double,dim+1,degree+1>> DiscontinuousLagrangeElement<dim,degree,MappingType>::sfCoeffsVector=DiscontinuousLagrangeElement<dim,degree,MappingType>::get_sfCoeffsVector();
452
453} // close namespace
454#endif
455
456
457
static const std::vector< Eigen::Matrix< double, _dim+1, degree+1 > > sfCoeffsVector
static Eigen::Matrix< double, dim, nodesPerElement > gradS(const BaryType &bary)
static Eigen::Matrix< double, dim+1, nodesPerElement > diff(const BaryType &bary)
Eigen::Matrix< double, dim, 1 > jGN(const BaryType &bary, const int &n) const
static Eigen::Matrix< double, 1, nodesPerElement > sf(const BaryType &bary)
TypeTraits< TrialFunctionType >::ShapeFunctionDefMatrixType sfmDef(const BaryType &bary) const
Eigen::Matrix< double, _dim, _dim > Gs(const BaryType &bary) const
static const Eigen::Matrix< int,CombinationWithRepetition< _dim+1, degree >::value, _dim+1 > baryStarsAndBars
DiscontinuousLagrangeElement(const Simplex< dim, dim > &s, std::deque< NodeType > &nodeContainer, std::map< Eigen::Matrix< double, dim, 1 >, NodeType *const, CompareVectorsByComponent< double, dim, float > > &, std::map< size_t, const NodeType *const > &)
static const Eigen::Matrix< double, CombinationWithRepetition< _dim+1, degree >::value, _dim+1 > baryNodalCoordinates
double absJ(const BaryType &bary) const
const NodeType & node(const size_t &n) const
Eigen::Matrix< double, _dim, _dim > Fs(const BaryType &bary) const
static TypeTraits< TrialFunctionType >::ShapeFunctionMatrixType sfm(const BaryType &bary)
Eigen::Matrix< double, dim, 1 > position(const BaryType &bary) const
TypeTraits< TrialFunctionType >::ShapeFunctionGradMatrixType sfmGrad(const BaryType &bary) const
Class template that defines the isoparametric coordinate transformation between actual and standared ...
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
int i
vertex temp
int current