1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2014 projectchrono.org
5 // All rights reserved.
6 //
7 // Use of this source code is governed by a BSD-style license that can be found
8 // in the LICENSE file at the top level of the distribution and at
9 // http://projectchrono.org/license-chrono.txt.
10 //
11 // =============================================================================
12 // Authors: Alessandro Tasora, Radu Serban
13 // =============================================================================
14
15 //#define BEAM_VERBOSE
16 #include "chrono/core/ChQuadrature.h"
17 #include "chrono/fea/ChElementBeamTaperedTimoshenkoFPM.h"
18
19 namespace chrono {
20 namespace fea {
ChElementBeamTaperedTimoshenkoFPM()21 ChElementBeamTaperedTimoshenkoFPM::ChElementBeamTaperedTimoshenkoFPM() : guass_order(4) {
22 q_refrotA = QUNIT;
23 q_refrotB = QUNIT;
24 q_element_abs_rot = QUNIT;
25 q_element_ref_rot = QUNIT;
26 force_symmetric_stiffness = false;
27 disable_corotate = false;
28 use_geometric_stiffness = true;
29 use_Rc = true;
30 use_Rs = true;
31
32 nodes.resize(2);
33
34 Km.setZero(this->GetNdofs(), this->GetNdofs());
35 Kg.setZero(this->GetNdofs(), this->GetNdofs());
36 M.setZero(this->GetNdofs(), this->GetNdofs());
37 Rm.setZero(this->GetNdofs(), this->GetNdofs());
38 Ri.setZero(this->GetNdofs(), this->GetNdofs());
39 Ki.setZero(this->GetNdofs(), this->GetNdofs());
40
41 T.setZero(this->GetNdofs(), this->GetNdofs());
42 Rs.setIdentity(6, 6);
43 Rc.setIdentity(6, 6);
44 }
45
ShapeFunctionsTimoshenkoFPM(ShapeFunctionGroupFPM & NB,double eta)46 void ChElementBeamTaperedTimoshenkoFPM::ShapeFunctionsTimoshenkoFPM(ShapeFunctionGroupFPM& NB, double eta) {
47 // The shape functions have referenced two papers below, especially the first one:
48 // Alexander R.Stäblein,and Morten H.Hansen.
49 // "Timoshenko beam element with anisotropic cross-sectional properties."
50 // ECCOMAS Congress 2016, VII European Congress on Computational Methods in Applied Sciences and Engineering.
51 // Crete Island, Greece, 5 - 10 June 2016
52 //
53 // Taeseong Kim, Anders M.Hansen,and Kim Branner.
54 // "Development of an anisotropic beam finite element for composite wind turbine blades in multibody system."
55 // Renewable Energy 59(2013) : 172 - 183.
56
57 // eta = 2 * x/L;
58 // x = (-L/2, L/2), hence eta = (-1, 1)
59 double L = this->length;
60 double LL = L * L;
61 double LLL = LL * L;
62 double eta1 = (eta + 1) / 2.0;
63 double eta2 = eta1 * eta1;
64 double eta3 = eta2 * eta1;
65
66 ChMatrixNM<double, 6, 14> Ax;
67 Ax.setZero();
68 ChMatrixNM<double, 6, 14> dAx;
69 dAx.setZero();
70 ChMatrixNM<double, 14, 14> Ex;
71 Ex.setZero();
72 ChMatrixNM<double, 14, 14> Ex_inv;
73 Ex_inv.setZero();
74 ChMatrixNM<double, 6, 12> Nx;
75 Nx.setZero();
76 ChMatrixNM<double, 6, 12> dNx;
77 dNx.setZero();
78
79 // The coefficient matrix of the displacements and rotations with respect to the shape function coefficient vector
80 // c_v note: the shape function coefficient vector is as below: c_v = [c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c13 c14 c11
81 // c12].'; // notice the order of c11 c12 c13 c14
82 Ax.row(0) << L * eta1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
83 Ax.row(1) << 0, 0, LLL * eta3, LL * eta2, L * eta1, 1, 0, 0, 0, 0, 0, 0, 0, 0;
84 Ax.row(2) << 0, 0, 0, 0, 0, 0, LLL * eta3, LL * eta2, L * eta1, 1, 0, 0, 0, 0;
85 Ax.row(3) << 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L * eta1, 1;
86 Ax.row(4) << 0, 0, 0, 0, 0, 0, -3 * LL * eta2, -2 * L * eta1, -1, 0, 1, 0, 0, 0;
87 Ax.row(5) << 0, 0, 3 * LL * eta2, 2 * L * eta1, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0;
88
89 // The derivative of Ax
90 dAx.row(0) << 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
91 dAx.row(1) << 0, 0, 3 * LL * eta2, 2 * L * eta1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0;
92 dAx.row(2) << 0, 0, 0, 0, 0, 0, 3 * LL * eta2, 2 * L * eta1, 1, 0, 0, 0, 0, 0;
93 dAx.row(3) << 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0;
94 dAx.row(4) << 0, 0, 0, 0, 0, 0, -6 * L * eta1, -2, 0, 0, 0, 0, 0, 0;
95 dAx.row(5) << 0, 0, 6 * L * eta1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
96
97 // A temporary transformation matrix
98 ChMatrixNM<double, 14, 12> Ttemp;
99 Ttemp.setZero();
100 Ttemp.block<12, 12>(2, 0).setIdentity();
101
102 // the cross-sectional material stiffness matrix Klaw along beam element may be variant
103 // due to different Klaw at two ends of tapered-sectional beam
104 ChMatrixNM<double, 6, 6> Klaw_point = this->tapered_section_fpm->GetKlawAtPoint(eta);
105 // double k11 = Klaw_point(0, 0);
106 double k12 = Klaw_point(0, 1);
107 double k13 = Klaw_point(0, 2);
108 // double k14 = Klaw_point(0, 3);
109 // double k15 = Klaw_point(0, 4);
110 // double k16 = Klaw_point(0, 5);
111 double k22 = Klaw_point(1, 1);
112 double k23 = Klaw_point(1, 2);
113 double k24 = Klaw_point(1, 3);
114 double k25 = Klaw_point(1, 4);
115 double k26 = Klaw_point(1, 5);
116 double k33 = Klaw_point(2, 2);
117 double k34 = Klaw_point(2, 3);
118 double k35 = Klaw_point(2, 4);
119 double k36 = Klaw_point(2, 5);
120 // double k44 = Klaw_point(3, 3);
121 // double k45 = Klaw_point(3, 4);
122 // double k46 = Klaw_point(3, 5);
123 double k55 = Klaw_point(4, 4);
124 double k56 = Klaw_point(4, 5);
125 double k66 = Klaw_point(5, 5);
126
127 // The coefficient matrix of the equilibrium and compatibility equations
128 // with respect to the shape function coefficient vector c_v
129 Ex.row(0) << -k13, 0, 6 * k56 - 3 * L * k36 - 3 * L * eta * k36, -2 * k36, 0, 0,
130 3 * L * k35 - 6 * k55 + 3 * L * eta * k35, 2 * k35, 0, 0, -k33, -k23, -k34, 0;
131 Ex.row(1) << k12, 0, 6 * k66 + 3 * L * k26 + 3 * L * eta * k26, 2 * k26, 0, 0,
132 -6 * k56 - 3 * L * k25 - 3 * L * eta * k25, -2 * k25, 0, 0, k23, k22, k24, 0;
133 Ex.row(2) << 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
134 Ex.row(3) << 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0;
135 Ex.row(4) << 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0;
136 Ex.row(5) << 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1;
137 Ex.row(6) << 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0;
138 Ex.row(7) << 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0;
139 Ex.row(8) << L, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
140 Ex.row(9) << 0, 0, LLL, LL, L, 1, 0, 0, 0, 0, 0, 0, 0, 0;
141 Ex.row(10) << 0, 0, 0, 0, 0, 0, LLL, LL, L, 1, 0, 0, 0, 0;
142 Ex.row(11) << 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L, 1;
143 Ex.row(12) << 0, 0, 0, 0, 0, 0, -3 * LL, -2 * L, -1, 0, 1, 0, 0, 0;
144 Ex.row(13) << 0, 0, 3 * LL, 2 * L, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0;
145
146 // The inverse of Ex
147 Ex_inv = Ex.inverse();
148
149 // The shape function matrix at dimensionless position eta
150 Nx = Ax * Ex_inv * Ttemp;
151 // and its derivative
152 dNx = dAx * Ex_inv * Ttemp; // DO NOT add Ax * dEx_inv * Ttemp, see the first paper please.
153
154 // A temporary matrix
155 ChMatrixNM<double, 6, 6> TNtemp;
156 TNtemp.setZero();
157 TNtemp(1, 5) = -1.0;
158 TNtemp(2, 4) = 1.0;
159
160 // The strain displacement matrix at dimensionless position eta
161 ChMatrixNM<double, 6, 12> Bx = dNx + TNtemp * Nx;
162
163 // return result
164 NB = std::make_tuple(Nx, Bx);
165 }
166
167 /// This class defines the calculations for the Guass integrand of
168 /// the cross-sectional stiffness/damping/mass matrices
169 class BeamTaperedTimoshenkoFPM : public ChIntegrable1D<ChMatrixNM<double, 12, 12>> {
170 public:
BeamTaperedTimoshenkoFPM(ChElementBeamTaperedTimoshenkoFPM * element,const int option)171 BeamTaperedTimoshenkoFPM(ChElementBeamTaperedTimoshenkoFPM* element, const int option)
172 : m_element(element), m_choice_KiRiMi(option) {}
~BeamTaperedTimoshenkoFPM()173 ~BeamTaperedTimoshenkoFPM() {}
174
175 // Which one matrix is evaluated? stiffness/damping/mass matrices
176 // - 0: stiffness matrix
177 // - 1: damping matrix
178 // - 2: mass matix
SetChoiceKiRiMi(int mv)179 void SetChoiceKiRiMi(int mv) { m_choice_KiRiMi = mv; }
GetChoiceKiRiMi()180 int GetChoiceKiRiMi() { return m_choice_KiRiMi; }
181
182 private:
183 ChElementBeamTaperedTimoshenkoFPM* m_element;
184 // 0: stiffness matrix
185 // 1: damping matrix
186 // 2: mass matix
187 int m_choice_KiRiMi = 0;
188
189 virtual void Evaluate(ChMatrixNM<double, 12, 12>& result, const double x) override;
190 };
191
Evaluate(ChMatrixNM<double,12,12> & result,const double x)192 void BeamTaperedTimoshenkoFPM::Evaluate(ChMatrixNM<double, 12, 12>& result, const double x) {
193 double eta = x;
194
195 ChElementBeamTaperedTimoshenkoFPM::ShapeFunctionGroupFPM NxBx;
196 m_element->ShapeFunctionsTimoshenkoFPM(NxBx, eta);
197 // shape function matrix
198 ChMatrixNM<double, 6, 12> Nx = std::get<0>(NxBx);
199 // strain-displacement relation matrix
200 ChMatrixNM<double, 6, 12> Bx = std::get<1>(NxBx);
201
202 auto tapered_section_fpm = m_element->GetTaperedSection();
203 ChMatrixNM<double, 6, 6> Klaw_point;
204 ChMatrixNM<double, 6, 6> Rlaw_point;
205 ChMatrixNM<double, 6, 6> Mlaw_point;
206
207 switch (m_choice_KiRiMi) {
208 case 0:
209 Klaw_point = tapered_section_fpm->GetKlawAtPoint(eta);
210 result = Bx.transpose() * Klaw_point * Bx;
211 break;
212 case 1:
213 Rlaw_point = tapered_section_fpm->GetRlawAtPoint(eta);
214 result = Bx.transpose() * Rlaw_point * Bx; // modified Rayleigh damping model
215 break;
216 case 2:
217 Mlaw_point = tapered_section_fpm->GetMlawAtPoint(eta);
218 result = Nx.transpose() * Mlaw_point * Nx;
219 break;
220 default:
221 std::cout << "Please input the correct option: 0,1,2" << std::endl;
222 return;
223 }
224 };
225
ComputeStiffnessMatrix()226 void ChElementBeamTaperedTimoshenkoFPM::ComputeStiffnessMatrix() {
227 // Calculate the local element stiffness matrix via Guass integration
228 this->Km.setZero();
229 BeamTaperedTimoshenkoFPM myformula(this, 0); // 0: stiffness matrix
230 ChMatrixNM<double, 12, 12> TempStiffnessMatrix;
231 TempStiffnessMatrix.setZero();
232 ChQuadrature::Integrate1D<ChMatrixNM<double, 12, 12>>(TempStiffnessMatrix, // result of integration will go there
233 myformula, // formula to integrate
234 -1, 1, // x limits
235 guass_order // order of integration
236 );
237 // eta = 2*x/L;
238 // ---> Deta/dx = 2./L;
239 // ---> detJ = dx/Deta = L/2.;
240 TempStiffnessMatrix *= this->length / 2.0; // need to multiple detJ
241 this->Km = this->T.transpose() * TempStiffnessMatrix * this->T;
242 }
243
ComputeDampingMatrix()244 void ChElementBeamTaperedTimoshenkoFPM::ComputeDampingMatrix() {
245 // Calculate the local element damping matrix via Guass integration
246 this->Rm.setZero();
247 BeamTaperedTimoshenkoFPM myformula(this, 1); // 1: damping matrix
248 ChMatrixNM<double, 12, 12> TempDampingMatrix;
249 TempDampingMatrix.setZero();
250 ChQuadrature::Integrate1D<ChMatrixNM<double, 12, 12>>(TempDampingMatrix, // result of integration will go there
251 myformula, // formula to integrate
252 -1, 1, // x limits
253 guass_order // order of integration
254 );
255 // eta = 2*x/L;
256 // ---> Deta/dx = 2./L;
257 // ---> detJ = dx/Deta = L/2.;
258 TempDampingMatrix *= this->length / 2.0; // need to multiple detJ
259 this->Rm = this->T.transpose() * TempDampingMatrix * this->T;
260
261 // The mass-proportional term
262 double rdamping_alpha = this->tapered_section->GetAverageSectionParameters()->rdamping_coeff.alpha;
263 if (this->tapered_section->GetLumpedMassMatrixType()) {
264 double node_multiplier_fact = 0.5 * this->length;
265 Rm += rdamping_alpha * this->M * node_multiplier_fact;
266 } else {
267 Rm += rdamping_alpha * this->M;
268 }
269 }
270
ComputeConsistentMassMatrix()271 void ChElementBeamTaperedTimoshenkoFPM::ComputeConsistentMassMatrix() {
272 // Calculate the local element mass matrix via Guass integration
273 this->M.setZero();
274 BeamTaperedTimoshenkoFPM myformula(this, 2); // 2: mass matrix
275 ChMatrixNM<double, 12, 12> TempMassMatrix;
276 TempMassMatrix.setZero();
277 ChQuadrature::Integrate1D<ChMatrixNM<double, 12, 12>>(TempMassMatrix, // result of integration will go there
278 myformula, // formula to integrate
279 -1, 1, // x limits
280 guass_order // order of integration
281 );
282 // eta = 2*x/L;
283 // ---> Deta/dx = 2./L;
284 // ---> detJ = dx/Deta = L/2.;
285 TempMassMatrix *= this->length / 2.0; // need to multiple detJ
286 this->M = TempMassMatrix;
287 // If the cross-sectional mass properties are given at the mass center,
288 // then it should be transformed to the centerline firstly,
289 // this is handled in the Class ChBeamSectionTimoshenkoAdvancedGenericFPM. NOT HERE.
290 }
291
ComputeMassMatrix()292 void ChElementBeamTaperedTimoshenkoFPM::ComputeMassMatrix() {
293 // Compute local mass matrix of element
294 // It could be lumped or consistent mass matrix, depends on SetLumpedMassMatrix(true/false)
295 if (this->tapered_section_fpm->GetLumpedMassMatrixType()) {
296 // If it is lumped mass matrix, you need to multiple 0.5 * length to obtain the final mass matrix
297 // For consistent mass matrix, don't need to multiple anything.
298 this->tapered_section_fpm->ComputeInertiaMatrix(this->M);
299 } else {
300 // If the consistent mass matrix is used, you need to compute the ave_sec_par firstly.
301 this->tapered_section_fpm->ComputeAverageSectionParameters();
302 ComputeConsistentMassMatrix();
303 }
304 }
305
SetupInitial(ChSystem * system)306 void ChElementBeamTaperedTimoshenkoFPM::SetupInitial(ChSystem* system) {
307 assert(tapered_section_fpm);
308
309 // Compute rest length, mass:
310 this->length = (nodes[1]->GetX0().GetPos() - nodes[0]->GetX0().GetPos()).Length();
311 this->mass = 0.5 * this->length * this->tapered_section_fpm->GetSectionA()->GetMassPerUnitLength() +
312 0.5 * this->length * this->tapered_section_fpm->GetSectionB()->GetMassPerUnitLength();
313
314 // Compute initial rotation
315 ChMatrix33<> A0;
316 ChVector<> mXele = nodes[1]->GetX0().GetPos() - nodes[0]->GetX0().GetPos();
317 ChVector<> myele = nodes[0]->GetX0().GetA().Get_A_Yaxis();
318 A0.Set_A_Xdir(mXele, myele);
319 q_element_ref_rot = A0.Get_A_quaternion();
320
321 // Compute transformation matrix
322 ComputeTransformMatrix();
323
324 // Compute local mass matrix:
325 ComputeMassMatrix();
326
327 // Compute local stiffness matrix:
328 ComputeStiffnessMatrix();
329
330 // Compute local geometric stiffness matrix normalized by pull force P: Kg/P
331 ComputeGeometricStiffnessMatrix();
332
333 // Compute local damping matrix:
334 ComputeDampingMatrix();
335 }
336
EvaluateSectionDisplacement(const double eta,ChVector<> & u_displ,ChVector<> & u_rotaz)337 void ChElementBeamTaperedTimoshenkoFPM::EvaluateSectionDisplacement(const double eta,
338 ChVector<>& u_displ,
339 ChVector<>& u_rotaz) {
340 ChVectorDynamic<> displ(this->GetNdofs());
341 this->GetStateBlock(displ);
342 // No transformation for the displacement of two nodes,
343 // so the section displacement is evaluated at the centerline of beam
344
345 ShapeFunctionGroupFPM NxBx;
346 ShapeFunctionsTimoshenkoFPM(NxBx, eta);
347 // the shape function matrix
348 ChMatrixNM<double, 6, 12> Nx = std::get<0>(NxBx);
349
350 // the displacements and rotations, as a vector
351 ChVectorDynamic<> u_vector = Nx * displ;
352
353 u_displ.x() = u_vector(0);
354 u_displ.y() = u_vector(1);
355 u_displ.z() = u_vector(2);
356 u_rotaz.x() = u_vector(3);
357 u_rotaz.y() = u_vector(4);
358 u_rotaz.z() = u_vector(5);
359 }
360
EvaluateSectionForceTorque(const double eta,ChVector<> & Fforce,ChVector<> & Mtorque)361 void ChElementBeamTaperedTimoshenkoFPM::EvaluateSectionForceTorque(const double eta,
362 ChVector<>& Fforce,
363 ChVector<>& Mtorque) {
364 assert(tapered_section_fpm);
365
366 ChVectorDynamic<> displ(this->GetNdofs());
367 this->GetStateBlock(displ);
368
369 // transform the displacement of two nodes to elastic axis
370 ChVectorDynamic<> displ_ec = this->T * displ;
371
372 ShapeFunctionGroupFPM NxBx;
373 ShapeFunctionsTimoshenkoFPM(NxBx, eta);
374 // the strain displacement matrix B:
375 ChMatrixNM<double, 6, 12> Bx = std::get<1>(NxBx);
376
377 // generalized strains/curvatures;
378 ChVectorN<double, 6> sect_ek = Bx * displ_ec;
379
380 // 6*6 fully populated constitutive matrix of the beam:
381 ChMatrixNM<double, 6, 6> Klaw_d = this->tapered_section_fpm->GetKlawAtPoint(eta);
382
383 ChMatrixDynamic<> Teta;
384 ComputeTransformMatrixAtPoint(Teta, eta);
385
386 // ..unrolled rotated constitutive matrix..
387 ChMatrixNM<double, 6, 6> Klaw_r;
388 Klaw_r.setZero();
389 Klaw_r = Teta.transpose() * Klaw_d;
390
391 // .. compute wrench = Klaw_r * sect_ek
392 ChVectorN<double, 6> wrench = Klaw_r * sect_ek;
393 Fforce = wrench.segment(0, 3);
394 Mtorque = wrench.segment(3, 3);
395 }
396
EvaluateSectionStrain(const double eta,ChVector<> & StrainV_trans,ChVector<> & StrainV_rot)397 void ChElementBeamTaperedTimoshenkoFPM::EvaluateSectionStrain(const double eta,
398 ChVector<>& StrainV_trans,
399 ChVector<>& StrainV_rot) {
400 assert(tapered_section_fpm);
401
402 ChVectorDynamic<> displ(this->GetNdofs());
403 this->GetStateBlock(displ);
404
405 // transform the displacement of two nodes to elastic axis
406 ChVectorDynamic<> displ_ec = this->T * displ;
407
408 ShapeFunctionGroupFPM NxBx;
409 ShapeFunctionsTimoshenkoFPM(NxBx, eta);
410 // the strain displacement matrix B:
411 ChMatrixNM<double, 6, 12> Bx = std::get<1>(NxBx);
412
413 // generalized strains/curvatures;
414 ChVectorN<double, 6> sect_ek = Bx * displ_ec;
415
416 StrainV_trans = sect_ek.segment(0, 3);
417 StrainV_rot = sect_ek.segment(3, 3);
418 }
419
ComputeNF(const double U,ChVectorDynamic<> & Qi,double & detJ,const ChVectorDynamic<> & F,ChVectorDynamic<> * state_x,ChVectorDynamic<> * state_w)420 void ChElementBeamTaperedTimoshenkoFPM::ComputeNF(const double U,
421 ChVectorDynamic<>& Qi,
422 double& detJ,
423 const ChVectorDynamic<>& F,
424 ChVectorDynamic<>* state_x,
425 ChVectorDynamic<>* state_w) {
426 ShapeFunctionGroupFPM NxBx;
427 // the shape function matrix
428 ChMatrixNM<double, 6, 12> Nx;
429
430 double eta = -1;
431 ShapeFunctionsTimoshenkoFPM(NxBx, eta);
432 Nx = std::get<0>(NxBx);
433 Qi.head(6) = Nx.transpose() * F;
434
435 eta = 1;
436 ShapeFunctionsTimoshenkoFPM(NxBx, eta);
437 Nx = std::get<0>(NxBx);
438 Qi.tail(6) = Nx.transpose() * F;
439
440 // eta = 2*x/L;
441 // ---> Deta/dx = 2./L;
442 // ---> detJ = dx/Deta = L/2.;
443 detJ = this->GetRestLength() / 2.0;
444 }
445
ComputeNF(const double U,const double V,const double W,ChVectorDynamic<> & Qi,double & detJ,const ChVectorDynamic<> & F,ChVectorDynamic<> * state_x,ChVectorDynamic<> * state_w)446 void ChElementBeamTaperedTimoshenkoFPM::ComputeNF(const double U,
447 const double V,
448 const double W,
449 ChVectorDynamic<>& Qi,
450 double& detJ,
451 const ChVectorDynamic<>& F,
452 ChVectorDynamic<>* state_x,
453 ChVectorDynamic<>* state_w) {
454 this->ComputeNF(U, Qi, detJ, F, state_x, state_w);
455 detJ /= 4.0; // because volume
456 }
457
458 } // end namespace fea
459 } // end namespace chrono
460