G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
gsVisitorNonLinearElasticity.h
Go to the documentation of this file.
1
16#pragma once
17
20
22#include <gsCore/gsFuncData.h>
23
24namespace gismo
25{
26
27template <class T>
28class gsVisitorNonLinearElasticity
29{
30public:
31 gsVisitorNonLinearElasticity(const gsPde<T> & pde_, const gsMultiPatch<T> & displacement_)
32 : pde_ptr(static_cast<const gsBasePde<T>*>(&pde_)),
33 displacement(displacement_) { }
34
35 void initialize(const gsBasisRefs<T> & basisRefs,
36 const index_t patchIndex,
37 const gsOptionList & options,
38 gsQuadRule<T> & rule)
39 {
40 GISMO_UNUSED(patchIndex);
41 // parametric dimension of the first displacement component
42 dim = basisRefs.front().dim();
43 // a quadrature rule is defined by the basis for the first displacement component.
44 rule = gsQuadrature::get(basisRefs.front(), options);
45 // saving necessary info
46 patch = patchIndex;
47 materialLaw = options.getInt("MaterialLaw");
48 T YM = options.getReal("YoungsModulus");
49 T PR = options.getReal("PoissonsRatio");
50 lambda = YM * PR / ( ( 1. + PR ) * ( 1. - 2. * PR ) );
51 mu = YM / ( 2. * ( 1. + PR ) );
52 forceScaling = options.getReal("ForceScaling");
53 localStiffening = options.getReal("LocalStiff");
54 // elasticity tensor
55 I = gsMatrix<T>::Identity(dim,dim);
56 if (materialLaw == 0)
57 {
58 matrixTraceTensor<T>(C,I,I);
59 C *= lambda;
60 symmetricIdentityTensor<T>(Ctemp,I);
61 C += mu*Ctemp;
62 }
63 // resize containers for global indices
64 globalIndices.resize(dim);
65 blockNumbers.resize(dim);
66 }
67
68 inline void evaluate(const gsBasisRefs<T> & basisRefs,
69 const gsGeometry<T> & geo,
70 const gsMatrix<T> & quNodes)
71 {
72 // store quadrature points of the element for geometry evaluation
73 md.points = quNodes;
74 // NEED_VALUE to get points in the physical domain for evaluation of the RHS
75 // NEED_MEASURE to get the Jacobian determinant values for integration
76 // NEED_GRAD_TRANSFORM to get the Jacobian matrix to transform gradient from the parametric to physical domain
78 // Compute image of the quadrature points plus gradient, jacobian and other necessary data
79 geo.computeMap(md);
80 // find local indices of the displacement basis functions active on the element
81 basisRefs.front().active_into(quNodes.col(0),localIndicesDisp);
82 N_D = localIndicesDisp.rows();
83 // Evaluate displacement basis functions and their derivatives on the element
84 basisRefs.front().evalAllDers_into(quNodes,1,basisValuesDisp);
85 // Evaluate right-hand side at the image of the quadrature points
86 pde_ptr->rhs()->eval_into(md.values[0],forceValues);
87 // store quadrature points of the element for displacement evaluation
88 mdDisplacement.points = quNodes;
89 // NEED_DERIV to compute deformation gradient
90 mdDisplacement.flags = NEED_DERIV;
91 // evaluate displacement gradient
92 displacement.patch(patch).computeMap(mdDisplacement);
93 }
94
95 inline void assemble(gsDomainIterator<T> & element,
96 const gsVector<T> & quWeights)
97 {
98 GISMO_UNUSED(element);
99 // initialize local matrix and rhs
100 localMat.setZero(dim*N_D,dim*N_D);
101 localRhs.setZero(dim*N_D,1);
102 // loop over quadrature nodes
103 for (index_t q = 0; q < quWeights.rows(); ++q)
104 {
105 const T weightForce = quWeights[q] * md.measure(q);
106 // Compute physical gradients of basis functions at q as a dim x numActiveFunction matrix
107 transformGradients(md,q,basisValuesDisp[1],physGrad);
108 // physical jacobian of displacemnt du/dx = du/dxi * dxi/dx
109 physDispJac = mdDisplacement.jacobian(q)*(md.jacobian(q).cramerInverse());
110 // deformation gradient F = I + du/dx
111 F = I + physDispJac;
112 // deformation jacobian J = det(F)
113 T J = F.determinant();
114 // Right Cauchy Green strain, C = F'*F
115 RCG = F.transpose() * F;
116 // Green-Lagrange strain, E = 0.5*(C-I), a.k.a. full geometric strain tensor
117 E = 0.5 * (RCG - I);
118 const T weightBody = quWeights[q] * pow(md.measure(q),-1.*localStiffening) * md.measure(q);
119 // Second Piola-Kirchhoff stress tensor
120 if (materialLaw == 0) // Saint Venant-Kirchhoff
121 S = lambda*E.trace()*I + 2*mu*E;
122 if (materialLaw == 1) // neo-Hooke ln(J)
123 {
124 GISMO_ENSURE(J>0,"Invalid configuration: J < 0");
125 RCGinv = RCG.cramerInverse();
126 S = (lambda*log(J)-mu)*RCGinv + mu*I;
127 // elasticity tensor
128 matrixTraceTensor<T>(C,RCGinv,RCGinv);
129 C *= lambda;
130 symmetricIdentityTensor<T>(Ctemp,RCGinv);
131 C += (mu-lambda*log(J))*Ctemp;
132 }
133 if (materialLaw == 2) // quad neo-Hooke
134 {
135 RCGinv = RCG.cramerInverse();
136 S = (lambda*(J*J-1)/2-mu)*RCGinv + mu*I;
137 // elasticity tensor
138 matrixTraceTensor<T>(C,RCGinv,RCGinv);
139 C *= lambda*J*J;
140 symmetricIdentityTensor<T>(Ctemp,RCGinv);
141 C += (mu-lambda*(J*J-1)/2)*Ctemp;
142 }
143 // loop over active basis functions (u_i)
144 for (index_t i = 0; i < N_D; i++)
145 {
146 // Material tangent K_tg_mat = B_i^T * C * B_j;
147 setB<T>(B_i,F,physGrad.col(i));
148 materialTangentTemp = B_i.transpose() * C;
149 // Geometric tangent K_tg_geo = gradB_i^T * S * gradB_j;
150 geometricTangentTemp = S * physGrad.col(i);
151 // loop over active basis functions (v_j)
152 for (index_t j = 0; j < N_D; j++)
153 {
154 setB<T>(B_j,F,physGrad.col(j));
155
156 materialTangent = materialTangentTemp * B_j;
157 T geometricTangent = geometricTangentTemp.transpose() * physGrad.col(j);
158 // K_tg = K_tg_mat + I*K_tg_geo;
159 for (short_t d = 0; d < dim; ++d)
160 materialTangent(d,d) += geometricTangent;
161
162 for (short_t di = 0; di < dim; ++di)
163 for (short_t dj = 0; dj < dim; ++dj)
164 localMat(di*N_D+i, dj*N_D+j) += weightBody * materialTangent(di,dj);
165 }
166 // Second Piola-Kirchhoff stress tensor as vector
167 voigtStress<T>(Svec,S);
168 // rhs = -r = force - B*Svec,
169 localResidual = B_i.transpose() * Svec;
170 for (short_t d = 0; d < dim; d++)
171 localRhs(d*N_D+i) -= weightBody * localResidual(d);
172 }
173 // contribution of volumetric load function to residual/rhs
174 for (short_t d = 0; d < dim; ++d)
175 localRhs.middleRows(d*N_D,N_D).noalias() += weightForce * forceScaling * forceValues(d,q) * basisValuesDisp[0].col(q);
176 }
177 }
178
179 inline void localToGlobal(const int patchIndex,
180 const std::vector<gsMatrix<T> > & eliminatedDofs,
181 gsSparseSystem<T> & system)
182 {
183 // computes global indices for displacement components
184 for (short_t d = 0; d < dim; ++d)
185 {
186 system.mapColIndices(localIndicesDisp, patchIndex, globalIndices[d], d);
187 blockNumbers.at(d) = d;
188 }
189 // push to global system
190 system.pushToRhs(localRhs,globalIndices,blockNumbers);
191 system.pushToMatrix(localMat,globalIndices,eliminatedDofs,blockNumbers,blockNumbers);
192 }
193
194protected:
195 // problem info
196 short_t dim;
197 index_t patch; // current patch
198 const gsBasePde<T> * pde_ptr;
199 index_t materialLaw; // (0: St. Venant-Kirchhoff, 1: ln neo-Hooke, 2: quad neo-Hooke)
200 // Lame coefficients and force scaling factor
201 T lambda, mu, forceScaling;
202 // geometry mapping
203 gsMapData<T> md;
204 // local components of the global linear system
205 gsMatrix<T> localMat;
206 gsMatrix<T> localRhs;
207 // local indices (at the current patch) of the displacement basis functions active at the current element
208 gsMatrix<index_t> localIndicesDisp;
209 // number of displacement basis functions active at the current element
210 index_t N_D;
211 // values and derivatives of displacement basis functions at quadrature points at the current element
212 // values are stored as a N_D x numQuadPoints matrix; not sure about derivatives, must be smth like N_D*dim x numQuadPoints
213 std::vector<gsMatrix<T> > basisValuesDisp;
214 // RHS values at quadrature points at the current element; stored as a dim x numQuadPoints matrix
215 gsMatrix<T> forceValues;
216 // current displacement field
217 const gsMultiPatch<T> & displacement;
218 // evaluation data of the current displacement field
219 gsMapData<T> mdDisplacement;
220
221 // all temporary matrices defined here for efficiency
222 gsMatrix<T> C, Ctemp, physGrad, physDispJac, F, RCG, E, S, RCGinv, B_i, materialTangentTemp, B_j, materialTangent, I;
223 gsVector<T> geometricTangentTemp, Svec, localResidual;
224 T localStiffening;
225 // containers for global indices
226 std::vector< gsMatrix<index_t> > globalIndices;
227 gsVector<index_t> blockNumbers;
228};
229
230} // namespace gismo
IMHO, a useless class, but it is necessary to use the gsAssembler class. Contains proper information ...
#define short_t
Definition gsConfig.h:35
#define index_t
Definition gsConfig.h:32
#define GISMO_UNUSED(x)
Definition gsDebug.h:112
#define GISMO_ENSURE(cond, message)
Definition gsDebug.h:102
This object is a cache for computed values from an evaluator.
Creates a variety of quadrature rules.
Tensor operations for elasticity.
The G+Smo namespace, containing all definitions for the library.
@ NEED_VALUE
Value of the object.
Definition gsForwardDeclarations.h:72
@ NEED_DERIV
Gradient of the object.
Definition gsForwardDeclarations.h:73
@ NEED_GRAD_TRANSFORM
Gradient transformation matrix.
Definition gsForwardDeclarations.h:77
@ NEED_MEASURE
The density of the measure pull back.
Definition gsForwardDeclarations.h:76
static gsQuadRule< T > get(const gsBasis< T > &basis, const gsOptionList &options, short_t fixDir=-1)
Constructs a quadrature rule based on input options.
Definition gsQuadrature.h:51