-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathelement.h
151 lines (123 loc) · 5.61 KB
/
element.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#ifndef element_h
#define element_h
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#include <execution>
#pragma GCC diagnostic pop
#include <eigen3/Eigen/Sparse>
#include <eigen3/Eigen/Dense>
#include "node.h"
/** \class element
\brief Template abstract class, mother class for tetraedrons and facettes.
template parameters are N number of sommits and NPI number of interpolation points. It contains a list of indices to the N nodes of the element, a reference to the full nodes vector, and index refering to the associated material parameters. All indices are zero based, derived class constructor should call zerobasing() if needed. It contains also the vector and matrix weight, Kp, Lp, P related to finite element computations. weight values are not initialized, they have to be set by derived class constructor.
Member function getPtGauss() returns Gauss points.
orientate() is a pure virtual function, it should manipulate indices to orientate positively the element.
*/
template <int N,int NPI>
class element
{
/** constructor */
public:
explicit element(const std::vector<Nodes::Node> &_p_node /**< vector of nodes */,
const int _idx /**< index to params */,
std::initializer_list<int> & _i /**< indices to the nodes */
) : idxPrm(_idx), refNode(_p_node)
{
if(_i.size() == N)
{ ind.assign(_i); }
else
{
std::cout<<"Warning: element constructor is given an init list with size() != N\n";
}
Lp.setZero();
}
/** indices to the nodes */
std::vector<int> ind;
/** index of the material parameters of the element */
int idxPrm;
/** weights hat function of the element */
Eigen::Matrix<double,NPI,1> weight;
/** matrix for integrales */
Eigen::Matrix<double,2*N,2*N> Kp;
/** vector for integrales */
Eigen::Matrix<double,2*N,1> Lp;
/** getter for N */
inline constexpr int getN(void) const { return N; }
/** getter for NPI */
inline constexpr int getNPI(void) const { return NPI; }
/** build matrix P direcly from ep,eq in nodes
* P is block diagonal:
( Epx Epy Epz )
( Eqz Eqy Eqz )
with each block E(p|q)(x|y|z) a N*N diagonal matrix
* see here http://eigen.tuxfamily.org/dox-devel/TopicTemplateKeyword.html for the wierd template syntax
*/
void buildMatP(Eigen::Ref<Eigen::Matrix<double,2*N,3*N>> P /**< [out] block diagonal matrix */)
{
P.setZero();
Eigen::Matrix<double,Nodes::DIM,N,Eigen::RowMajor> tempo;
for (int i = 0; i < N; i++) { tempo.col(i) = getNode(i).ep; }
P.template block<N,N>(0,0).diagonal() = tempo.row(Nodes::IDX_X);
P.template block<N,N>(0,N).diagonal() = tempo.row(Nodes::IDX_Y);
P.template block<N,N>(0,2*N).diagonal() = tempo.row(Nodes::IDX_Z);
for (int i = 0; i < N; i++) { tempo.col(i) = getNode(i).eq; }
P.template block<N,N>(N,0).diagonal() = tempo.row(Nodes::IDX_X);
P.template block<N,N>(N,N).diagonal() = tempo.row(Nodes::IDX_Y);
P.template block<N,N>(N,2*N).diagonal() = tempo.row(Nodes::IDX_Z);
}
/** assemble the big sparse matrix K from tetra or facette inner matrix Kp */
void assemblage_mat(const int NOD /**< [in] nb nodes */,
std::vector<Eigen::Triplet<double>> &K /**< [out] COO matrix */ ) const
{
for (int i = 0; i < N; i++)
{
int i_ = ind[i];
for (int j = 0; j < N; j++)
{
int j_ = ind[j];
if(Kp(i,j) != 0) K.emplace_back( NOD + i_, j_, Kp(i,j) );
if (Kp(i,N + j) != 0) K.emplace_back( NOD + i_, NOD + j_, Kp(i,N + j) );
if (Kp(N + i,j) != 0) K.emplace_back( i_, j_, Kp(N + i,j) );
if (Kp(N + i,N + j) != 0) K.emplace_back( i_, NOD + j_, Kp(N + i,N + j) );
}
}
}
/** assemble the big vector L from tetra or facette inner vector Lp */
void assemblage_vect(const int NOD /**< [in] nb nodes */,
Eigen::Ref<Eigen::VectorXd> L /**< [out] vector */) const
{
for (int i = 0; i < N; i++)
{
const int i_ = ind[i];
if(Lp[i] != 0)
{ L(NOD + i_) += Lp[i]; }
if(Lp[N+i] != 0)
{ L(i_) += Lp[N + i]; }
}
}
/** info: print node indices of the element and the vector index of the associated param */
void infos() const
{
std::cout << "idxPrm: " << idxPrm << " ind: {";
for(unsigned int i = 0; i < N-1; i++)
{ std::cout << ind[i] << ": " << refNode[ind[i]].p << std::endl; }
std::cout << ind[N-1] <<": " << refNode[ind[N-1]].p << "}\n";
};
/** computes Gauss point of the element, return in result */
virtual void getPtGauss(Eigen::Ref<Eigen::Matrix<double,Nodes::DIM,NPI>> result) const = 0;
protected:
/** returns reference to node at ind[i] from mesh node vector */
inline const Nodes::Node & getNode(const int i) const { return refNode[ind[i]]; }
/** returns true if mesh node vector is not empty */
inline bool existNodes(void)
{ return (refNode.size() > 0); }
/** zeroBasing: index convention Matlab/msh (one based) -> C++ (zero based) */
inline void zeroBasing(void)
{ std::for_each(ind.begin(),ind.end(),[](int & _i){ _i--; } ); }
private:
/** vector of nodes */
const std::vector<Nodes::Node> & refNode;
/** a method to orientate the element */
virtual void orientate() = 0;
};
#endif