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