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