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: Mike Taylor, Antonio Recuero
13 // =============================================================================
14 
15 #include "chrono/fea/ChNodeFEAxyzDDD.h"
16 
17 namespace chrono {
18 namespace fea {
19 
ChNodeFEAxyzDDD(ChVector<> initial_pos,ChVector<> initial_dir_u,ChVector<> initial_dir_v,ChVector<> initial_dir_w)20 ChNodeFEAxyzDDD::ChNodeFEAxyzDDD(ChVector<> initial_pos, ChVector<> initial_dir_u, ChVector<> initial_dir_v, ChVector<> initial_dir_w)
21     : ChNodeFEAxyzDD(initial_pos, initial_dir_u, initial_dir_v), DDD(initial_dir_w), DDD_dt(VNULL), DDD_dtdt(VNULL) {
22     variables_DDD = new ChVariablesGenericDiagonalMass(3);
23     // default: no atomic mass associated to fea node, the fea element will add mass matrix
24     variables_DDD->GetMassDiagonal().setZero();
25 }
26 
ChNodeFEAxyzDDD(const ChNodeFEAxyzDDD & other)27 ChNodeFEAxyzDDD::ChNodeFEAxyzDDD(const ChNodeFEAxyzDDD& other) : ChNodeFEAxyzDD(other) {
28     variables_DDD = new ChVariablesGenericDiagonalMass(3);
29     (*variables_DDD) = (*other.variables_DDD);
30     DDD = other.DDD;
31     DDD_dt = other.DDD_dt;
32     DDD_dtdt = other.DDD_dtdt;
33 }
34 
~ChNodeFEAxyzDDD()35 ChNodeFEAxyzDDD::~ChNodeFEAxyzDDD() {
36     delete variables_DDD;
37 }
38 
39 // -----------------------------------------------------------------------------
40 
operator =(const ChNodeFEAxyzDDD & other)41 ChNodeFEAxyzDDD& ChNodeFEAxyzDDD::operator=(const ChNodeFEAxyzDDD& other) {
42     if (&other == this)
43         return *this;
44 
45     ChNodeFEAxyzDD::operator=(other);
46 
47     DDD = other.DDD;
48     DDD_dt = other.DDD_dt;
49     DDD_dtdt = other.DDD_dtdt;
50     (*variables_DDD) = (*other.variables_DDD);
51     return *this;
52 }
53 
54 // -----------------------------------------------------------------------------
55 
SetNoSpeedNoAcceleration()56 void ChNodeFEAxyzDDD::SetNoSpeedNoAcceleration() {
57     ChNodeFEAxyzDD::SetNoSpeedNoAcceleration();
58 
59     DDD_dt = VNULL;
60     DDD_dtdt = VNULL;
61 }
62 
SetFixed(bool mev)63 void ChNodeFEAxyzDDD::SetFixed(bool mev) {
64     ChNodeFEAxyzDD::SetFixed(mev);
65     variables_DDD->SetDisabled(mev);
66 }
67 
68 // -----------------------------------------------------------------------------
69 
NodeIntStateGather(const unsigned int off_x,ChState & x,const unsigned int off_v,ChStateDelta & v,double & T)70 void ChNodeFEAxyzDDD::NodeIntStateGather(const unsigned int off_x,
71                                         ChState& x,
72                                         const unsigned int off_v,
73                                         ChStateDelta& v,
74                                         double& T) {
75     x.segment(off_x + 0, 3) = pos.eigen();
76     x.segment(off_x + 3, 3) = D.eigen();
77     x.segment(off_x + 6, 3) = DD.eigen();
78 	x.segment(off_x + 9, 3) = DDD.eigen();
79 
80     v.segment(off_v + 0, 3) = pos_dt.eigen();
81     v.segment(off_v + 3, 3) = D_dt.eigen();
82     v.segment(off_v + 6, 3) = DD_dt.eigen();
83 	v.segment(off_v + 9, 3) = DDD_dt.eigen();
84 }
85 
NodeIntStateScatter(const unsigned int off_x,const ChState & x,const unsigned int off_v,const ChStateDelta & v,const double T)86 void ChNodeFEAxyzDDD::NodeIntStateScatter(const unsigned int off_x,
87                                          const ChState& x,
88                                          const unsigned int off_v,
89                                          const ChStateDelta& v,
90                                          const double T) {
91     SetPos(x.segment(off_x, 3));
92     SetD(x.segment(off_x + 3, 3));
93     SetDD(x.segment(off_x + 6, 3));
94 	SetDDD(x.segment(off_x + 9, 3));
95 
96     SetPos_dt(v.segment(off_v, 3));
97     SetD_dt(v.segment(off_v + 3, 3));
98     SetDD_dt(v.segment(off_v + 6, 3));
99 	SetDDD_dt(v.segment(off_v + 9, 3));
100 }
101 
NodeIntStateGatherAcceleration(const unsigned int off_a,ChStateDelta & a)102 void ChNodeFEAxyzDDD::NodeIntStateGatherAcceleration(const unsigned int off_a, ChStateDelta& a) {
103     a.segment(off_a + 0, 3) = pos_dtdt.eigen();
104     a.segment(off_a + 3, 3) = D_dtdt.eigen();
105     a.segment(off_a + 6, 3) = DD_dtdt.eigen();
106 	a.segment(off_a + 9, 3) = DDD_dtdt.eigen();
107 }
108 
NodeIntStateScatterAcceleration(const unsigned int off_a,const ChStateDelta & a)109 void ChNodeFEAxyzDDD::NodeIntStateScatterAcceleration(const unsigned int off_a, const ChStateDelta& a) {
110     SetPos_dtdt(a.segment(off_a, 3));
111     SetD_dtdt(a.segment(off_a + 3, 3));
112     SetDD_dtdt(a.segment(off_a + 6, 3));
113 	SetDDD_dtdt(a.segment(off_a + 9, 3));
114 }
115 
NodeIntStateIncrement(const unsigned int off_x,ChState & x_new,const ChState & x,const unsigned int off_v,const ChStateDelta & Dv)116 void ChNodeFEAxyzDDD::NodeIntStateIncrement(const unsigned int off_x,
117                                            ChState& x_new,
118                                            const ChState& x,
119                                            const unsigned int off_v,
120                                            const ChStateDelta& Dv) {
121     x_new(off_x + 0) = x(off_x + 0) + Dv(off_v + 0);
122     x_new(off_x + 1) = x(off_x + 1) + Dv(off_v + 1);
123     x_new(off_x + 2) = x(off_x + 2) + Dv(off_v + 2);
124     x_new(off_x + 3) = x(off_x + 3) + Dv(off_v + 3);
125     x_new(off_x + 4) = x(off_x + 4) + Dv(off_v + 4);
126     x_new(off_x + 5) = x(off_x + 5) + Dv(off_v + 5);
127     x_new(off_x + 6) = x(off_x + 6) + Dv(off_v + 6);
128     x_new(off_x + 7) = x(off_x + 7) + Dv(off_v + 7);
129     x_new(off_x + 8) = x(off_x + 8) + Dv(off_v + 8);
130 	x_new(off_x + 9) = x(off_x + 9) + Dv(off_v + 9);
131 	x_new(off_x + 10) = x(off_x + 10) + Dv(off_v + 10);
132 	x_new(off_x + 11) = x(off_x + 11) + Dv(off_v + 11);
133 }
134 
NodeIntLoadResidual_F(const unsigned int off,ChVectorDynamic<> & R,const double c)135 void ChNodeFEAxyzDDD::NodeIntLoadResidual_F(const unsigned int off, ChVectorDynamic<>& R, const double c) {
136     R.segment(off + 0, 3) += c * Force.eigen();
137     R.segment(off + 3, 3).setZero();  // TODO something about applied nodal torque..
138     R.segment(off + 6, 3).setZero();  // TODO something about applied nodal torque..
139 	R.segment(off + 9, 3).setZero();  // TODO something about applied nodal torque..
140 }
141 
NodeIntLoadResidual_Mv(const unsigned int off,ChVectorDynamic<> & R,const ChVectorDynamic<> & w,const double c)142 void ChNodeFEAxyzDDD::NodeIntLoadResidual_Mv(const unsigned int off,
143                                             ChVectorDynamic<>& R,
144                                             const ChVectorDynamic<>& w,
145                                             const double c) {
146     R(off + 0) += c * GetMass() * w(off + 0);
147     R(off + 1) += c * GetMass() * w(off + 1);
148     R(off + 2) += c * GetMass() * w(off + 2);
149     R(off + 3) += c * GetMassDiagonal()(0) * w(off + 3);  // unuseful? mass for D isalways zero..
150     R(off + 4) += c * GetMassDiagonal()(1) * w(off + 4);
151     R(off + 5) += c * GetMassDiagonal()(2) * w(off + 5);
152     R(off + 6) += c * GetMassDiagonalDD()(0) * w(off + 6);
153     R(off + 7) += c * GetMassDiagonalDD()(1) * w(off + 7);
154     R(off + 8) += c * GetMassDiagonalDD()(2) * w(off + 8);
155     R(off + 9) += c * GetMassDiagonalDDD()(0) * w(off + 9);
156     R(off + 10) += c * GetMassDiagonalDDD()(1) * w(off + 10);
157     R(off + 11) += c * GetMassDiagonalDDD()(2) * w(off + 11);
158 }
159 
NodeIntToDescriptor(const unsigned int off_v,const ChStateDelta & v,const ChVectorDynamic<> & R)160 void ChNodeFEAxyzDDD::NodeIntToDescriptor(const unsigned int off_v, const ChStateDelta& v, const ChVectorDynamic<>& R) {
161     ChNodeFEAxyzDD::NodeIntToDescriptor(off_v, v, R);
162     variables_DDD->Get_qb().segment(0, 3) = v.segment(off_v + 9, 3);
163     variables_DDD->Get_fb().segment(0, 3) = R.segment(off_v + 9, 3);
164 }
165 
NodeIntFromDescriptor(const unsigned int off_v,ChStateDelta & v)166 void ChNodeFEAxyzDDD::NodeIntFromDescriptor(const unsigned int off_v, ChStateDelta& v) {
167     ChNodeFEAxyzDD::NodeIntFromDescriptor(off_v, v);
168     v.segment(off_v + 9, 3) = variables_DDD->Get_qb().segment(0, 3);
169 }
170 
171 // -----------------------------------------------------------------------------
172 
InjectVariables(ChSystemDescriptor & mdescriptor)173 void ChNodeFEAxyzDDD::InjectVariables(ChSystemDescriptor& mdescriptor) {
174     ChNodeFEAxyzDD::InjectVariables(mdescriptor);
175     mdescriptor.InsertVariables(variables_DDD);
176 }
177 
VariablesFbReset()178 void ChNodeFEAxyzDDD::VariablesFbReset() {
179     ChNodeFEAxyzDD::VariablesFbReset();
180     variables_DDD->Get_fb().setZero();
181 }
182 
VariablesFbLoadForces(double factor)183 void ChNodeFEAxyzDDD::VariablesFbLoadForces(double factor) {
184     ChNodeFEAxyzDD::VariablesFbLoadForces(factor);
185     ////variables_D->Get_fb().segment(3, 3) += VNULL.eigen();  // TODO something related to inertia?
186 }
187 
VariablesQbLoadSpeed()188 void ChNodeFEAxyzDDD::VariablesQbLoadSpeed() {
189     ChNodeFEAxyzDD::VariablesQbLoadSpeed();
190     variables_DDD->Get_qb().segment(0,3) = DDD_dt.eigen();
191 }
192 
VariablesQbSetSpeed(double step)193 void ChNodeFEAxyzDDD::VariablesQbSetSpeed(double step) {
194     ChNodeFEAxyzDD::VariablesQbSetSpeed(step);
195 
196     ChVector<> oldDDD_dt = DDD_dt;
197     SetDDD_dt(variables_DDD->Get_qb().segment(0, 3));
198     if (step) {
199         SetDDD_dtdt((DDD_dt - oldDDD_dt) / step);
200     }
201 }
202 
VariablesFbIncrementMq()203 void ChNodeFEAxyzDDD::VariablesFbIncrementMq() {
204     ChNodeFEAxyzDD::VariablesFbIncrementMq();
205     variables_DDD->Compute_inc_Mb_v(variables_DDD->Get_fb(), variables_DDD->Get_qb());
206 }
207 
VariablesQbIncrementPosition(double step)208 void ChNodeFEAxyzDDD::VariablesQbIncrementPosition(double step) {
209     ChNodeFEAxyzDD::VariablesQbIncrementPosition(step);
210 
211     ChVector<> newspeed_DDD(variables_DDD->Get_qb().segment(0, 3));
212 
213     // ADVANCE POSITION: pos' = pos + dt * vel
214     SetDDD(GetDDD() + newspeed_DDD * step);
215 }
216 
217 // -----------------------------------------------------------------------------
218 
ComputeNF(const double U,const double V,const double W,ChVectorDynamic<> & Qi,double & detJ,const ChVectorDynamic<> & F,ChVectorDynamic<> * state_x,ChVectorDynamic<> * state_w)219 void ChNodeFEAxyzDDD::ComputeNF(
220     const double U,              ///< x coordinate of application point in absolute space
221     const double V,              ///< y coordinate of application point in absolute space
222     const double W,              ///< z coordinate of application point in absolute space
223     ChVectorDynamic<>& Qi,       ///< Return result of N'*F  here, maybe with offset block_offset
224     double& detJ,                ///< Return det[J] here
225     const ChVectorDynamic<>& F,  ///< Input F vector, containing Force xyz in absolute coords and a 'pseudo' torque.
226     ChVectorDynamic<>* state_x,  ///< if != 0, update state (pos. part) to this, then evaluate Q
227     ChVectorDynamic<>* state_w   ///< if != 0, update state (speed part) to this, then evaluate Q
228     ) {
229     // ChVector<> abs_pos(U,V,W); not needed, nodes has no torque. Assuming load is applied to node center
230     Qi.segment(0, 6) = F.segment(0, 6);  // [absF ; absPseudoTorque]
231     detJ = 1;  // not needed because not used in quadrature.
232 }
233 
234 // -----------------------------------------------------------------------------
235 
ArchiveOUT(ChArchiveOut & marchive)236 void ChNodeFEAxyzDDD::ArchiveOUT(ChArchiveOut& marchive) {
237     // version number
238     marchive.VersionWrite<ChNodeFEAxyzDD>();
239     // serialize parent class
240     ChNodeFEAxyzDD::ArchiveOUT(marchive);
241     // serialize all member data:
242     marchive << CHNVP(DDD);
243     marchive << CHNVP(DDD_dt);
244     marchive << CHNVP(DDD_dtdt);
245 }
246 
ArchiveIN(ChArchiveIn & marchive)247 void ChNodeFEAxyzDDD::ArchiveIN(ChArchiveIn& marchive) {
248     // version number
249     /*int version = */ marchive.VersionRead<ChNodeFEAxyzDDD>();
250     // deserialize parent class
251     ChNodeFEAxyzDD::ArchiveIN(marchive);
252     // stream in all member data:
253     marchive >> CHNVP(DDD);
254     marchive >> CHNVP(DDD_dt);
255     marchive >> CHNVP(DDD_dtdt);
256 }
257 
258 }  // end namespace fea
259 }  // end namespace chrono
260