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