1 //#**************************************************************
2 //# filename: ANCFBeam3DTorsion.cpp
3 //#
4 //# author: PG & KN
5 //#
6 //# generated: 2012
7 //# description: 3D ANCF beam element with torsion, without shear deformation (BE beam theory)
8 //# comments:
9 //#
10 //# Copyright (c) 2003-2013 Johannes Gerstmayr, Linz Center of Mechatronics GmbH, Austrian
11 //# Center of Competence in Mechatronics GmbH, Institute of Technical Mechanics at the
12 //# Johannes Kepler Universitaet Linz, Austria. All rights reserved.
13 //#
14 //# This file is part of HotInt.
15 //# HotInt is free software: you can redistribute it and/or modify it under the terms of
16 //# the HOTINT license. See folder 'licenses' for more details.
17 //#
18 //# bug reports are welcome!!!
19 //# WWW: www.hotint.org
20 //# email: bug_reports@hotint.org or support@hotint.org
21 //#***************************************************************************************
22
23 #include "body3d.h"
24 #include "femathhelperfunctions.h"
25 #include "material.h"
26 #include "ANCFBeam3Dtorsion.h"
27 #include "Node.h"
28 #include "graphicsconstants.h"
29 #include "elementdataaccess.h"
30 #include "solversettings_auto.h"
31
32
33 //#define OLD_SHAPEFUNCTIONS
34
CalculateElementLength() const35 double ANCFBeam3DTorsion::CalculateElementLength() const
36 {
37 //
38 // calculation of the length:
39 // --------------------------
40 //
41 // length = \int_{-1}^{1} 1/2 |r'_0(x)| dx, where x is in [-1,1] (which is the interval of Gauss points for numerical integration)
42 //
43 //
44 // representation of r'_0(x):
45 // ----------------------------
46 //
47 // by definition, the beam element axis r_0(x) (r_0 is the axis in reference configuration, and x is in [-1,1])
48 // is a cubic spline defined by the nodes a and b, i.e., the nodal positions r_0^a and r_0^b, and the nodal slopes r'_0^a and r'_0^b, respectively.
49 // let us fix the i-th component (in space), then the i-th component of the beam axis is defined by
50 // (r_0(x))_i = a_0 + a_1 x_0 + a_2 x_0^2 + a_3 x_0^3, where the coefficients a_0,..,a_3 are yet unknown.
51 // the coefficients a_0,..,a_3 are found by matching the boundary conditions,
52 // (r_0(-1))_i=(r_0^a)_i, (r_0(1))_i=(r_0^b)_i, (r'_0(-1))_i=(r'_0^a)_i, (r'_0(1))_i=(r'_0^b)_i
53 // which leads to solving the linear system
54 // [ (r_0^a)_i ] [ 1 -1 1 -1 ] [ a_0 ]
55 // [ (r'_0^a)_i ] = [ 0 1 -2 3 ] [ a_1 ]
56 // [ (r_0^b)_i ] [ 1 1 1 1 ] [ a_2 ]
57 // [ (r'_0^b)_i ] [ 0 1 2 3 ] [ a_3 ]
58 // or, in short:
59 // q0_i = \AMat \aVec.
60 // hence, the coefficients read
61 // \aVec = \AInv q0_i, where \AInv = \AMat^{-1},
62 // and we end up with the representation as an inner product
63 // (r'_0(x_0))_i = [ 0 1 2(x_0) 3(x_0)^2] \AInv q0_i (*)
64 //
65
66 double length = 0;
67
68 Vector3D r0a(q0(1),q0(2),q0(3));
69 Vector3D r0b(q0(1+6),q0(2+6),q0(3+6));
70 Vector3D r0a_prime(q0(4),q0(5),q0(6));
71 Vector3D r0b_prime(q0(4+6),q0(5+6),q0(6+6));
72 r0a_prime.Normalize();
73 r0b_prime.Normalize();
74
75 // calculate some geometrical quantities
76 Vector3D vector_AB(r0b-r0a); // vector from node a to node b
77 double distance_AB = vector_AB.Norm(); // distance between node a and node b
78
79 // "full circle" beam elements or elements of length 0 are not allowed
80 assert(distance_AB > 0);
81
82 double alpha = acos((r0a_prime*vector_AB)/distance_AB); // acos returns value between [0,pi]; alpha is angle between vector_AB and slope in node a (which in an arc is equal to the angle between vector_AB and slope in node b) (r0a_prime is already normalized!)
83 double sin_alpha = sin(alpha); // is non-negative, since alpha is non-negative
84
85 if (alpha < 1e-14) // if this is a straight beam element
86 {
87 // keep distance_AB as it is
88 }
89 else if (alpha > MY_PI - 1e-14) // if this is an almost full circle
90 {
91 assert (0 && "full circle beam elements elements are not allowed");
92 }
93 else // general curved beam element
94 {
95 distance_AB *= alpha/sin_alpha; // arc_length = radius * theta, where theta is the angle between the two sekants of the arc; there holds radius = distance_AB / (2*sin(alpha)), and theta = 2*alpha
96 }
97
98 //multiply slopes at nodes with arclength and divide by two, since x is in [-1,1]
99 r0a_prime *= distance_AB/2;
100 r0b_prime *= distance_AB/2;
101
102 // Matrix containing nodal positions and nodal slope vectors of arc-length divided by two (size of interval [-1,1])
103 Matrix Q(4,3);
104
105 // fill columns of Q
106 for (int j=1; j<=3; j++)
107 {
108 Q(1,j)=r0a(j);
109 Q(2,j)=r0a_prime(j);
110 Q(3,j)=r0b(j);
111 Q(4,j)=r0b_prime(j);
112 }
113
114 // first row (would be nr. 0) can be neglected due to multiplication with 0 in representation of (r'_0(x_0))_i (see *)
115 Matrix AInv(3,4);
116 AInv(1,1) = -3;
117 AInv(1,2) = -1;
118 AInv(1,3) = 3;
119 AInv(1,4) = -1;
120 AInv(2,1) = 0;
121 AInv(2,2) = -1;
122 AInv(2,3) = 0;
123 AInv(2,4) = 1;
124 AInv(3,1) = 1;
125 AInv(3,2) = 1;
126 AInv(3,3) = -1;
127 AInv(3,4) = 1;
128
129 static Vector w,x; //integration points and weights
130 GetIntegrationRule(x,w,intorder_axial_strain);
131
132 //loop over all integration points
133 for (int j=1; j<=x.GetLen(); j++)
134 {
135
136 Vector r0_prime_at_xj = Vector(1.,2.*x(j),3.*Sqr(x(j)))*AInv*Q;
137 //mbs->UO() << "r'r0_prime(" << x(j) << ") = " << r0_prime_at_xj << "\n";
138 length += w(j)*r0_prime_at_xj.GetNorm();
139 }
140 length /= 4.; // factor of AInv: 1/4
141
142 return length;
143 }
144
145 // standard set function
SetANCFBeam3DTorsion(const Vector & xc1,const Vector & xc2,const double & theta1,const double & theta2,const Vector3D & director1,const Vector3D & director2,int n1i,int n2i,int materialnumi,const Vector3D & coli,const int do_update_directorsi,const int kinematic_computation_modei)146 void ANCFBeam3DTorsion::SetANCFBeam3DTorsion(const Vector& xc1, const Vector& xc2, const double& theta1, const double& theta2,
147 const Vector3D& director1, const Vector3D& director2, int n1i, int n2i, int materialnumi,
148 const Vector3D& coli, const int do_update_directorsi, const int kinematic_computation_modei)
149 {
150 n1=n1i; n2=n2i;
151
152 x_init.SetLen(2*SOS()); //2*SOS -> add initial conditions for positions and velocities
153 x_init.SetAll(0);
154
155 materialnum = materialnumi;
156
157 col = coli;
158
159 //set vector of generalized coordinates of reference configuration
160 q0.SetLen(SOS());
161 //position and slope of first node
162 for(int i=1;i<=SOSPos()/NNodes();i++)
163 {
164 q0(i)=xc1(i);
165 }
166 //position and slope of second node
167 for(int i=SOSPos()/NNodes()+1;i<=SOSPos();i++)
168 {
169 q0(i)=xc2(i-SOSPos()/2);
170 }
171 //torsional angle at first and second node (measured w.r.t. the director: projection of the director into cross section and normalization -> e30, torsion of e30 around e1=r'/|r'| by the angle theta -> e3 of local frame, finally: e2 = e3 x e1)
172 q0(13) = theta1;
173 q0(14) = theta2;
174
175 size.X() = CalculateElementLength();
176 Material mat = GetMaterial();
177 if (mat.IsMaterialOfBeamWithRectangularCrossSection())
178 {
179 size.Y() = GetMaterial().GetBeamThicknessY();
180 size.Z() = GetMaterial().GetBeamThicknessZ();
181 }
182 else
183 {
184 assert (GetMaterial().IsMaterialOfBeamWithRectangularCrossSection()); //$ PG 2012-12-18: (as yet) a rectangular cross section (which is specified by the material) is required in ANCFBeam3DTorsion
185 }
186 mass = size.X()*size.Y()*size.Z()*GetMaterial().Density();
187
188 do_update_directors = do_update_directorsi;
189
190 //kinematic_computation_mode = 0 ... exact terms, 5th order gaussian integration (slow);
191 // 1 ... exact terms, low order (1st order lobatto) integration (fast);
192 // 2 ... approximate mass matrix (torsional terms approximated), no quadratic velocity vector (fastest) --- see also paper by dmitrochenko
193 kinematic_computation_mode = kinematic_computation_modei;
194 assert(kinematic_computation_mode >= 0 && kinematic_computation_mode <= 2);
195
196 // set directors
197 Vector xdatainit(director1.X(), director1.Y(), director1.Z(), director2.X(), director2.Y(), director2.Z());
198 SetDataInit(xdatainit);
199 }
200
201 // standard set function with oriented nodes (default set function for script language)
SetANCFBeam3DTorsion(int n1nr,int n2nr,int matnr,const Vector3D & coli,const int do_update_directorsi,const int kinematic_computation_modei)202 void ANCFBeam3DTorsion::SetANCFBeam3DTorsion(int n1nr, int n2nr, int matnr, const Vector3D& coli, const int do_update_directorsi, const int kinematic_computation_modei)
203 {
204 ANCFNodeS1rot1_3D& n1 = (ANCFNodeS1rot1_3D&)mbs->GetNode(n1nr);
205 ANCFNodeS1rot1_3D& n2 = (ANCFNodeS1rot1_3D&)mbs->GetNode(n2nr);
206 Matrix3D f1 = n1.GetLocalFrame();
207 Matrix3D f2 = n2.GetLocalFrame();
208 Vector3D n1_pos = n1.Pos();
209 Vector3D n2_pos = n2.Pos();
210 Vector3D n1_e1(f1(1,1),f1(2,1),f1(3,1));
211 Vector3D n2_e1(f2(1,1),f2(2,1),f2(3,1));
212 Vector3D n1_e3(f1(1,3),f1(2,3),f1(3,3)); // direction of director1, when torsional angle theta1 = 0
213 Vector3D n2_e3(f2(1,3),f2(2,3),f2(3,3)); // direction of director2, when torsional angle theta2 = 0
214
215 Vector xc1(6);
216 Vector xc2(6);
217
218 for (int i=1; i<=Dim(); i++)
219 {
220 xc1(i) = n1_pos(i);
221 xc1(i+Dim()) = n1_e1(i);
222 xc2(i) = n2_pos(i);
223 xc2(i+Dim()) = n2_e1(i);
224 }
225
226 // call standard set function
227 SetANCFBeam3DTorsion(xc1, xc2, 0, 0, n1_e3, n2_e3, n1.NodeNum(), n2.NodeNum(), matnr, coli, do_update_directorsi, kinematic_computation_modei);
228 }
229
230
231 // alternative set function with explicit element size (si)
SetANCFBeam3DTorsion(const Vector & xc1,const Vector & xc2,const double & theta1,const double & theta2,const Vector3D & director1,const Vector3D & director2,int n1i,int n2i,int materialnumi,const Vector3D & si,const Vector3D & coli,const int do_update_directorsi,const int kinematic_computation_modei)232 void ANCFBeam3DTorsion::SetANCFBeam3DTorsion(const Vector& xc1, const Vector& xc2, const double& theta1, const double& theta2,
233 const Vector3D& director1, const Vector3D& director2, int n1i, int n2i, int materialnumi, const Vector3D& si,
234 const Vector3D& coli, const int do_update_directorsi, const int kinematic_computation_modei)
235 {
236 // call standard set function
237 SetANCFBeam3DTorsion(xc1, xc2, theta1, theta2, director1, director2, n1i, n2i, materialnumi, coli, do_update_directorsi, kinematic_computation_modei);
238
239 // reset size
240 size = si;
241 }
242
243 // alternative set function, which determines directors automatically, caution: angles theta1 and theta2 are measured w.r.t. these directors
SetANCFBeam3DTorsion(const Vector & xc1,const Vector & xc2,const double & theta1,const double & theta2,int n1i,int n2i,int materialnumi,const Vector3D & si,const Vector3D & coli,const int do_update_directorsi,const int kinematic_computation_modei)244 void ANCFBeam3DTorsion::SetANCFBeam3DTorsion(const Vector& xc1, const Vector& xc2, const double& theta1, const double& theta2,
245 int n1i, int n2i, int materialnumi, const Vector3D& si, const Vector3D& coli, const int do_update_directorsi, const int kinematic_computation_modei)
246 {
247 // determine directors
248 Vector3D director;
249 Vector3D slopevector1(xc1(4), xc1(5), xc1(6));
250 Vector3D slopevector2(xc2(4), xc2(5), xc2(6));
251 director = DetermineStandardDirector(slopevector1, slopevector2);
252
253 // call standard set function
254 SetANCFBeam3DTorsion(xc1, xc2, theta1, theta2, director, director, n1i, n2i, materialnumi, si, coli, do_update_directorsi, kinematic_computation_modei);
255 }
256
257 // determine one standard director (for the whole element) by the knowledge of the axial slopes in the nodes
258 // if slopes are significantly distinct, then the director is chosen to be the cross product of both
259 // else
260 // if axial direction is not identical with 3rd kartesian direction then 3rd kartesian direction is chosen for director
261 // else 2nd kartesian direction is chosen for director
DetermineStandardDirector(Vector3D slopevector1,Vector3D slopevector2) const262 Vector3D ANCFBeam3DTorsion::DetermineStandardDirector(Vector3D slopevector1, Vector3D slopevector2) const
263 {
264 Vector3D director;
265
266 slopevector1.Normalize();
267 slopevector2.Normalize();
268
269 double minimal_distance = 1e-8;
270 if ((slopevector1 - slopevector2).Norm2() < minimal_distance) // slopevectors are almost identical
271 {
272 director.Set(0., 0., 1.);
273 double sqrt_half = sqrt(0.5);
274 if (((director - slopevector1).Norm2() < sqrt_half) || ((director + slopevector1).Norm2() < sqrt_half))
275 {
276 director.Set(0., 1., 0.);
277 }
278 }
279 else // slopevectors are significantly distinct
280 {
281 director = slopevector1.Cross(slopevector2);
282 director.Normalize();
283 }
284
285 return director;
286 }
287
288
GetElementData(ElementDataContainer & edc)289 void ANCFBeam3DTorsion::GetElementData(ElementDataContainer& edc) //fill in all element data
290 {
291 Body3D::GetElementData(edc);
292
293 //ElementData ed;
294 //Vector3D director1(GetDirector1()), director2(GetDirector2());
295 //ed.SetVector3D(director1.X(), director1.Y(), director1.Z(), "director at node 1"); ed.SetToolTipText("director at node 1"); edc.Add(ed);
296 //ed.SetVector3D(director2.X(), director2.Y(), director2.Z(), "director at node 2"); ed.SetToolTipText("director at node 2"); edc.Add(ed);
297 }
298
299 //user has changed data ==> write new data and parameters to element
SetElementData(ElementDataContainer & edc)300 int ANCFBeam3DTorsion::SetElementData(ElementDataContainer& edc) //fill in all element data
301 {
302 int rv = Body3D::SetElementData(edc);
303
304 SetANCFBeam3DTorsion(n1, n2, materialnum, col, do_update_directors, kinematic_computation_mode);
305
306 //Vector3D director1, director2;
307 //GetElemDataVector3D(GetMBS(), edc, "director at node 1", director1);
308 //GetElemDataVector3D(GetMBS(), edc, "director at node 2", director2);
309 //SetDirector1(director1);
310 //SetDirector2(director2);
311
312 return rv;
313 }
314
SetDirector1(const Vector3D & director)315 void ANCFBeam3DTorsion::SetDirector1(const Vector3D& director)
316 // save director1 in XData
317 {
318 XData(1) = director.X();
319 XData(2) = director.Y();
320 XData(3) = director.Z();
321 }
322
SetDirector2(const Vector3D & director)323 void ANCFBeam3DTorsion::SetDirector2(const Vector3D& director)
324 // save director2 in XData
325 {
326 XData(4) = director.X();
327 XData(5) = director.Y();
328 XData(6) = director.Z();
329 }
330
GetDirector1(int flagd) const331 Vector3D ANCFBeam3DTorsion::GetDirector1(int flagd) const
332 // return director1 from XData
333 {
334 if (flagd)
335 {
336 return Vector3D(XDataD(1), XDataD(2), XDataD(3));
337 }
338 return Vector3D(XData(1), XData(2), XData(3));
339 }
340
GetDirector2(int flagd) const341 Vector3D ANCFBeam3DTorsion::GetDirector2(int flagd) const
342 // return director2 from XData
343 {
344 if (flagd)
345 {
346 return Vector3D(XDataD(4), XDataD(5), XDataD(6));
347 }
348 return Vector3D(XData(4), XData(5), XData(6));
349 }
350
UpdateDirectors(const Vector3D & r1dx,const Vector3D & r2dx,const double theta1,const double theta2)351 int ANCFBeam3DTorsion::UpdateDirectors(const Vector3D& r1dx, const Vector3D& r2dx, const double theta1, const double theta2)
352 {
353
354 //test, if directori is collinear with ridx
355 Vector3D dir1 = GetDirector1();
356 Vector3D dir2 = GetDirector2();
357 double abs_cos1 = fabs(r1dx*dir1) / (r1dx.Norm() * dir1.Norm());
358 double abs_cos2 = fabs(r2dx*dir2) / (r2dx.Norm() * dir2.Norm());
359 double critical_value = 0.98; //has to be just a little smaller than one
360 if (abs_cos1 > critical_value || abs_cos2 > critical_value)
361 {
362 return 1;
363 }
364
365 Vector3D director_projection(dir1);
366 r1dx.GramSchmidt(director_projection); //project director1 into normal plane of r1dx -> director_projection; GramSchmidt returns normalized director_projection
367 SetDirector1(director_projection); //update director1
368
369 // same for second director
370 director_projection = dir2;
371 r2dx.GramSchmidt(director_projection);
372 SetDirector2(director_projection);
373
374 return 0;
375 }
376
Initialize()377 void ANCFBeam3DTorsion::Initialize()
378 {
379 Body3D::Initialize();
380 }
381
LinkToElements()382 void ANCFBeam3DTorsion::LinkToElements()
383 {
384 //Vector of degrees of freedom: [ r1 , r1' , r2 , r2' , phi1 , phi2 ]
385 //= 14 DOFs
386 //1=left node, 2=right node
387 //ri=position vector, ri'=slope vector along the beamcenterline, phi=rotation (torsion)
388
389 if (SOSowned() == 0)
390 {
391 //UO() << "Link nodes to elements";
392 const Node& node1 = GetMBS()->GetNode(n1);
393 const Node& node2 = GetMBS()->GetNode(n2);
394
395 //nodes must have dimension 7: r, r', phi (rotation of cross section)
396 const int nodedim = 7;
397 assert(node1.SOS() == nodedim);
398 assert(node2.SOS() == nodedim);
399
400 for (int i=1; i <= nodedim-1; i++)
401 {
402 AddLTG(node1.Get(i)); //LocalToGlobal-Element-list - left node (6 DOFs = pos. vector and slope vector)
403 }
404 for (int i=1; i <= nodedim-1; i++)
405 {
406 AddLTG(node2.Get(i));//right node(6 DOFs = pos. vector and slope vector)
407 }
408 //add rotation (torsion) degrees of freedom
409 AddLTG(node1.Get(nodedim));//1 DOF = rotation of cross section in left node
410 AddLTG(node2.Get(nodedim));//1 DOF = rotation of cross section in right node
411
412 //same for velocities:
413 for (int i=1; i <= nodedim-1; i++)
414 {
415 AddLTG(node1.Get(i+nodedim));
416 }
417 for (int i=1; i <= nodedim-1; i++)
418 {
419 AddLTG(node2.Get(i+nodedim));
420 }
421 AddLTG(node1.Get(nodedim*2));
422 AddLTG(node2.Get(nodedim*2));
423 }
424 }
425
426 //---------------------------------------------------
427 //Shapefunctions: between -lx/2 and lx/2
428 //---------------------------------------------------
429
430 //---------------------------------------------------
431 //interpolation of positions r_i and derivatives r_i'
432 //---------------------------------------------------
433
434 //GetShapesPos(sf,X) computes Shapefunctions at position X and saves values in vector sf
GetShapesPos(Vector & sf,double xi) const435 void ANCFBeam3DTorsion::GetShapesPos(Vector& sf, double xi) const
436 {
437 sf.SetLen(NSPos()); //NSPos=2*nnodes, length(sf)=4
438 double lx = size.X();
439
440 #ifndef OLD_SHAPEFUNCTIONS // xi e [-1,1]
441 double xi2 = xi*xi;
442 double xi3 = xi2*xi;
443 sf(1) = (2. - 3.*xi + xi3)/4.;
444 sf(2) = (1. - xi - xi2 + xi3)*lx/8.;
445 sf(3) = (2. + 3.*xi - xi3)/4.;
446 sf(4) = (-1. - xi + xi2 + xi3)*lx/8.;
447 #else // xi e [-L/2,L/2]
448 double s=2*xi/lx;//-1<=s<=+1
449 double s2 = s*s;
450 double s3 = Cub(s);
451
452 sf(1)=(s3 - 3.*s + 2.)/4.;
453 sf(2)=(s3 - s2 - s + 1.)/2./lx;
454 sf(3)=(-s3 + 3.*s + 2.)/4.;
455 sf(4)=(s3 + s2 - s - 1.)/2./lx;
456 #endif
457 }
458
459 //GetSFPos(i,X) computes i-th Shapefunction at X
GetSFPos(int i,double xi) const460 double ANCFBeam3DTorsion::GetSFPos(int i, double xi) const
461 {
462 double lx = size.X();
463
464 #ifndef OLD_SHAPEFUNCTIONS
465 //xi between -1 and 1
466 double xi2 = xi*xi;
467 double xi3 = xi2*xi;
468 switch(i)
469 {
470 case 1: return (2. - 3.*xi + xi3)/4.;
471 case 2: return (1. - xi - xi2 + xi3)*lx/8.;
472 case 3: return (2. + 3.*xi - xi3)/4.;
473 case 4: return (-1. - xi + xi2 + xi3)*lx/8.;
474 default: mbs->UO() << "only 4 Shapefunctions for position\n"; return 0.;
475 }
476 #else
477 //xi between -length/2 and length/2
478 double s=2*xi/lx;
479 double s2 = s*s;
480 double s3 = Cub(s);
481
482 switch(i)
483 {
484 case 1: return (s3 - 3.*s + 2.)/4.;
485 case 2: return (s3 - s2 - s + 1.)/2./lx;
486 case 3: return (-s3 + 3.*s + 2.)/4.;
487 case 4: return (s3 + s2 - s - 1.)/2./lx;
488 default: mbs->UO()<<"only 4 Shapefunctions for position\n"; return 0.;
489 }
490 #endif
491
492 return 0.;
493 }
494
495 //1st derivative dS/dx
GetShapesPosx(Vector & sf,double xi) const496 void ANCFBeam3DTorsion::GetShapesPosx(Vector& sf, double xi) const
497 {
498 sf.SetLen(NSPos());
499 double lx = size.X();
500
501 #ifndef OLD_SHAPEFUNCTIONS
502 //xi between -1 and 1
503 double f = 2./lx;
504 double xi2 = xi*xi;
505 sf(1) = f*(-3. + 3.*xi2)/4.;
506 sf(2) = f*(-1. - 2.*xi + 3.*xi2)*lx/8.;
507 sf(3) = f*(3. - 3.*xi2)/4.;
508 sf(4) = f*(-1. + 2.*xi + 3.*xi2)*lx/8.;
509 #else
510 //xi between -length/2 and length/2
511 double s=2*xi/lx;
512 double s2 = s*s;
513 double lx2 = lx*lx;
514
515 sf(1)=1.5*(s2 - 1.)/lx;
516 sf(2)=(3.*s2 - 2.*s -1.)/lx2;
517 sf(3)=1.5*(-s2 + 1.)/lx;
518 sf(4)=(3.*s2 + 2.*s - 1.)/lx2;
519 #endif
520 }
521
GetSFPosx(int i,double xi) const522 double ANCFBeam3DTorsion::GetSFPosx(int i, double xi) const
523 {
524 double lx = size.X();
525
526 #ifndef OLD_SHAPEFUNCTIONS
527 //xi between -1/2 and 1/2
528 double xi2 = xi*xi;
529 double f = 2./lx;
530 switch(i)
531 {
532 case 1: return f*(- 3. + 3.*xi2)/4.;
533 case 2: return f*(-1. - 2.*xi + 3.*xi2)*lx/8.;
534 case 3: return f*(3. - 3.*xi2)/4.;
535 case 4: return f*(-1. + 2.*xi + 3.*xi2)*lx/8.;
536 default: mbs->UO() << "only 4 Shapefunctions for position\n"; return 0.;
537 }
538 #else
539 //xi between -length/2 and length/2
540 double s=2*xi/lx;
541 double s2 = s*s;
542 double lx2 = lx*lx;
543
544 switch(i)
545 {
546 case 1: return 1.5*(s2 - 1.)/lx;
547 case 2: return (3.*s2 - 2.*s -1.)/(lx2);
548 case 3: return 1.5*(-s2 + 1.)/lx;
549 case 4: return(3.*s2 + 2.*s - 1.)/(lx2);
550 default: mbs->UO()<<"only 4 Shapefunctions for position\n"; return 0.;
551 }
552 #endif
553
554 return 0.;
555 }
556
557 //2nd derivatives d^2S/dx^2
GetShapesPosxx(Vector & sf,double xi) const558 void ANCFBeam3DTorsion::GetShapesPosxx(Vector& sf, double xi) const
559 {
560 sf.SetLen(NSPos());
561 double lx = size.X();
562
563 #ifndef OLD_SHAPEFUNCTIONS
564 //xi between -1/2 and 1/2
565 double f = 4./Sqr(lx);
566 sf(1) = f*(6.*xi)/4.;
567 sf(2) = f*(-2. + 6.*xi)*lx/8.;
568 sf(3) = f*(-6.*xi)/4.;
569 sf(4) = f*(2. + 6.*xi)*lx/8.;
570 #else
571 //xi between -length/2 and length/2
572 double s=2*xi/lx;
573 double lx2 = lx*lx;
574 double lx3 = lx2*lx;
575
576 sf(1)=6.*s/lx2;
577 sf(2)=(12.*s - 4.)/lx3;
578 sf(3)=-6.*s/lx2;
579 sf(4)=(12.*s + 4.)/lx3;
580 #endif
581 }
582
GetSFPosxx(int i,double xi) const583 double ANCFBeam3DTorsion::GetSFPosxx(int i, double xi) const
584 {
585 double lx = size.X();
586
587 #ifndef OLD_SHAPEFUNCTIONS
588 //xi between -1/2 and 1/2
589 double f = 4./Sqr(lx);
590 switch(i)
591 {
592 case 1: return f*(6.*xi)/4.;
593 case 2: return f*(-2. + 6.*xi)*lx/8.;
594 case 3: return f*(-6.*xi)/4.;
595 case 4: return f*(2. + 6.*xi)*lx/8.;
596 default: mbs->UO()<<"only 4 Shapefunctions for position\n"; return 0.;
597 }
598 #else
599 //xi between -length/2 and length/2
600 double s=2*xi/lx;
601 double lx2 = lx*lx;
602 double lx3 = lx2*lx;
603 switch(i)
604 {
605
606 case 1: return 6.*s/lx2;
607 case 2: return (12.*s - 4.)/lx3;
608 case 3: return -6.*s/lx2;
609 case 4: return (12.*s + 4.)/lx3;
610 default: mbs->UO()<<"only 4 Shapefunctions for position\n"; return 0.;
611 }
612 #endif
613
614 return 0.;
615 }
616
617 //3rd derivatives d^3S/dx^3
GetShapesPosxxx(Vector & sf,double xi) const618 void ANCFBeam3DTorsion::GetShapesPosxxx(Vector& sf, double xi) const
619 {
620 sf.SetLen(NSPos());
621 double lx = size.X();
622
623 #ifndef OLD_SHAPEFUNCTIONS
624 //xi between -1/2 and 1/2
625 double f = 8./Cub(lx);
626 sf(1) = f*(6.)/4.;
627 sf(2) = f*(6.)*lx/8.;
628 sf(3) = f*(-6.)/4.;
629 sf(4) = f*(6.)*lx/8.;
630 #else
631 //xi between -length/2 and length/2
632 double lx3 = Cub(lx);
633 double lx4 = lx3*lx;
634
635 sf(1)=12./lx3;
636 sf(2)=24./lx4;
637 sf(3)=-12./lx3;
638 sf(4)=24./lx4;
639 #endif
640 }
641
GetSFPosxxx(int i,double xi) const642 double ANCFBeam3DTorsion::GetSFPosxxx(int i, double xi) const
643 {
644 double lx = size.X();
645
646 #ifndef OLD_SHAPEFUNCTIONS
647 //xi between -1/2 and 1/2
648 double f = 8./Cub(lx);
649 switch(i)
650 {
651 case 1: return f*(6.)/4.;
652 case 2: return f*(6.)*lx/8.;
653 case 3: return f*(-6.)/4.;
654 case 4: return f*(6.)*lx/8.;
655 default: mbs->UO()<<"only 4 Shapefunctions for position\n"; return 0.;
656 }
657 #else
658 //xi between -length/2 and length/2
659 double lx3 = Cub(lx);
660 double lx4 = lx3*lx;
661
662 switch(i)
663 {
664 case 1: return 12./lx3;
665 case 2: return 24./lx4;
666 case 3: return -12./lx3;
667 case 4: return 24./lx4;
668 default: mbs->UO()<<"only 4 Shapefunctions for position\n"; return 0.;
669 }
670 #endif
671
672 return 0.;
673 }
674
675 //---------------------------------------------------
676 //interpolation of angle theta, -1/2<\xi<+L/2
677 //---------------------------------------------------
678
GetShapesRot(Vector & sf,double xi) const679 void ANCFBeam3DTorsion::GetShapesRot(Vector& sf, double xi) const
680 {
681 double lx = size.X();
682
683 sf.SetLen(NSRot()); //NSRot=2
684 sf(1)= 0.5-xi/lx;
685 sf(2)= 0.5+xi/lx;
686 }
687
GetSFRot(int i,double xi) const688 double ANCFBeam3DTorsion::GetSFRot(int i, double xi) const
689 {
690 double lx = size.X();
691
692 switch(i)
693 {
694 case 1: return 0.5-xi/lx;
695 case 2: return 0.5+xi/lx;
696 default: mbs->UO()<<"only 2 Shapefunctions for rotation\n"; return 0.;
697 }
698 return 0.;
699 }
700
701 // 1st derivative
GetShapesRotx(Vector & sf,double xi) const702 void ANCFBeam3DTorsion::GetShapesRotx(Vector& sf, double xi) const
703 {
704 double lx = size.X();
705
706 sf.SetLen(NSRot()); //NSRot=2
707 sf(1)=-1./lx;
708 sf(2)=1./lx;
709 }
710
GetSFRotx(int i,double xi) const711 double ANCFBeam3DTorsion::GetSFRotx(int i, double xi) const
712 {
713 double lx = size.X();
714
715 switch(i)
716 {
717 case 1: return -1./lx;
718 case 2: return 1./lx;
719 default: mbs->UO()<<"only 2 Shapefunctions for rotation\n"; return 0.;
720 }
721 return 0.;
722 }
723
724
725 //----------------------------------------------
726 //Position and Displacement for Drawing
727 //----------------------------------------------
GetRefPosD() const728 Vector3D ANCFBeam3DTorsion::GetRefPosD() const
729 {
730 return GetPosD(Vector3D(0.,0.,0.));
731 }
732
GetPosD(const Vector3D & p_loc) const733 Vector3D ANCFBeam3DTorsion::GetPosD(const Vector3D& p_loc) const
734 {
735 return GetPos(p_loc(1),1) + GetRotMatrix(p_loc(1), 1)*Vector3D(0., p_loc.Y(), p_loc.Z());
736 }
737
738 //Get actual position of relative point p_loc in range [-lx/2..lx/2, etc.]
GetPos(const Vector3D & p_loc) const739 Vector3D ANCFBeam3DTorsion::GetPos(const Vector3D& p_loc) const
740 {
741 return GetPos(p_loc(1),0) + GetRotMatrix(p_loc(1), 0)*Vector3D(0., p_loc.Y(), p_loc.Z());
742 }
743
GetDisplacement(const Vector3D & p0,int flagD) const744 Vector3D ANCFBeam3DTorsion::GetDisplacement(const Vector3D& p0, int flagD) const
745 {
746 // p0 is in [-lx/2., lx/2.] x [-ly/2., ly/2.] x [-lz/2., lz/2.]
747 // compute u(x,y,z) = r(x) - r0(x) + (A(x)-A0(x))(0,y,z)^T
748 Vector3D u(0.,0.,0.);
749 Vector3D ploc = p0;
750 ploc.Scale(size.X()/2.,size.Y()/2.,size.Z()/2.); // ploc is in [-1, 1]^3
751
752 Matrix3D A = GetRotMatrix(p0(1), flagD);
753 Matrix3D A0 = GetInitRotMatrix3D(p0.X());
754 for (int i = 1; i <= Dim(); i++)
755 {
756 //A(i,i) -= 1.;
757 u(i) += (A(i,2)-A0(i,2))*p0.Y() + (A(i,3)-A0(i,3))*p0.Z();
758 for (int j = 1; j <= NSPos(); j++)
759 {
760 #ifndef OLD_SHAPEFUNCTIONS
761 if (flagD)
762 u(i) += GetSFPos(j, ploc(1))*(XGD((j-1)*Dim()+i));
763 else
764 u(i) += GetSFPos(j, ploc(1))*(XG((j-1)*Dim()+i));
765 #else
766 if (flagD)
767 u(i) += GetSFPos(j, p0(1))*(XGD((j-1)*Dim()+i));
768 else
769 u(i) += GetSFPos(j, p0(1))*(XG((j-1)*Dim()+i));
770 #endif
771 }
772 }
773 return u;
774 }
775
GetVel(double xi,int flagD) const776 Vector3D ANCFBeam3DTorsion::GetVel(double xi, int flagD) const
777 {
778 //status: -l/2<=xi<=l/2
779 #ifndef OLD_SHAPEFUNCTIONS
780 xi *= 2./size.X(); //status: -1<=xi<=1
781 #endif
782 Vector3D v(0.,0.,0.);
783 for (int i = 1; i <= Dim(); i++)
784 {
785 for (int j = 1; j <= NSPos(); j++)
786 {
787 if(flagD==0)
788 v(i) += GetSFPos(j,xi)*XGP((j-1)*Dim()+i);
789 else
790 v(i) += GetSFPos(j,xi)*XGPD((j-1)*Dim()+i);
791 }
792 }
793 return v;
794 }
795
GetVel(const Vector3D & p_loc) const796 Vector3D ANCFBeam3DTorsion::GetVel(const Vector3D& p_loc) const
797 {
798 return GetVel(p_loc(1), 0) + GetRotMatrixP(p_loc(1), 0)*Vector3D(0., p_loc.Y(), p_loc.Z());
799 }
800
GetVelD(const Vector3D & p_loc) const801 Vector3D ANCFBeam3DTorsion::GetVelD(const Vector3D& p_loc) const
802 {
803 return GetVel(p_loc(1), 1) + GetRotMatrixP(p_loc(1), 1)*Vector3D(0., p_loc.Y(), p_loc.Z());
804 }
805
GetNodePos(int node_idx) const806 Vector3D ANCFBeam3DTorsion::GetNodePos(int node_idx) const //returns position of i-th node
807 {
808 switch(node_idx)
809 {
810 case 1: return GetPos(Vector3D(-size.X()*.5, 0, 0));
811 case 2: return GetPos(Vector3D(+size.X()*.5, 0, 0));
812 }
813 assert(0);
814 return Vector3D(0.);
815 }
816
GetNodePosD(int node_idx) const817 Vector3D ANCFBeam3DTorsion::GetNodePosD(int node_idx) const //returns position of i-th node (draw mode)
818 {
819 switch(node_idx)
820 {
821 case 1: return GetPosD(Vector3D(-size.X()*.5, 0, 0));
822 case 2: return GetPosD(Vector3D(+size.X()*.5, 0, 0));
823 }
824 assert(0);
825 return Vector3D(0.);
826 }
827
GetDOFPosD(int idof) const828 Vector3D ANCFBeam3DTorsion::GetDOFPosD(int idof) const //returns position of i-th DOF
829 {
830 if (idof > SOS() && idof <= 2*SOS()) idof -= SOS();
831 if (idof > 0)
832 {
833 if (idof < 7 || idof == 13) //left node
834 {
835 return GetPosD(Vector3D(-0.5*size.X(),0.,0.));
836 }
837 else if (idof < 13 || idof == 14) //right node
838 {
839 return GetPosD(Vector3D(0.5*size.X(),0.,0.));
840 }
841 }
842 assert(0);
843 return Vector3D();
844 }
845
GetDOFDirD(int idof) const846 Vector3D ANCFBeam3DTorsion::GetDOFDirD(int idof) const //returns direction of action of i-th DOF
847 {
848 if (idof > SOS() && idof <= 2*SOS()) idof -= SOS();
849
850 Matrix3D rot;
851 if (idof < 7)
852 rot = Matrix3D(1.);//GetInitRotMatrix3D(-size.X()*.5);
853 else
854 rot = Matrix3D(1.);//GetInitRotMatrix3D(size.X()*.5);
855
856 switch(idof)
857 {
858 case 1: case 7: return Vector3D(rot(1,1),rot(2,1),rot(3,1)); break;
859 case 2: case 8: return Vector3D(rot(1,2),rot(2,2),rot(3,2)); break;
860 case 3: case 9: return Vector3D(rot(1,3),rot(2,3),rot(3,3)); break;
861 }
862 return Vector3D(0.,0.,0.);
863 }
864
865
866 //-------------------------------------------------------
867 //GetPos, shapefunctions are defined between -lx/2 and lx/2
868 //-------------------------------------------------------
869
870 //GetPos berechnet Positionsvektor r im deformierten Element
871 //GetPos computes position r in deformed element
872 //xg = generalized coordinates (= our vector of unknowns q)
GetPos(double xi,const Vector & xg) const873 Vector3D ANCFBeam3DTorsion::GetPos(double xi, const Vector& xg) const
874 {
875 #ifndef OLD_SHAPEFUNCTIONS
876 xi *= 2./size.X();
877 #endif
878 Vector3D p(0.,0.,0.);
879 for (int i = 1; i <= Dim(); i++)
880 {
881 for (int j = 1; j <= NSPos(); j++)
882 {
883 p(i) += GetSFPos(j,xi)*(xg((j-1)*Dim()+i)+q0((j-1)*Dim()+i)); //r=u+r_0=Sq+Sq_0 (q_0=initial values, x_init=0-Vector -> no displacement in the beginning))
884 }
885 }
886 return p;
887 }
888
889
890 //GetPos von oben, aber falls im Aufruf als zweite Eingabe kein Vektor, sondern ein Integer steht,
891 //wird diese Fkt f�r Grafik aufgerufen; globale Variable XG wird f�r Rechnung verwendet anstatt Eingabe xg
892 //same GetPos function as above, but with the second parameter (flag D) the function for the visualization is activated
893 //Aufruf mit xg braucht weniger Zeit, weil es sich xg nicht holen muss
GetPos(double xi,int flagD) const894 Vector3D ANCFBeam3DTorsion::GetPos(double xi, int flagD) const
895 {
896 //status: -l/2<=xi<=l/2
897 #ifndef OLD_SHAPEFUNCTIONS
898 xi *= 2./size.X(); //status: -1<=xi<=1
899 #endif
900 Vector3D p(0.,0.,0.);
901 for (int i = 1; i <= Dim(); i++)
902 {
903 for (int j = 1; j <= NSPos(); j++)
904 {
905 if(flagD==0)
906 p(i) += GetSFPos(j,xi)*(XG((j-1)*Dim()+i)+q0((j-1)*Dim()+i));
907 else
908 p(i) += GetSFPos(j,xi)*(XGD((j-1)*Dim()+i)+q0((j-1)*Dim()+i));
909 }
910 }
911 return p;
912 }
913
914
915 //Ableitungen von GetPos entsprechen unseren Richtungsvektoren
916 //GetPosx (Ableitung in Richtung der Balkenachse: dr/dx=r,x)
917 //GetPosx is the derivative with respect to the direction of the beam centerline
GetPosx(double xi,const Vector & xg) const918 Vector3D ANCFBeam3DTorsion::GetPosx(double xi, const Vector& xg) const
919 {
920 #ifndef OLD_SHAPEFUNCTIONS
921 xi *= 2./size.X();
922 #endif
923 Vector3D p(0.,0.,0.);
924 for (int i = 1; i <= Dim(); i++)
925 {
926 for (int j = 1; j <= NSPos(); j++)
927 {
928 p(i) += GetSFPosx(j,xi)*(xg((j-1)*Dim()+i)+q0((j-1)*Dim()+i)); //r,x=S,x*u+S,x*q_0
929 }
930 }
931 return p;
932 }
933
934
GetPosx(double xi,int flagD) const935 Vector3D ANCFBeam3DTorsion::GetPosx(double xi, int flagD) const
936 {
937 #ifndef OLD_SHAPEFUNCTIONS
938 xi *= 2./size.X();
939 #endif
940 Vector3D p(0.,0.,0.);
941 for (int i = 1; i <= Dim(); i++)
942 {
943 for (int j = 1; j <= NSPos(); j++)
944 {
945 if(flagD==0)
946 p(i) += GetSFPosx(j,xi)*(XG((j-1)*Dim()+i)+q0((j-1)*Dim()+i));
947 else
948 p(i) += GetSFPosx(j,xi)*(XGD((j-1)*Dim()+i)+q0((j-1)*Dim()+i));
949 }
950 }
951 return p;
952 }
953
954
955 //second derivatives of position vector r with respect to x
GetPosxx(double xi,const Vector & xg) const956 Vector3D ANCFBeam3DTorsion::GetPosxx(double xi, const Vector& xg) const
957 {
958 #ifndef OLD_SHAPEFUNCTIONS
959 xi *= 2./size.X();
960 #endif
961 Vector3D p(0.,0.,0.);
962 for (int i = 1; i <= Dim(); i++)
963 {
964 for (int j = 1; j <= NSPos(); j++)
965 {
966 p(i) += GetSFPosxx(j,xi)*(xg((j-1)*Dim()+i)+q0((j-1)*Dim()+i));
967 }
968 }
969 return p;
970 }
971
972
GetPosxx(double xi,int flagD) const973 Vector3D ANCFBeam3DTorsion::GetPosxx(double xi, int flagD) const
974 {
975 #ifndef OLD_SHAPEFUNCTIONS
976 xi *= 2./size.X();
977 #endif
978 Vector3D p(0.,0.,0.);
979 for (int i = 1; i <= Dim(); i++)
980 {
981 for (int j = 1; j <= NSPos(); j++)
982 {
983 if(flagD==0)
984 p(i) += GetSFPosxx(j,xi)*(XG((j-1)*Dim()+i)+q0((j-1)*Dim()+i));
985 else
986 p(i) += GetSFPosxx(j,xi)*(XGD((j-1)*Dim()+i)+q0((j-1)*Dim()+i));
987 }
988 }
989 return p;
990 }
991
992
993 //third derivatives of position vector r with respect to x
GetPosxxx(double xi,const Vector & xg) const994 Vector3D ANCFBeam3DTorsion::GetPosxxx(double xi, const Vector& xg) const
995 {
996 #ifndef OLD_SHAPEFUNCTIONS
997 xi *= 2./size.X();
998 #endif
999 Vector3D p(0.,0.,0.);
1000 for (int i = 1; i <= Dim(); i++)
1001 {
1002 for (int j = 1; j <= NSPos(); j++)
1003 {
1004 p(i) += GetSFPosxxx(j,xi)*(xg((j-1)*Dim()+i)+q0((j-1)*Dim()+i));
1005 }
1006 }
1007 return p;
1008 }
1009
1010
GetPosxxx(double xi,int flagD) const1011 Vector3D ANCFBeam3DTorsion::GetPosxxx(double xi, int flagD) const
1012 {
1013 #ifndef OLD_SHAPEFUNCTIONS
1014 xi *= 2./size.X();
1015 #endif
1016 Vector3D p(0.,0.,0.);
1017 for (int i = 1; i <= Dim(); i++)
1018 {
1019 for (int j = 1; j <= NSPos(); j++)
1020 {
1021 if(flagD==0)
1022 p(i) += GetSFPosxxx(j,xi)*(XG((j-1)*Dim()+i)+q0((j-1)*Dim()+i));
1023 else
1024 p(i) += GetSFPosxxx(j,xi)*(XGD((j-1)*Dim()+i)+q0((j-1)*Dim()+i));
1025 }
1026 }
1027 return p;
1028 }
1029
GetPosxP(double xi,int flagD) const1030 Vector3D ANCFBeam3DTorsion::GetPosxP(double xi, int flagD) const
1031 {
1032 #ifndef OLD_SHAPEFUNCTIONS
1033 xi *= 2./size.X();
1034 #endif
1035 Vector3D p(0.,0.,0.);
1036 for (int i = 1; i <= Dim(); i++)
1037 {
1038 for (int j = 1; j <= NSPos(); j++)
1039 {
1040 if(flagD==0)
1041 p(i) += GetSFPosx(j,xi)*XGP((j-1)*Dim()+i);
1042 else
1043 p(i) += GetSFPosx(j,xi)*XGPD((j-1)*Dim()+i);
1044 }
1045 }
1046 return p;
1047 }
1048
1049 //---------------------------------------------
1050 //GetRot
1051 //---------------------------------------------
1052
GetRot(double xi,const Vector & xg) const1053 double ANCFBeam3DTorsion::GetRot(double xi, const Vector& xg) const
1054 {
1055 double a=0;
1056 for (int j = 1; j <= NSRot(); j++)
1057 {
1058 a += GetSFRot(j,xi)*(xg(SOSPos()+j)+q0(SOSPos()+j)); //aus xg und q0 werden nur die letzten beide Eintr�ge verwendet
1059 }
1060 return a;
1061 }
1062
GetRot(double xi,int flagD) const1063 double ANCFBeam3DTorsion::GetRot(double xi, int flagD) const
1064 {
1065 double a=0;
1066 for (int j = 1; j <= NSRot(); j++)
1067 {
1068 if(flagD==0)
1069 a += GetSFRot(j,xi)*(XG(SOSPos()+j)+q0(SOSPos()+j));
1070 else
1071 a += GetSFRot(j,xi)*(XGD(SOSPos()+j)+q0(SOSPos()+j));
1072 }
1073 return a;
1074 }
1075
GetRotx(double xi,const Vector & xg) const1076 double ANCFBeam3DTorsion::GetRotx(double xi, const Vector& xg) const
1077 {
1078 double a=0;
1079 for (int j = 1; j <= NSRot(); j++)
1080 {
1081 a += GetSFRotx(j,xi)*(xg(SOSPos()+j)+q0(SOSPos()+j));
1082 }
1083 return a;
1084 }
1085
GetRotx(double xi,int flagD) const1086 double ANCFBeam3DTorsion::GetRotx(double xi, int flagD) const
1087 {
1088 double a=0;
1089 for (int j = 1; j <= NSRot(); j++)
1090 {
1091 if(flagD==0)
1092 a += GetSFRotx(j,xi)*(XG(SOSPos()+j)+q0(SOSPos()+j));
1093 else
1094 a += GetSFRotx(j,xi)*(XGD(SOSPos()+j)+q0(SOSPos()+j));
1095 }
1096 return a;
1097 }
1098
GetRotP(double xi,int flagD) const1099 double ANCFBeam3DTorsion::GetRotP(double xi, int flagD) const
1100 {
1101 double a=0;
1102 for (int j = 1; j <= NSRot(); j++)
1103 {
1104 if(flagD==0)
1105 a += GetSFRot(j,xi)*XGP(SOSPos()+j);
1106 else
1107 a += GetSFRot(j,xi)*XGPD(SOSPos()+j);
1108 }
1109 return a;
1110 }
1111
1112
1113 //---------------------------------------------
1114 //GetRotMatrix
1115 //---------------------------------------------
GetRotMatrix(double xi,int flagD) const1116 Matrix3D ANCFBeam3DTorsion::GetRotMatrix(double xi, int flagD) const
1117 {
1118 // xi in [-lx/2,lx/2]
1119
1120 Vector3D rx,ry,rz,d;
1121 double Ang,c,s;
1122
1123 Ang = GetRot(xi, flagD); //-lx/2<=xi<=+lx/2
1124 c = cos(Ang);
1125 s = sin(Ang);
1126
1127 rx = GetPosx(xi, flagD); //-lx/2<=xi<=+lx/2
1128 rx.Normalize();
1129
1130 //d = Vector3D(0.,0.,1.); //first trial, later put this vector into XData and update every step
1131 d = GetDirector(xi, flagD);
1132 Vector3D e30 = d;
1133
1134 rx.GramSchmidt(e30); //d is projected into plane normal to rx (GramSchmidt() already returns a normalized Vector3D)
1135
1136 Vector3D e20 = e30.Cross(rx);
1137 //e20.Normalize(); ... is redundant, since |rx|=1, |e30| = 1, rx ortho to e30
1138
1139 ry = e20*c + e30*s;
1140 rz = e30*c - e20*s;
1141
1142 Matrix3D A(rx.X(),ry.X(),rz.X(),
1143 rx.Y(),ry.Y(),rz.Y(),
1144 rx.Z(),ry.Z(),rz.Z());
1145 return A;
1146 }
1147
GetRotMatrixP(double xi,int flagD) const1148 Matrix3D ANCFBeam3DTorsion::GetRotMatrixP(double xi, int flagD) const
1149 {
1150 // xi in [-lx/2,lx/2]
1151
1152 double Ang = GetRot(xi, flagD);
1153 double AngP = GetRotP(xi, flagD);
1154
1155 double c = cos(Ang);
1156 double s = sin(Ang);
1157 double cP = -s*AngP;
1158 double sP = c*AngP;
1159
1160 Vector3D e1 = GetPosx(xi, flagD); // non normalized e1
1161 double length_rx = e1.Norm();
1162 e1 *= (1./length_rx); // e1 now normalized
1163
1164 Vector3D e1P = GetPosxP(xi, flagD);
1165 Vector3D rxP(e1P); // store for later use (see return)
1166 e1P *= (1./length_rx);
1167 e1P -= (e1P*e1)*e1; // time derivative of normalized e1
1168
1169 Vector3D d = GetDirector(xi, flagD);
1170
1171 Vector3D e30 = d - (e1*d)*e1; // GramSchmidt() w/o Normalize()
1172 Vector3D e30P = -(e1P*d)*e1 - (e1*d)*e1P; // time derivative of non-normalized e30: Director d is constant during time step
1173 double length_e30hat = e30.Norm();
1174 e30 *= (1./length_e30hat); // e30 now normalized
1175
1176 e30P *= (1./length_e30hat);
1177 e30P -= (e30P*e30)*e30; // time derivative of normalized e30
1178
1179 Vector3D e20 = e30.Cross(e1); // e20 has unit length, since e30 and e1 are of unit length and orthogonal
1180 Vector3D e20P = e30P.Cross(e1) + e30.Cross(e1P);
1181
1182 Vector3D ryP = e20P*c + e30P*s + e20*cP + e30*sP;
1183 Vector3D rzP = e30P*c - e20P*s + e30*cP - e20*sP;
1184
1185 Matrix3D AP(rxP.X(),ryP.X(),rzP.X(),
1186 rxP.Y(),ryP.Y(),rzP.Y(),
1187 rxP.Z(),ryP.Z(),rzP.Z());
1188 return AP;
1189 }
1190
GetInitRotMatrix3D(double xi) const1191 Matrix3D ANCFBeam3DTorsion::GetInitRotMatrix3D(double xi) const
1192 {
1193 // xi in [-lx/2,lx/2]
1194
1195 Vector3D rx,ry,rz,d;
1196 double Ang,c,s;
1197
1198 Ang = GetInitRot3D(xi); //-lx/2<=xi<=+lx/2
1199 c = cos(Ang);
1200 s = sin(Ang);
1201
1202 rx = GetInitPosx3D(xi); //-lx/2<=xi<=+lx/2
1203 rx.Normalize();
1204
1205 //d = Vector3D(0.,0.,1.); //first trial, later put this vector into XData and update every step
1206 d = GetInitDirector(xi);
1207 Vector3D e30 = d;
1208
1209 rx.GramSchmidt(e30); //d is projected into plane normal to rx (GramSchmidt() already returns a normalized Vector3D)
1210
1211 Vector3D e20 = e30.Cross(rx);
1212 //e20.Normalize(); ... is redundant, since |rx|=1, |e30| = 1, rx ortho to e30
1213
1214 ry = e20*c + e30*s;
1215 rz = e30*c - e20*s;
1216
1217 Matrix3D A(rx.X(),ry.X(),rz.X(),
1218 rx.Y(),ry.Y(),rz.Y(),
1219 rx.Z(),ry.Z(),rz.Z());
1220 return A;
1221 }
1222
GetdPosdqT(const Vector3D & ploc,Matrix & d)1223 void ANCFBeam3DTorsion::GetdPosdqT(const Vector3D& ploc, Matrix& d)
1224 {
1225 if (ploc.Y() != 0 || ploc.Z() != 0) {mbs->UO() << "ERROR: ANCFBeam3DTorsion::GetdPosdqT only implemented for y=z=0!!!!!\n";}
1226
1227 //r = Spos*q; dr/dq = Spos
1228 d.SetSize(SOS(),3);
1229 d.FillWithZeros();
1230
1231 double xi = ploc.X();
1232 #ifndef OLD_SHAPEFUNCTIONS
1233 xi *= 2./size.X();
1234 #endif
1235
1236 for (int i = 1; i <= Dim(); i++)
1237 {
1238 for (int j = 1; j <= NSPos(); j++)
1239 {
1240 d((j-1)*Dim()+i, i) = GetSFPos(j,xi);
1241 //p(i) += GetSFPos(j,xi)*(xg((j-1)*Dim()+i)+q0((j-1)*Dim()+i)); //r=u+r_0=Sq+Sq_0 (q_0=initial values, x_init=0-Vector -> no displacement in the beginning))
1242 }
1243 }
1244 }
1245
GetIntDuDq(Matrix & dudq)1246 void ANCFBeam3DTorsion::GetIntDuDq(Matrix& dudq)
1247 {
1248 //integrate du/dq over beam volume => (crossection area) * (integration over axis)
1249 //u(q) = r(q) - r0 ==> du/dq = dr/dq
1250
1251 dudq.SetSize(NSPos()*Dim()+NSRot(), Dim());
1252 dudq.SetAll(0);
1253
1254 GetIntegrationRule(x1, w1, 5); //Interpolation positions: third order 3*2-1 = 5
1255 double fact = size.X()*0.5*size.Y()*size.Z(); //crosssection area times determinant for line integral
1256
1257 for (int i1=1; i1<=x1.GetLen(); i1++)
1258 {
1259 double scaled_weight = w1(i1) * fact; //scale weight
1260 double xi = x1(i1);
1261
1262 #ifdef OLD_SHAPEFUNCTIONS
1263 xi *= size.X()*0.5;
1264 #endif
1265 for (int j=1; j<=NSPos(); j++)
1266 {
1267 double sf_value = GetSFPos(j, xi); //value returned by i'th (positional) shape function at point xi
1268 double block_j = Dim()*(j-1); //addresses (j-1)st block in dudq
1269 for (int k=1; k<=Dim(); k++)
1270 {
1271 dudq(k+block_j, k) += scaled_weight*sf_value;
1272 }
1273 }
1274 }
1275 }
1276
1277
GetdRotvdqT(const Vector3D & vloc,const Vector3D & ploc,Matrix & drotvdqT)1278 void ANCFBeam3DTorsion::GetdRotvdqT(const Vector3D& vloc, const Vector3D& ploc, Matrix& drotvdqT)
1279 {
1280 GetdRotvdqT(vloc, ploc, drotvdqT, 0);
1281 }
1282
1283 //// method calculates gradient of (A(ploc)*vloc) with respect to generalized coordinates (gc), where
1284 //// A(ploc) denotes the Rotation Matrix at the axial position ploc,
1285 //// vloc denotes an input vector,
1286 //// the result is returned through Matrix& drotvdqT (the T (transpose) means, that drotvdqT has
1287 //// as many rows as partial derivatives and 3 columns (dimension of vector w=A(ploc)*vloc)
1288 ////
1289 //// IMPORTANT: if (!use_transposed), then everything is done as explained above
1290 //// if (use_transposed), then vloc is multiplied with transposed of A
1291 //void ANCFBeam3DTorsion::GetdRotvdqT(const Vector3D& vloc, const Vector3D& ploc, Matrix& drotvdqT, int use_transposed)
1292 //{
1293 // // ploc is in [-lx/2,lx/2] x [-ly/2,ly/2] x [-lz/2,lz/2]
1294 // // drot/dq = drot/dr . dr/dq = dRot/dr . S, since r=Sq
1295 //
1296 // double xi=ploc.X();
1297 //
1298 // Vector3D rdx = GetPosx(xi);
1299 // Vector3D d = GetDirector(xi);
1300 // double angle = GetRot(xi);
1301 //
1302 // // rot = (rot11 rot12 rot13 rot21 rot22 rot23 rot31 rot32 rot33)
1303 // // r = (r1', r2', r3', d1, d2, d3, angle) //notice, (d1,d2,d3)/dq = (0,0,0)
1304 // // r_pos = (r1', r2', r3')
1305 // // r_rot = (angle)
1306 // Matrix drotdrpos(Dim()*Dim(),3);
1307 //
1308 // //drotdrpos =
1309 // // [dA11dr1 dA11dr2 dA11dr3]
1310 // // [dA12dr1 dA12dr2 dA12dr3]
1311 // // [dA13dr1 dA13dr2 dA13dr3]
1312 // // [dA21dr1 dA21dr2 dA21dr3]
1313 // // [dA22dr1 dA22dr2 dA22dr3]
1314 // // [dA23dr1 dA23dr2 dA23dr3]
1315 // // [dA31dr1 dA31dr2 dA31dr3]
1316 // // [dA32dr1 dA32dr2 dA32dr3]
1317 // // [dA33dr1 dA33dr2 dA33dr3]
1318 // GetdRotdrpos(drotdrpos, rdx.X(), rdx.Y(), rdx.Z(), d.X(), d.Y(), d.Z(), angle);
1319 //
1320 // Matrix drotvdrpos(Dim(),3);
1321 // for (int i=1; i<=Dim(); i++)
1322 // {
1323 // for (int j=1; j<=3; j++)
1324 // {
1325 // if (!use_transposed)
1326 // {
1327 // drotvdrpos(i,j) += vloc.X()*drotdrpos(i*Dim()-2,j) + vloc.Y()*drotdrpos(i*Dim()-1,j) + vloc.Z()*drotdrpos(i*Dim(),j);
1328 // }
1329 // else
1330 // {
1331 // drotvdrpos(i,j) += vloc.X()*drotdrpos(i,j) + vloc.Y()*drotdrpos(i+Dim(),j) + vloc.Z()*drotdrpos(i+2*Dim(),j);
1332 // }
1333 // }
1334 // }
1335 //
1336 // Matrix drotdrrot;
1337 // drotdrrot.SetSize(Dim()*Dim(),1);
1338 // GetdRotdrrot(drotdrrot, rdx.X(), rdx.Y(), rdx.Z(), d.X(), d.Y(), d.Z(), angle);
1339 //
1340 // Matrix drotvdrrot(Dim(),1);
1341 // for (int i=1; i<=Dim(); i++)
1342 // {
1343 // for (int j=1; j<=1; j++)
1344 // {
1345 // if (!use_transposed)
1346 // {
1347 // drotvdrrot(i,j) += vloc.X()*drotdrrot(i*Dim()-2,j) + vloc.Y()*drotdrrot(i*Dim()-1,j) + vloc.Z()*drotdrrot(i*Dim(),j);
1348 // }
1349 // else
1350 // {
1351 // drotvdrrot(i,j) += vloc.X()*drotdrrot(i,j) + vloc.Y()*drotdrrot(i+Dim(),j) + vloc.Z()*drotdrrot(i+2*Dim(),j);
1352 // }
1353 // }
1354 // }
1355 //
1356 // drotvdqT.SetSize(SOS(),Dim());
1357 // drotvdqT.SetAll(0.);
1358 //
1359 // for (int h=1; h<=Dim(); h++)
1360 // {
1361 // for (int i=1; i<=Dim(); i++)
1362 // {
1363 // for (int j=1; j<=NSPos(); j++)
1364 // {
1365 //#ifndef OLD_SHAPEFUNCTIONS
1366 // drotvdqT(i+Dim()*(j-1), h) += drotvdrpos(h,i)*GetSFPosx(j,xi*2./size.X());
1367 //#else
1368 // drotvdqT(i+Dim()*(j-1), h) += drotvdrpos(h,i)*GetSFPosx(j,xi);
1369 //#endif
1370 // }
1371 // }
1372 //
1373 // for (int j=1; j<=NSRot(); j++)
1374 // {
1375 // drotvdqT(SOSPos()+j, h) += drotvdrrot(h,1)*GetSFRot(j,xi);
1376 // }
1377 // }
1378 //}
1379 // method calculates gradient of (A(ploc)*vloc) with respect to generalized coordinates (gc), where
1380 // A(ploc) denotes the Rotation Matrix at the axial position ploc,
1381 // vloc denotes an input vector,
1382 // the result is returned through Matrix& drotvdqT (the T (transpose) means, that drotvdqT has
1383 // as many rows as partial derivatives and 3 columns (dimension of vector w=A(ploc)*vloc)
1384 //
1385 // IMPORTANT: if (!use_transposed), then everything is done as explained above
1386 // if (use_transposed), then vloc is multiplied with transposed of A
1387
GetdRotvdqT(const Vector3D & vloc,const Vector3D & ploc,Matrix & drotvdqT,int use_transposed)1388 void ANCFBeam3DTorsion::GetdRotvdqT(const Vector3D& vloc, const Vector3D& ploc, Matrix& drotvdqT, int use_transposed)
1389 {
1390 // ploc is in [-lx/2,lx/2] x [-ly/2,ly/2] x [-lz/2,lz/2]
1391 // drot/dq = drot/dr . dr/dq = dRot/dr . S, since r=Sq
1392
1393 double xi=ploc.X();
1394
1395 Vector3D rdx = GetPosx(xi);
1396 Vector3D d = GetDirector(xi);
1397 double angle = GetRot(xi);
1398
1399 // rot = (rot11 rot12 rot13 rot21 rot22 rot23 rot31 rot32 rot33)
1400 // r = (r1', r2', r3', d1, d2, d3, angle) //notice, (d1,d2,d3)/dq = (0,0,0)
1401 // r_pos = (r1', r2', r3')
1402 // r_rot = (angle)
1403 Matrix drotdrpos(Dim()*Dim(),3);
1404 Matrix drotdrposT(Dim()*Dim(),3);
1405
1406 //drotdrpos =
1407 // [dA11dr1 dA11dr2 dA11dr3]
1408 // [dA12dr1 dA12dr2 dA12dr3]
1409 // [dA13dr1 dA13dr2 dA13dr3]
1410 // [dA21dr1 dA21dr2 dA21dr3]
1411 // [dA22dr1 dA22dr2 dA22dr3]
1412 // [dA23dr1 dA23dr2 dA23dr3]
1413 // [dA31dr1 dA31dr2 dA31dr3]
1414 // [dA32dr1 dA32dr2 dA32dr3]
1415 // [dA33dr1 dA33dr2 dA33dr3]
1416 GetdRotdrpos(drotdrpos, rdx.X(), rdx.Y(), rdx.Z(), d.X(), d.Y(), d.Z(), angle);
1417 GetdRotdrposT(drotdrposT, rdx.X(), rdx.Y(), rdx.Z(), d.X(), d.Y(), d.Z(), angle);
1418
1419 Matrix drotvdrpos(Dim(),3);
1420 for (int i=1; i<=Dim(); i++)
1421 {
1422 for (int j=1; j<=3; j++)
1423 {
1424 if (!use_transposed)
1425 {
1426 drotvdrpos(i,j) += vloc.X()*drotdrpos(i*Dim()-2,j) + vloc.Y()*drotdrpos(i*Dim()-1,j) + vloc.Z()*drotdrpos(i*Dim(),j);
1427 }
1428 else
1429 {
1430 drotvdrpos(i,j) += vloc.X()*drotdrposT(i*Dim()-2,j) + vloc.Y()*drotdrposT(i*Dim()-1,j) + vloc.Z()*drotdrposT(i*Dim(),j);
1431 }
1432 }
1433 }
1434
1435 Matrix drotdrrot;
1436 Matrix drotdrrotT;
1437 drotdrrot.SetSize(Dim()*Dim(),1);
1438 drotdrrotT.SetSize(Dim()*Dim(),1);
1439
1440 GetdRotdrrot(drotdrrot, rdx.X(), rdx.Y(), rdx.Z(), d.X(), d.Y(), d.Z(), angle);
1441 GetdRotdrrotT(drotdrrotT, rdx.X(), rdx.Y(), rdx.Z(), d.X(), d.Y(), d.Z(), angle);
1442
1443 Matrix drotvdrrot(Dim(),1);
1444 for (int i=1; i<=Dim(); i++)
1445 {
1446 for (int j=1; j<=1; j++)
1447 {
1448 if (!use_transposed)
1449 {
1450 drotvdrrot(i,j) += vloc.X()*drotdrrot(i*Dim()-2,j) + vloc.Y()*drotdrrot(i*Dim()-1,j) + vloc.Z()*drotdrrot(i*Dim(),j);
1451 }
1452 else
1453 {
1454 drotvdrrot(i,j) += vloc.X()*drotdrrotT(i*Dim()-2,j) + vloc.Y()*drotdrrotT(i*Dim()-1,j) + vloc.Z()*drotdrrotT(i*Dim(),j);
1455 }
1456 }
1457 }
1458
1459 drotvdqT.SetSize(SOS(),Dim());
1460 drotvdqT.SetAll(0.);
1461
1462 for (int h=1; h<=Dim(); h++)
1463 {
1464 for (int i=1; i<=Dim(); i++)
1465 {
1466 for (int j=1; j<=NSPos(); j++)
1467 {
1468 #ifndef OLD_SHAPEFUNCTIONS
1469 drotvdqT(i+Dim()*(j-1), h) += drotvdrpos(h,i)*GetSFPosx(j,xi*2./size.X());
1470 #else
1471 drotvdqT(i+Dim()*(j-1), h) += drotvdrpos(h,i)*GetSFPosx(j,xi);
1472 #endif
1473 }
1474 }
1475
1476 for (int j=1; j<=NSRot(); j++)
1477 {
1478 drotvdqT(SOSPos()+j, h) += drotvdrrot(h,1)*GetSFRot(j,xi);
1479 }
1480 }
1481 }
1482
GetdRotdqT(const Vector3D & ploc,Matrix & d)1483 void ANCFBeam3DTorsion::GetdRotdqT(const Vector3D& ploc, Matrix& d)
1484 {
1485 //ploc in [-lx/2,lx/2] x [-ly/2,ly/2] x [-lz/2,lz/2]
1486 ////////////////////////////////////////////////////
1487
1488 int approach = 3; // 1..JG, 2..YV, 3..KN,PG
1489
1490 if (approach == 1)
1491 {
1492 //JG's approach (probably just for special cases)
1493 //here, the routine GetdRotvdqT has to sum up (e_j)_n v_j (instead of (e_j)_n v_n)
1494 //UO() << "dRotdq\n";
1495
1496 Vector3D p0=ploc;
1497 //p0.Scale(0.5*size.X(),0.5*size.Y(),0.5*size.Z());
1498
1499 d.SetSize(SOS(),3);
1500 d.FillWithZeros(); //needed???
1501
1502 Matrix dAvdq(SOS(),3);
1503 double x = ploc.X();
1504
1505 Matrix3D AT = GetRotMatrix(ploc).GetTp();
1506
1507 Vector3D v;
1508 v = Vector3D(AT(1,1),AT(2,1),AT(3,1));
1509 GetdRotvdqT(v, ploc, dAvdq, 0);
1510 for (int j=1; j <= SOS(); j++)
1511 {
1512 d(j,3) = dAvdq(j,2);
1513 d(j,2) =-dAvdq(j,3);
1514 }
1515 v = Vector3D(AT(1,2),AT(2,2),AT(3,2));
1516 GetdRotvdqT(v, ploc, dAvdq, 0);
1517 for (int j=1; j <= SOS(); j++)
1518 {
1519 d(j,1) = dAvdq(j,3);
1520 }
1521 }
1522 else if (approach == 2)
1523 {
1524 ////////////////////////////////////////////////////////////
1525 // YV's approach
1526 // let e_k denote the k-th base vector of the actual system
1527 // \delta \theta = 0.5 * (e_k) \times \delta (e_k)
1528 // (\grad \theta)_{l,m} = \eps_{ijm} (e_k)_i (\partial (e_k)_j / \partial q_l)
1529 //here, the routine GetdRotvdqT has to sum up (e_j)_n v_n (instead of (e_j)_n v_j)
1530
1531 d.SetSize(SOS(),Dim()); d.SetAll(0.);
1532 Matrix drotvdqT;
1533 drotvdqT.SetSize(SOS(),Dim());
1534 Vector3D e;
1535 Vector3D epse; // Levi-Civita-Symbol multiplyed with base vector e
1536 Matrix3D AT = GetRotMatrix(ploc).GetTp();
1537 for (int m=1; m<=Dim(); m++) {
1538 for (int k=1; k<=Dim(); k++) {
1539 e = Vector3D(AT(k,1),AT(k,2),AT(k,3));
1540 for (int j=1; j<=Dim(); j++) {
1541 epse(j) = 0.;
1542 for (int i=1; i<=Dim(); i++) {
1543 epse(j) += (i-j)*(j-m)*(m-i)*e(i);
1544 }
1545 }
1546 GetdRotvdqT(0.25*epse, ploc, drotvdqT, 1);
1547 for (int l=1; l<=SOS(); l++) {
1548 d(l,m) += drotvdqT(l,k);
1549 }
1550 }
1551 }
1552 }
1553 else
1554 {
1555 ////////////////////////////////////////////////////////////
1556 //KN&PG's approach from \cite{book_hodges}
1557 //let e_i denote the i-th base vector of the actual system (i-th column of the rotation matrix)
1558 //\delta \theta = \sum_{i=1}^3 e_i (\delta e_j . e_k) where j = i%3+1, k = j%3+1
1559 //(\grad_q \theta^T)_{l,m} = (\partial q_l/ \partial (e_j)_n) (e_k)_n (e_i)_m
1560 //here, the routine GetdRotvdqT has to sum up (e_j)_n v_n (instead of (e_j)_n v_j)
1561 //note: ploc is in [-lx/2,lx/2] x [-ly/2,ly/2] x [-lz/2,lz/2]
1562 d.SetSize(SOS(),Dim());
1563 d.FillWithZeros();
1564
1565 Matrix3D A = GetRotMatrix(ploc);
1566 //mbs->UO() << "RotMatrix = \n" << A << "\n";
1567
1568 Matrix drotvdqT(SOS(),Dim());
1569 for (int i=1; i<=Dim(); i++)
1570 {
1571 int j = i%3 + 1;
1572 int k = j%3 + 1;
1573 Vector3D ei(A(1,i), A(2,i), A(3,i));
1574 GetdRotvdqT(Vector3D(A(1,k), A(2,k), A(3,k)), ploc, drotvdqT, 1);
1575 for (int l=1; l<=SOS(); l++)
1576 for (int m=1; m<=Dim(); m++)
1577 d(l,m) += drotvdqT(l,j)*ei(m);
1578 }
1579 }
1580
1581 }
1582
1583
GetInitDirector(const double & xi) const1584 Vector3D ANCFBeam3DTorsion::GetInitDirector(const double& xi) const
1585 {
1586 Vector d = GetDataInit();
1587 Vector3D director1(d(1), d(2), d(3));
1588 Vector3D director2(d(4), d(5), d(6));
1589 return GetSFRot(1,xi)*director1 + GetSFRot(2,xi)*director2;
1590 }
1591
GetDirector(const double & xi,int flagD) const1592 Vector3D ANCFBeam3DTorsion::GetDirector(const double& xi, int flagD) const
1593 {
1594 return GetSFRot(1,xi)*GetDirector1(flagD) + GetSFRot(2,xi)*GetDirector2(flagD);
1595 }
1596
GetDirectorx(const double & xi,int flagD) const1597 Vector3D ANCFBeam3DTorsion::GetDirectorx(const double& xi, int flagD) const
1598 {
1599 return GetSFRotx(1,xi)*GetDirector1(flagD) + GetSFRotx(2,xi)*GetDirector2(flagD);
1600 }
1601
1602 //------------------------------------------------------------
1603 //computes position vector in the reference element: r_0
1604 //------------------------------------------------------------
GetInitPos3D(double xi) const1605 Vector3D ANCFBeam3DTorsion::GetInitPos3D(double xi) const
1606 {
1607 #ifndef OLD_SHAPEFUNCTIONS
1608 xi *= 2./size.X();
1609 #endif
1610 Vector3D p(0.,0.,0.);
1611 for (int i = 1; i <= Dim(); i++)
1612 {
1613 for (int j = 1; j <= NSPos(); j++)
1614 {
1615 p(i) += GetSFPos(j,xi)*(q0((j-1)*Dim()+i)); //r_0=Sq_0; (q_0 includes initial values)
1616 }
1617 }
1618 return p;
1619 }
1620
GetInitPosx3D(double xi) const1621 Vector3D ANCFBeam3DTorsion::GetInitPosx3D(double xi) const
1622 {
1623 #ifndef OLD_SHAPEFUNCTIONS
1624 xi *= 2./size.X();
1625 #endif
1626 Vector3D p(0.,0.,0.);
1627 for (int i = 1; i <= Dim(); i++)
1628 {
1629 for (int j = 1; j <= NSPos(); j++)
1630 {
1631 p(i) += GetSFPosx(j,xi)*(q0((j-1)*Dim()+i)); //rx_0=Sx q_0; (q_0 includes initial values)
1632 }
1633 }
1634 return p;
1635 }
1636
GetInitRot3D(double xi) const1637 double ANCFBeam3DTorsion::GetInitRot3D(double xi) const
1638 {
1639 double a=0;
1640 for (int j = 1; j <= NSRot(); j++)
1641 {
1642 a += GetSFRot(j,xi)*q0(SOSPos()+j);
1643 }
1644 return a;
1645 }
1646
GetInitRotx3D(double xi) const1647 double ANCFBeam3DTorsion::GetInitRotx3D(double xi) const
1648 {
1649 double a=0;
1650 for (int j = 1; j <= NSRot(); j++)
1651 {
1652 a += GetSFRotx(j,xi)*q0(SOSPos()+j);
1653 }
1654 return a;
1655 }
1656
1657 //-------
1658 //strains
1659 //-------
1660
GetGamma1(const double & xi,double & Gamma1,int flagD) const1661 void ANCFBeam3DTorsion::GetGamma1(const double& xi, double& Gamma1, int flagD) const
1662 {
1663 // Gamma1 = (|r'|-|r0'|)/(|r0'|)
1664 Vector3D rdx = GetPosx(xi,flagD);
1665 Gamma1 = rdx.Norm();
1666 rdx = GetInitPosx3D(xi);
1667 double rdxnorm = rdx.Norm();
1668 Gamma1 = (Gamma1 - rdxnorm)/rdxnorm;
1669 }
1670
GetDeltaGamma1(const double & xi,Vector & DeltaGamma1) const1671 void ANCFBeam3DTorsion::GetDeltaGamma1(const double& xi, Vector& DeltaGamma1) const
1672 {
1673 // delta gamma1 = (|r0'| |r'|)^{-1} r' . S'
1674 double fac = 1.;
1675 Vector3D rdx = GetInitPosx3D(xi);
1676 fac /= rdx.Norm();
1677 rdx = GetPosx(xi);
1678 fac /= rdx.Norm();
1679
1680 for (int i=1; i<=Dim(); i++)
1681 {
1682 for (int j=1; j<=NSPos(); j++)
1683 {
1684 #ifndef OLD_SHAPEFUNCTIONS
1685 DeltaGamma1(3*(j-1)+i) = fac*rdx(i)*GetSFPosx(j,xi*2./size.X());
1686 #else
1687 DeltaGamma1(3*(j-1)+i) = fac*rdx(i)*GetSFPosx(j,xi);
1688 #endif
1689 }
1690 }
1691
1692 DeltaGamma1(13) = DeltaGamma1(14) = 0.;
1693 }
1694
GetKappa1(const double & xi,double & Kappa1,int flagD) const1695 void ANCFBeam3DTorsion::GetKappa1(const double& xi, double& Kappa1, int flagD) const
1696 {
1697 Vector3D rx = GetPosx(xi, flagD);
1698 Vector3D rxx = GetPosxx(xi, flagD);
1699 double ang = GetRot(xi, flagD) - GetInitRot3D(xi);
1700 double angx = GetRotx(xi, flagD) - GetInitRotx3D(xi);
1701 Vector3D d = GetDirector(xi, flagD);
1702 Vector3D dx = GetDirectorx(xi, flagD);
1703
1704 Kappa1 = GetKappa1(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1705 }
1706
GetKappa2(const double & xi,double & Kappa2,int flagD) const1707 void ANCFBeam3DTorsion::GetKappa2(const double& xi, double& Kappa2, int flagD) const
1708 {
1709 Vector3D rx = GetPosx(xi, flagD);
1710 Vector3D rxx = GetPosxx(xi, flagD);
1711 double ang = GetRot(xi, flagD) - GetInitRot3D(xi);
1712 double angx = GetRotx(xi, flagD) - GetInitRotx3D(xi);
1713 Vector3D d = GetDirector(xi, flagD);
1714 Vector3D dx = GetDirectorx(xi, flagD);
1715
1716 Kappa2 = GetKappa2(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1717 }
1718
GetKappa3(const double & xi,double & Kappa3,int flagD) const1719 void ANCFBeam3DTorsion::GetKappa3(const double& xi, double& Kappa3, int flagD) const
1720 {
1721 Vector3D rx = GetPosx(xi, flagD);
1722 Vector3D rxx = GetPosxx(xi, flagD);
1723 double ang = GetRot(xi, flagD) - GetInitRot3D(xi);
1724 double angx = (GetRotx(xi, flagD) - GetInitRotx3D(xi));
1725 Vector3D d = GetDirector(xi, flagD);
1726 Vector3D dx = GetDirectorx(xi, flagD);
1727
1728 Kappa3 = GetKappa3(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1729 }
1730
GetDeltaKappa1(const double & xi,Vector & DeltaKappa1) const1731 void ANCFBeam3DTorsion::GetDeltaKappa1(const double& xi, Vector& DeltaKappa1) const //derivative of Kappa1 wrt q at xi
1732 {
1733 Vector3D rx = GetPosx(xi);
1734 Vector3D rxx = GetPosxx(xi);
1735 double ang = GetRot(xi) - GetInitRot3D(xi);
1736 double angx = GetRotx(xi) - GetInitRotx3D(xi);
1737 Vector3D d = GetDirector(xi);
1738 Vector3D dx = GetDirectorx(xi);
1739
1740 // delta kappa1 = [ d kappa1 / d (r',r'',ang,ang') ] . [ d (r',r'',ang,ang') / dq ]
1741 Vector3D kappa_pos;
1742 double kappa_angle;
1743
1744 kappa_pos = GetDKappa1DPosx(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1745 DeltaKappa1.SetAll(0.);
1746 for (int i=1; i<=Dim(); i++)
1747 {
1748 for (int j=1; j<=NSPos(); j++)
1749 {
1750 #ifndef OLD_SHAPEFUNCTIONS
1751 DeltaKappa1(i+Dim()*(j-1)) += kappa_pos(i)*GetSFPosx(j,xi*2./size.X());
1752 #else
1753 DeltaKappa1(i+Dim()*(j-1)) += kappa_pos(i)*GetSFPosx(j,xi);
1754 #endif
1755 }
1756 }
1757
1758 kappa_pos = GetDKappa1DPosxx(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1759 for (int i=1; i<=Dim(); i++)
1760 {
1761 for (int j=1; j<=NSPos(); j++)
1762 {
1763 #ifndef OLD_SHAPEFUNCTIONS
1764 DeltaKappa1(i+Dim()*(j-1)) += kappa_pos(i)*GetSFPosxx(j,xi*2./size.X());
1765 #else
1766 DeltaKappa1(i+Dim()*(j-1)) += kappa_pos(i)*GetSFPosxx(j,xi);
1767 #endif
1768 }
1769 }
1770
1771 kappa_angle = GetDKappa1DAng(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1772 for (int j=1; j<=NSRot(); j++)
1773 {
1774 DeltaKappa1(Dim()*NSPos()+j) += kappa_angle*GetSFRot(j,xi);
1775 }
1776
1777 kappa_angle = GetDKappa1DAngx(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1778 for (int j=1; j<=NSRot(); j++)
1779 {
1780 DeltaKappa1(Dim()*NSPos()+j) += kappa_angle*GetSFRotx(j,xi);
1781 }
1782 }
1783
GetDeltaKappa2(const double & xi,Vector & DeltaKappa2) const1784 void ANCFBeam3DTorsion::GetDeltaKappa2(const double& xi, Vector& DeltaKappa2) const //derivative of Kappa2 wrt q at xi
1785 {
1786 Vector3D rx = GetPosx(xi);
1787 Vector3D rxx = GetPosxx(xi);
1788 double ang = GetRot(xi) - GetInitRot3D(xi);
1789 double angx = GetRotx(xi) - GetInitRotx3D(xi);
1790 Vector3D d = GetDirector(xi);
1791 Vector3D dx = GetDirectorx(xi);
1792
1793 // delta Kappa2 = [ d Kappa2 / d (r',r'',ang,ang') ] . [ d (r',r'',ang,ang') / dq ]
1794 Vector3D kappa_pos;
1795 double kappa_angle;
1796
1797 kappa_pos = GetDKappa2DPosx(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1798 DeltaKappa2.SetAll(0.);
1799 for (int i=1; i<=Dim(); i++)
1800 {
1801 for (int j=1; j<=NSPos(); j++)
1802 {
1803 #ifndef OLD_SHAPEFUNCTIONS
1804 DeltaKappa2(i+Dim()*(j-1)) += kappa_pos(i)*GetSFPosx(j,xi*2./size.X());
1805 #else
1806 DeltaKappa2(i+Dim()*(j-1)) += kappa_pos(i)*GetSFPosx(j,xi);
1807 #endif
1808 }
1809 }
1810
1811 kappa_pos = GetDKappa2DPosxx(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1812 for (int i=1; i<=Dim(); i++)
1813 {
1814 for (int j=1; j<=NSPos(); j++)
1815 {
1816 #ifndef OLD_SHAPEFUNCTIONS
1817 DeltaKappa2(i+Dim()*(j-1)) += kappa_pos(i)*GetSFPosxx(j,xi*2./size.X());
1818 #else
1819 DeltaKappa2(i+Dim()*(j-1)) += kappa_pos(i)*GetSFPosxx(j,xi);
1820 #endif
1821 }
1822 }
1823
1824 kappa_angle = GetDKappa2DAng(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1825 for (int j=1; j<=NSRot(); j++)
1826 {
1827 DeltaKappa2(Dim()*NSPos()+j) += kappa_angle*GetSFRot(j,xi);
1828 }
1829
1830 kappa_angle = GetDKappa2DAngx(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1831 for (int j=1; j<=NSRot(); j++)
1832 {
1833 DeltaKappa2(Dim()*NSPos()+j) += kappa_angle*GetSFRotx(j,xi);
1834 }
1835 }
1836
GetDeltaKappa3(const double & xi,Vector & DeltaKappa3) const1837 void ANCFBeam3DTorsion::GetDeltaKappa3(const double& xi, Vector& DeltaKappa3) const //derivative of Kappa3 wrt q at xi
1838 {
1839 Vector3D rx = GetPosx(xi);
1840 Vector3D rxx = GetPosxx(xi);
1841 double ang = GetRot(xi) - GetInitRot3D(xi);
1842 double angx = (GetRotx(xi) - GetInitRotx3D(xi));
1843 Vector3D d = GetDirector(xi);
1844 Vector3D dx = GetDirectorx(xi);
1845
1846 // delta Kappa3 = [ d Kappa3 / d (r',r'',ang,ang') ] . [ d (r',r'',ang,ang') / dq ]
1847 Vector3D kappa_pos;
1848 double kappa_angle;
1849
1850 kappa_pos = GetDKappa3DPosx(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1851 DeltaKappa3.SetAll(0.);
1852 for (int i=1; i<=Dim(); i++)
1853 {
1854 for (int j=1; j<=NSPos(); j++)
1855 {
1856 #ifndef OLD_SHAPEFUNCTIONS
1857 DeltaKappa3(i+Dim()*(j-1)) += kappa_pos(i)*GetSFPosx(j,xi*2./size.X());
1858 #else
1859 DeltaKappa3(i+Dim()*(j-1)) += kappa_pos(i)*GetSFPosx(j,xi);
1860 #endif
1861 }
1862 }
1863
1864 kappa_pos = GetDKappa3DPosxx(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1865 for (int i=1; i<=Dim(); i++)
1866 {
1867 for (int j=1; j<=NSPos(); j++)
1868 {
1869 #ifndef OLD_SHAPEFUNCTIONS
1870 DeltaKappa3(i+Dim()*(j-1)) += kappa_pos(i)*GetSFPosxx(j,xi*2./size.X());
1871 #else
1872 DeltaKappa3(i+Dim()*(j-1)) += kappa_pos(i)*GetSFPosxx(j,xi);
1873 #endif
1874 }
1875 }
1876
1877 kappa_angle = GetDKappa3DAng(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1878 for (int j=1; j<=NSRot(); j++)
1879 {
1880 DeltaKappa3(Dim()*NSPos()+j) += kappa_angle*GetSFRot(j,xi);
1881 }
1882
1883 kappa_angle = GetDKappa3DAngx(rx.X(), rx.Y(), rx.Z(), rxx.X(), rxx.Y(), rxx.Z(), ang, angx, d.X(), d.Y(),d.Z(), dx.X(), dx.Y(), dx.Z());
1884 for (int j=1; j<=NSRot(); j++)
1885 {
1886 DeltaKappa3(Dim()*NSPos()+j) += kappa_angle*GetSFRotx(j,xi);
1887 }
1888 }
1889
1890 //------------------------------------------------------------------------------
1891 //variational formulation: Delta U (Beam3D-Paper: equation (15))
1892 //we calculate residual
1893 //------------------------------------------------------------------------------
EvalF2(Vector & f,double t)1894 void ANCFBeam3DTorsion::EvalF2(Vector& f, double t) // dynamic test example: 74.0118% of CPU Time
1895 {
1896
1897 Body3D::EvalF2(f,t);
1898
1899 static Vector fadd;//element residual
1900 fadd.SetLen(SOS());
1901 fadd.SetAll(0.);
1902
1903 double lx = size.X();
1904
1905 { // dynamic test example: 62.2240% of CPU Time
1906
1907 double beamGJ = GetMaterial().BeamGJkx();
1908 double beamEIy = GetMaterial().BeamEIy();
1909 double beamEIz = GetMaterial().BeamEIz();
1910 double beamEA = GetMaterial().BeamEA();
1911
1912 static Vector wT,xT; //integration points and weights
1913 GetIntegrationRule(xT,wT,intorder_curvature);
1914
1915 for (int i1=1; i1<=xT.GetLen(); i1++) //i1-loop over all integration points
1916 {
1917 double x = xT(i1); //x in unit configuration [-1 , 1]
1918 double xi = x*lx*0.5; //xi in scaled configuration [-lx/2 , lx/2]
1919 double det = 0.5*lx; //determinant of the jacobian (from element transformation [-1 , 1] -> [-lx/2 , lx/2])
1920
1921 double fact_kappa1= beamGJ*wT(i1)*det; // beamGJ = torsional stiffness
1922 double fact_kappa2= beamEIy*wT(i1)*det; // beamEIy = bending stiffness (in e2=y direction)
1923 double fact_kappa3= beamEIz*wT(i1)*det; // beamEIz = bending stiffness (in e3=z direction)
1924
1925
1926 ConstVector<14> DeltaKappa1; GetDeltaKappa1(xi,DeltaKappa1);
1927 double Kappa1; GetKappa1(xi,Kappa1);
1928
1929 ConstVector<14> DeltaKappa2; GetDeltaKappa2(xi,DeltaKappa2);
1930 double Kappa2; GetKappa2(xi,Kappa2);
1931
1932 ConstVector<14> DeltaKappa3; GetDeltaKappa3(xi,DeltaKappa3);
1933 double Kappa3; GetKappa3(xi,Kappa3);
1934
1935 fadd +=
1936 (fact_kappa1*Kappa1)*DeltaKappa1 + // around x axis (beam axis)
1937 (fact_kappa2*Kappa2)*DeltaKappa2 + // around y axis
1938 (fact_kappa3*Kappa3)*DeltaKappa3; // around z-axis
1939 }
1940
1941 GetIntegrationRule(xT,wT,intorder_axial_strain);
1942 for (int i1=1; i1<=xT.GetLen(); i1++) //i1-loop over all integration points
1943 {
1944 double x = xT(i1); //x in unit configuration [-1 , 1]
1945 double xi = x*lx*0.5; //xi in scaled configuration [-lx/2 , lx/2]
1946 double det = 0.5*lx; //determinant of the jacobian (from element transformation [-1 , 1] -> [-lx/2 , lx/2])
1947
1948 double fact_gamma1= beamEA*wT(i1)*det; // beamEA = axial stiffness
1949
1950 ConstVector<14> DeltaGamma1; GetDeltaGamma1(xi,DeltaGamma1);
1951 double Gamma1; GetGamma1(xi,Gamma1);
1952
1953 fadd +=
1954 (fact_gamma1*Gamma1)*DeltaGamma1;
1955 }
1956
1957 //Residual:
1958 //in ANCFBeam3DTorsion::EvalF2:
1959 //from Element::EvalF2 -> Loads, Constraints (=f)
1960 //additional -> fadd = Ku
1961 //f-Ku (right hand side of second order DE) -> return value
1962 f -= fadd; //f=f-fadd; Ku=f -> Residual=f-Ku, Ku=fadd
1963 }
1964
1965 { // dynamic test example: 10.3733% of CPU Time
1966 //// add quadratic velocity vector
1967 if (!mbs->GetSolSet().dostaticcomputation && !GetMBS()->IsJacobianComputation() && kinematic_computation_mode != 2)
1968 {
1969 EvalQVV(fadd,t);
1970 f -= fadd;
1971 }
1972 }
1973 }
1974
EvalQVV(Vector & f,double t)1975 void ANCFBeam3DTorsion::EvalQVV(Vector& f, double t)
1976 {
1977 f.SetAll(0.);
1978
1979 double det = 0.5*size.X();
1980 ConstVector<14> qvv(14, 1); //nofill
1981
1982 if (kinematic_computation_mode == 0)
1983 {
1984 Vector x1, w1;
1985 GetIntegrationRule(x1,w1,intorder_mass);
1986
1987 for (int i1=1; i1<=x1.GetLen(); i1++)
1988 {
1989 double xi = x1(i1)*det;
1990 GetQuadraticVelocityVector(xi, qvv); //get quadratic velocity vector at integration point
1991 f += (det*w1(i1))*qvv;
1992 }
1993 }
1994 else if (kinematic_computation_mode == 1)
1995 {
1996 for (int n=1; n<=2; n++) // 2nd order Lobatto integration (IPs are at node n=1 and n=2)
1997 {
1998 GetQuadraticVelocityVectorAtNode(qvv, n); // determinant multiplied inside!
1999 f += qvv;
2000 }
2001 }
2002 }
2003
EvalM(Matrix & m,double t)2004 void ANCFBeam3DTorsion::EvalM(Matrix& m, double t)
2005 {
2006 if (kinematic_computation_mode == 2) // 2 ... approximate mass matrix (torsional terms approximated), no quadratic velocity vector (fastest)
2007 {
2008 if (massmatrix.Getcols() == SOS())
2009 {
2010 m = massmatrix;
2011 return;
2012 }
2013 else
2014 {
2015 m.SetAll(0);
2016 // space dimension, = 3
2017 int dim = Dim();
2018 // number of shape functions
2019 int nspos = NSPos();
2020 int nsrot = NSRot();
2021 // storage vector for shape functions
2022 Vector SVpos(nspos);
2023 Vector SVrot(nsrot);
2024 // shape function matrix
2025 // (r1 ) ( Spos1 0 0 Spos2 0 0 Spos3 0 0 Spos4 0 0 0 0 )
2026 // (r2 ) = ( 0 Spos1 0 0 Spos2 0 0 Spos3 0 0 Spos4 0 0 0 ) q^T
2027 // (r3 ) ( 0 0 Spos1 0 0 Spos2 0 0 Spos3 0 0 Spos4 0 0 )
2028 // (ang) ( 0 0 0 0 0 0 0 0 0 0 0 0 ///////////////////Srot1 Srot2 )
2029
2030 Matrix HL(SOS(),dim+1);
2031
2032 // integration rule
2033 Vector x1, w1;
2034 GetIntegrationRule(x1,w1,intorder_mass);
2035
2036 // material parameters
2037 double rhoA = GetMaterial().BeamRhoA();
2038 double rhoIx = GetMaterial().BeamRhoIx();
2039
2040 for (int i1=1; i1<=x1.GetLen(); i1++)
2041 {
2042 double x0 = x1(i1); //in [-1,1]
2043 double xi = x0*size.X()*0.5; //in [-lx/2, lx/2]
2044 #ifndef OLD_SHAPEFUNCTIONS
2045 GetShapesPos(SVpos, x0);
2046 #else
2047 GetShapesPos(SVpos, xi);
2048 #endif
2049 GetShapesRot(SVrot, xi);
2050
2051 // fill in matrix HL
2052 for (int i=1; i<=nspos; i++)
2053 {
2054 for (int j=1; j<=dim; j++)
2055 {
2056 HL((i-1)*dim+j,j) = SVpos(i);
2057 }
2058 }
2059 for (int i=1; i<=nsrot; i++)
2060 {
2061 HL(nspos*dim+i,4) = SVrot(i);
2062 }
2063
2064 // jacobi determinant
2065 Vector3D r0x = GetInitPosx3D(xi); //this should be the initial and not the current configuration!
2066 double rx0n = r0x.Norm();
2067 rx0n = 1; //
2068 double det = 0.5*size.X()*rx0n;
2069 // add to mass matrix
2070 m += det * w1(i1) * rhoA * (HL*HL.GetTp());
2071 }
2072
2073 for (int i=1; i<=nsrot; i++)
2074 {
2075 for (int j=1; j<=nsrot; j++)
2076 {
2077 m(dim*nspos+i,dim*nspos+j) *= rhoIx/rhoA;
2078 }
2079 }
2080
2081 massmatrix = m;
2082 }
2083 }
2084 else if (kinematic_computation_mode == 0 || kinematic_computation_mode == 1) // kinematic_computation_mode: 0 ... exact terms, 5th order gaussian integration (slow);
2085 {
2086 m.SetAll(0);
2087
2088 ConstMatrix<14*14> m_at_ip(14,14,1); //storage for mass matrix at integration point (nofill)
2089 double det = 0.5*size.X();
2090 Vector x1, w1;
2091 GetIntegrationRule(x1,w1,intorder_mass);
2092
2093 for (int i1=1; i1<=x1.GetLen(); i1++)
2094 {
2095 double xi = x1(i1)*det;
2096 GetM(xi, m_at_ip); //get mass matrix at integration point
2097 m += (det*w1(i1))*m_at_ip;
2098 }
2099 }
2100 //else // commented out: too inaccurate approximation, above exact evaluation of GetM (at IP) is not CPU-time consuming compared to QVV kinematic_computation_mode: 1 ... exact terms, low order (1st order lobatto) integration (fast);
2101 //{
2102 // m.SetAll(0);
2103 // double det = 0.5*size.X();
2104 // double det_rho_A = det*GetMaterial().BeamRhoA();
2105 // {
2106 // // evaluation at left node
2107 // TArray<double> de;
2108 // Getdeidposx_and_deidtheta(de,XG(4)+q0(4),XG(5)+q0(5),XG(6)+q0(6),XG(13)+q0(13),XData(1),XData(2),XData(3));
2109 // Matrix3D de2dposx(de(1),de(4),de(7),de(2),de(5),de(8),de(3),de(6),de(9));
2110 // Matrix3D de3dposx(de(13),de(16),de(19),de(14),de(17),de(20),de(15),de(18),de(21));
2111 // Vector3D de2dtheta(de(10),de(11),de(12));
2112 // Vector3D de3dtheta(de(22),de(23),de(24));
2113
2114 // Matrix3D m2 = GetMaterial().BeamRhoIz()*de2dposx.GetTp()*de2dposx + GetMaterial().BeamRhoIy()*de3dposx.GetTp()*de3dposx;
2115 // for (int i=1; i<=3 ; i++)
2116 // {
2117 // m(i,i) = det_rho_A*1.;
2118 // for (int j=1; j<=3 ; j++)
2119 // {
2120 // m(3+i,3+j) = det*m2(i,j);
2121 // }
2122 // }
2123 // m(13,13) = det*(GetMaterial().BeamRhoIz()*de2dtheta*de2dtheta + GetMaterial().BeamRhoIy()*de3dtheta*de3dtheta);
2124 // }
2125 // {
2126 // // evaluation at right node
2127 // TArray<double> de;
2128 // Getdeidposx_and_deidtheta(de,XG(10)+q0(10),XG(11)+q0(11),XG(12)+q0(12),XG(14)+q0(14),XData(4),XData(5),XData(6));
2129 // Matrix3D de2dposx(de(1),de(4),de(7),de(2),de(5),de(8),de(3),de(6),de(9));
2130 // Matrix3D de3dposx(de(13),de(16),de(19),de(14),de(17),de(20),de(15),de(18),de(21));
2131 // Vector3D de2dtheta(de(10),de(11),de(12));
2132 // Vector3D de3dtheta(de(22),de(23),de(24));
2133
2134 // Matrix3D m2 = GetMaterial().BeamRhoIz()*de2dposx.GetTp()*de2dposx + GetMaterial().BeamRhoIy()*de3dposx.GetTp()*de3dposx;
2135 // for (int i=1; i<=3 ; i++)
2136 // {
2137 // m(6+i,6+i) = det_rho_A*1.;
2138 // for (int j=1; j<=3 ; j++)
2139 // {
2140 // m(9+i,9+j) = det*m2(i,j);
2141 // }
2142 // }
2143 // m(14,14) = det*(GetMaterial().BeamRhoIz()*de2dtheta*de2dtheta + GetMaterial().BeamRhoIy()*de3dtheta*de3dtheta);
2144 // }
2145 //}
2146 };
2147
2148
PostNewtonStep(double t)2149 double ANCFBeam3DTorsion::PostNewtonStep(double t)
2150 {
2151 if (do_update_directors)
2152 {
2153 Vector3D r1dx, r2dx;
2154 double theta1, theta2;
2155
2156 r1dx.X() = q0(4) + XG(4);
2157 r1dx.Y() = q0(5) + XG(5);
2158 r1dx.Z() = q0(6) + XG(6);
2159 r2dx.X() = q0(10) + XG(10);
2160 r2dx.Y() = q0(11) + XG(11);
2161 r2dx.Z() = q0(12) + XG(12);
2162
2163 theta1 = q0(13) + XG(13);
2164 theta2 = q0(14) + XG(14);
2165
2166 int err = UpdateDirectors(r1dx, r2dx, theta1, theta2); // returns 1 in case update was not possible (old director colinear with slope), and 0 else
2167
2168 // return error for nonlinear iteration,
2169 // if the sum of these return value (over all elements) is larger than mbs->Discontinuous(),
2170 // then the Discontinuous iteration step is repeated.
2171 // If this step is repeated a several times, then the time/load increment is reduced by a factor,
2172 // see e.g. SolverOptions.Static.load_inc_up or SolverOptions.Static.load_inc_down
2173 return (mbs->DiscontinuousAccuracy() + 1.)*err;
2174 }
2175
2176 return 0.;
2177 }
2178
2179
2180
2181 //for visualization
GetPos3D0D(const Vector3D & p_loc) const2182 Vector3D ANCFBeam3DTorsion::GetPos3D0D(const Vector3D& p_loc) const
2183 {
2184 Vector3D plocscaled;
2185 plocscaled(1)=p_loc(1)*size.X()/2.;
2186 plocscaled(2)=p_loc(2)*size.Y()/2.;
2187 plocscaled(3)=p_loc(3)*size.Z()/2.;
2188 return GetPos(plocscaled(1),1) + GetRotMatrix(plocscaled(1), 1)*Vector3D(0., plocscaled.Y(), plocscaled.Z());
2189 };
2190
GetPos3D0D(const Vector3D & p_loc,double defscale) const2191 Vector3D ANCFBeam3DTorsion::GetPos3D0D(const Vector3D& p_loc, double defscale) const
2192 {
2193 Vector3D plocscaled;
2194 plocscaled(1)=p_loc(1)*size.X()/2.;
2195 plocscaled(2)=p_loc(2)*size.Y()/2.;
2196 plocscaled(3)=p_loc(3)*size.Z()/2.;
2197 return GetPos(plocscaled(1),1) + GetRotMatrix(plocscaled(1), 1)*Vector3D(0., plocscaled.Y(), plocscaled.Z());
2198 };
2199
2200
2201
2202
2203
2204
2205 static bool test_output_written = false;
StartTimeStep()2206 void ANCFBeam3DTorsion::StartTimeStep()
2207 {
2208 //int test_output_at_TIit = 1;
2209
2210 //if(mbs->GetTIit() == test_output_at_TIit)
2211 //{
2212 // if (GetNode(1).NodeNum() == 2 || GetNode(1).NodeNum() == 8 || GetNode(1).NodeNum() == 14)
2213 // {
2214 // ConstMatrix<14*14> m(14,14,1);
2215 // ConstVector<14> qvv(14,1);
2216 // EvalM(m,GetMBS()->GetTime());
2217 // EvalQVV(qvv,GetMBS()->GetTime());
2218
2219 // mbs->UO() << "\nmode " << kinematic_computation_mode << ":\n";
2220 // mbs->UO() << "Mass Matrix in mode " << kinematic_computation_mode << ":\n";
2221 // mbs->UO() << m << "\n";
2222 // mbs->UO() << "Quadratic Velocity vector:\n";
2223 // mbs->UO() << qvv << "\n";
2224 // mbs->UO() << "Node Position:\n";
2225 // mbs->UO() << GetNode(1).Pos() << "\n";
2226 // }
2227 //}
2228
2229 // if (kinematic_computation_mode == 0)
2230 // {
2231 // for (int n=1; n<=2; n++)
2232 // {
2233 // double xi;
2234 // if (n==1)
2235 // {
2236 // mbs->UO() << "left node (mode 0) -------------------------- :\n";
2237 // xi = -size.X()*0.5;
2238 // }
2239 // else
2240 // {
2241 // mbs->UO() << "right node (mode 0) -------------------------- :\n";
2242 // xi = size.X()*0.5;
2243 // }
2244 //
2245 // ConstMatrix<3*3> de2dposx(3,3,1);
2246 // ConstMatrix<3*3> de3dposx(3,3,1);
2247 // ConstVector<3> de3dtheta(3,1);
2248 // ConstVector<3> de2dtheta(3,1);
2249 // //ConstMatrix<3*3*3> dde2dposxdposx(3,3*3,1);
2250 // //ConstMatrix<3*3*3> dde3dposxdposx(3,3*3,1);
2251 // ConstMatrix<3*3> dde2dthetadposx(3,3,1);
2252 // ConstMatrix<3*3> dde3dthetadposx(3,3,1);
2253 // ConstVector<3> dde2dthetadtheta(3,1);
2254 // ConstVector<3> dde3dthetadtheta(3,1);
2255
2256 //
2257 // Getdeidposx(xi, 2, de2dposx);
2258 // Getdeidposx(xi, 3, de3dposx);
2259 // Getdeidrot(xi, 2, de2dtheta);
2260 // Getdeidrot(xi, 3, de3dtheta);
2261 // //Getddeidposxdposx(xi, 2, dde2dposxdposx);
2262 // //Getddeidposxdposx(xi, 3, dde3dposxdposx);
2263 // Getddeidposxdrot(xi,2,dde2dthetadposx);
2264 // Getddeidposxdrot(xi,3,dde3dthetadposx);
2265 // Getddeidrotdrot(xi,2,dde2dthetadtheta);
2266 // Getddeidrotdrot(xi,3,dde3dthetadtheta);
2267 //
2268 // Matrix3D Dde2dposx;
2269 // Matrix3D Dde3dposx;
2270 // Vector3D Dde2dtheta;
2271 // Vector3D Dde3dtheta;
2272 // Vector3D Ddde2dthetadtheta;
2273 // Vector3D Ddde3dthetadtheta;
2274 // Matrix3D Ddde2dthetadposx;
2275 // Matrix3D Ddde3dthetadposx;
2276 // for (int i=1; i<=3; i++)
2277 // {
2278 // Ddde2dthetadtheta(i)=dde2dthetadtheta(i);
2279 // Ddde3dthetadtheta(i)=dde3dthetadtheta(i);
2280
2281 // Dde2dtheta(i) = de2dtheta(i);
2282 // Dde3dtheta(i) = de3dtheta(i);
2283
2284 // for (int j=1; j<=3; j++)
2285 // {
2286 // Ddde2dthetadposx(i,j)=dde2dthetadposx(i,j);
2287 // Ddde3dthetadposx(i,j)=dde3dthetadposx(i,j);
2288
2289 // Dde2dposx(i,j) = de2dposx(i,j);
2290 // Dde3dposx(i,j) = de3dposx(i,j);
2291 // }
2292 // }
2293
2294 // //Matrix3D dde2dposxdposx1;
2295 // //Matrix3D dde2dposxdposx2;
2296 // //Matrix3D dde2dposxdposx3;
2297 // //Matrix3D dde3dposxdposx1;
2298 // //Matrix3D dde3dposxdposx2;
2299 // //Matrix3D dde3dposxdposx3;
2300
2301 // for (int i=1; i<=3; i++)
2302 // {
2303 // for (int j=1; j<=3; j++)
2304 // {
2305 // //dde2dposxdposx1(i,j)=dde2dposxdposx(i,j);
2306 // //dde2dposxdposx2(i,j)=dde2dposxdposx(i,j+3);
2307 // //dde2dposxdposx3(i,j)=dde2dposxdposx(i,j+6);
2308 // //dde3dposxdposx1(i,j)=dde3dposxdposx(i,j);
2309 // //dde3dposxdposx2(i,j)=dde3dposxdposx(i,j+3);
2310 // //dde3dposxdposx3(i,j)=dde3dposxdposx(i,j+6);
2311
2312 // }
2313 // }
2314 //
2315 // mbs->UO() << "de2dposx =\n" << Dde2dposx;
2316 // mbs->UO() << "de3dposx =\n" << Dde3dposx;
2317 // mbs->UO() << "de2dtheta =\n" << Dde2dtheta << "\n";
2318 // mbs->UO() << "de3dtheta =\n" << Dde3dtheta << "\n";
2319 // //mbs->UO() << "dde2dposxdposx1 =\n" << dde2dposxdposx1;
2320 // //mbs->UO() << "dde2dposxdposx2 =\n" << dde2dposxdposx2;
2321 // //mbs->UO() << "dde2dposxdposx3 =\n" << dde2dposxdposx3;
2322 // //mbs->UO() << "dde3dposxdposx1 =\n" << dde3dposxdposx1;
2323 // //mbs->UO() << "dde3dposxdposx2 =\n" << dde3dposxdposx2;
2324 // //mbs->UO() << "dde3dposxdposx3 =\n" << dde3dposxdposx3;
2325 // mbs->UO() << "dde2dthetadposx =\n" << Ddde2dthetadposx;
2326 // mbs->UO() << "dde3dthetadposx =\n" << Ddde3dthetadposx;
2327 // mbs->UO() << "dde2dthetadtheta =\n" << Ddde2dthetadtheta << "\n";
2328 // mbs->UO() << "dde3dthetadtheta =\n" << Ddde3dthetadtheta << "\n";
2329
2330 // /*for (int k=1; k<=14; k++)
2331 // {
2332 // ConstMatrix<9*14> dLdq
2333 // }*/
2334 // ConstMatrix<9*14> L0(9,14,1);
2335 // GetL0(xi, L0);
2336 // mbs->UO() << "L0 =\n" << L0;
2337 //
2338 // ConstMatrix<9*14> dL0dqk(9,14,1);
2339 // GetdL0dqk(xi, 12+n, dL0dqk);
2340 // mbs->UO() << "dL0dqk =\n" << dL0dqk;
2341
2342 // ConstVector<14> qdot(14);
2343 // for (int k=1; k<=14; k++)
2344 // {
2345 // qdot(k)=XGP(k);
2346 // }
2347 // double Iz = GetMaterial().BeamRhoIz();
2348 // double Iy = GetMaterial().BeamRhoIy();
2349 // ConstMatrix<9*9> D(9,9);
2350 // for (int i=1; i<=9; i++)
2351 // {
2352 // D(i,i) = (i<4)?GetMaterial().BeamRhoA():((i<7)?Iz:Iy);
2353 // }
2354 // ConstVector<9> L0_qdot(9); L0_qdot=D*L0*qdot;
2355 // ConstVector<9> dL0dqk_qdot(9); dL0dqk_qdot=dL0dqk*qdot;
2356 // double L0_qdot_dL0dqk_qdot = 0;
2357 // for (int a=1; a<=9; a++) L0_qdot_dL0dqk_qdot += L0_qdot(a)*dL0dqk_qdot(a);
2358 // double det=0.5*size.X();
2359 // double qvv12n = det*0.5*L0_qdot_dL0dqk_qdot;
2360
2361 // mbs->UO() << "qdot =\n" << qdot << "\n";
2362 // mbs->UO() << "L0_qdot =\n" << L0_qdot << "\n";
2363 // mbs->UO() << "Iz = " << Iz << ", Iy = " << Iy << "\n";
2364 // mbs->UO() << "D =\n" << D << "\n";
2365 // mbs->UO() << "dL0dqk_qdot =\n" << dL0dqk_qdot << "\n";
2366 // mbs->UO() << "L0_qdot_D_dL0dqk_qdot = " << L0_qdot_dL0dqk_qdot << "\n";
2367 // mbs->UO() << "det = " << det << "\n";
2368 // mbs->UO() << "qvv(" << 12+n << ") = " << qvv12n << "\n";
2369 // }
2370 // }
2371 // else if (kinematic_computation_mode == 1)
2372 // {
2373 // for (int n=1; n<=2; n++)
2374 // {
2375 // if (n==1)
2376 // {
2377 // mbs->UO() << "left node (mode 1) -------------------------- :\n";
2378 // }
2379 // else
2380 // {
2381 // mbs->UO() << "right node (mode 1) -------------------------- :\n";
2382 // }
2383 //
2384 // int offset_ang = n-1;
2385 // int offset_dir = 3*offset_ang;
2386 // int offset_pos = 6*offset_ang;
2387
2388 // double Iy = GetMaterial().BeamRhoIy();
2389 // double Iz = GetMaterial().BeamRhoIz();
2390
2391 // // evaluation at left node
2392 // double drdx1 = XG(4+offset_pos)+q0(4+offset_pos);
2393 // double drdx2 = XG(5+offset_pos)+q0(5+offset_pos);
2394 // double drdx3 = XG(6+offset_pos)+q0(6+offset_pos);
2395 // double theta = XG(13+offset_ang)+q0(13+offset_ang);
2396 // double d1 = XData(1+offset_dir);
2397 // double d2 = XData(2+offset_dir);
2398 // double d3 = XData(3+offset_dir);
2399 // Vector3D qdotpos(XGP(4+offset_pos),XGP(5+offset_pos),XGP(6+offset_pos));
2400 // double qdottheta(XGP(13+offset_ang));
2401
2402 // TArray<double> de, de11, de21, de31, de22, de32, de33, de4, de44;
2403
2404 // Getdeidposx_and_deidtheta(de,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2405 // //Getddeidposx1dposx1(de11,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2406 // //Getddeidposx2dposx1(de21,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2407 // //Getddeidposx3dposx1(de31,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2408 // //Getddeidposx2dposx2(de22,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2409 // //Getddeidposx3dposx2(de32,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2410 // //Getddeidposx3dposx3(de33,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2411 // Getddeidthetadposx(de4,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2412 // Getddeidthetadtheta(de44,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2413
2414 // Matrix3D de2dposx(de(1),de(4),de(7),de(2),de(5),de(8),de(3),de(6),de(9));
2415 // Matrix3D de3dposx(de(13),de(16),de(19),de(14),de(17),de(20),de(15),de(18),de(21));
2416 // Vector3D de2dtheta(de(10),de(11),de(12));
2417 // Vector3D de3dtheta(de(22),de(23),de(24));
2418 // //Matrix3D dde2dposxdposx1(de11(1),de21(1),de31(1),de11(2),de21(2),de31(2),de11(3),de21(3),de31(3));
2419 // //Matrix3D dde3dposxdposx1(de11(4),de21(4),de31(4),de11(5),de21(5),de31(5),de11(6),de21(6),de31(6));
2420 // //Matrix3D dde2dposxdposx2(de21(1),de22(1),de32(1),de21(2),de22(2),de32(2),de21(3),de22(3),de32(3));
2421 // //Matrix3D dde3dposxdposx2(de21(4),de22(4),de32(4),de21(5),de22(5),de32(5),de21(6),de22(6),de32(6));
2422 // //Matrix3D dde2dposxdposx3(de31(1),de32(1),de33(1),de31(2),de32(2),de33(2),de31(3),de32(3),de33(3));
2423 // //Matrix3D dde3dposxdposx3(de31(4),de32(4),de33(4),de31(5),de32(5),de33(5),de31(6),de32(6),de33(6));
2424 // Matrix3D dde2dthetadposx(de4(1),de4(4),de4(7),de4(2),de4(5),de4(8),de4(3),de4(6),de4(9));
2425 // Matrix3D dde3dthetadposx(de4(10),de4(13),de4(16),de4(11),de4(14),de4(17),de4(12),de4(15),de4(18));
2426 // Vector3D dde2dthetadposx1(de4(1),de4(2),de4(3));
2427 // Vector3D dde3dthetadposx1(de4(10),de4(11),de4(12));
2428 // Vector3D dde2dthetadposx2(de4(4),de4(5),de4(6));
2429 // Vector3D dde3dthetadposx2(de4(13),de4(14),de4(15));
2430 // Vector3D dde2dthetadposx3(de4(7),de4(8),de4(9));
2431 // Vector3D dde3dthetadposx3(de4(16),de4(17),de4(18));
2432 // Vector3D dde2dthetadtheta(de44(1),de44(2),de44(3));
2433 // Vector3D dde3dthetadtheta(de44(4),de44(5),de44(6));
2434
2435 // mbs->UO() << "de2dposx =\n" << de2dposx;
2436 // mbs->UO() << "de3dposx =\n" << de3dposx;
2437 // mbs->UO() << "de2dtheta =\n" << de2dtheta << "\n";
2438 // mbs->UO() << "de3dtheta =\n" << de3dtheta << "\n";
2439 // //mbs->UO() << "dde2dposxdposx1 =\n" << dde2dposxdposx1;
2440 // //mbs->UO() << "dde2dposxdposx2 =\n" << dde2dposxdposx2;
2441 // //mbs->UO() << "dde2dposxdposx3 =\n" << dde2dposxdposx3;
2442 // //mbs->UO() << "dde3dposxdposx1 =\n" << dde3dposxdposx1;
2443 // //mbs->UO() << "dde3dposxdposx2 =\n" << dde3dposxdposx2;
2444 // //mbs->UO() << "dde3dposxdposx3 =\n" << dde3dposxdposx3;
2445 // mbs->UO() << "dde2dthetadposx =\n" << dde2dthetadposx;
2446 // mbs->UO() << "dde3dthetadposx =\n" << dde3dthetadposx;
2447 // mbs->UO() << "dde2dthetadtheta =\n" << dde2dthetadtheta << "\n";
2448 // mbs->UO() << "dde3dthetadtheta =\n" << dde3dthetadtheta << "\n";
2449
2450 // Vector3D qdot_de2dposx = de2dposx*(Iz*qdotpos);
2451 // Vector3D qdot_de2dtheta = (Iz*qdottheta)*de2dtheta;
2452 // Vector3D qdot_de3dposx = de3dposx*(Iy*qdotpos);
2453 // Vector3D qdot_de3dtheta = (Iy*qdottheta)*de3dtheta;
2454
2455 // Vector3D dde2dthetadtheta_qdot = dde2dthetadtheta*qdottheta;
2456 // Vector3D dde3dthetadtheta_qdot = dde3dthetadtheta*qdottheta;
2457 // Vector3D dde2dposxdtheta_qdot = dde2dthetadposx*qdotpos;
2458 // Vector3D dde3dposxdtheta_qdot = dde3dthetadposx*qdotpos;
2459
2460
2461 // mbs->UO() << "qdotpos = " << qdotpos << "\n";
2462 // mbs->UO() << "qdottheta = " << qdottheta << "\n";
2463 // mbs->UO() << "dde2dposxdtheta_qdot =\n" << dde2dposxdtheta_qdot << "\n";
2464 // mbs->UO() << "dde3dposxdtheta_qdot =\n" << dde3dposxdtheta_qdot << "\n";
2465 // mbs->UO() << "dde2dthetadtheta_qdot =\n" << dde2dthetadtheta_qdot << "\n";
2466 // mbs->UO() << "dde3dthetadtheta_qdot =\n" << dde3dthetadtheta_qdot << "\n";
2467 // mbs->UO() << "dL02dq_qdot =\n" << dde2dposxdtheta_qdot+dde2dthetadtheta_qdot << "\n";
2468 // mbs->UO() << "dL03dq_qdot =\n" << dde3dposxdtheta_qdot+dde3dthetadtheta_qdot << "\n";
2469 // mbs->UO() << "Iz = " << Iz << ", Iy = " << Iy << "\n";
2470 // mbs->UO() << "qdot_de2dposx = de2dposx*(Iz*qdotpos) =\n" << qdot_de2dposx << "\n";
2471 // mbs->UO() << "qdot_de2dtheta = (Iz*qdottheta)*de2dtheta =\n" << qdot_de2dtheta << "\n";
2472 // mbs->UO() << "L02_qdot =\n" << qdot_de2dposx+qdot_de2dtheta << "\n";
2473 // mbs->UO() << "qdot_de3dposx = de3dposx*(Iy*qdotpos) =\n" << qdot_de3dposx << "\n";
2474 // mbs->UO() << "qdot_de3dtheta = (Iy*qdottheta)*de3dtheta =\n" << qdot_de3dtheta << "\n";
2475 // mbs->UO() << "L03_qdot =\n" << qdot_de3dposx+qdot_de3dtheta << "\n";
2476
2477 // mbs->UO() << "fac = " << 0.25*size.X() << "\n";
2478 //
2479
2480 // //double ftheta = (qdot_de2dposx+qdot_de2dtheta)*(dde2dposxdtheta_qdot+dde2dthetadtheta_qdot) + (qdot_de3dposx+qdot_de3dtheta)*(dde3dposxdtheta_qdot+dde3dthetadtheta_qdot);
2481
2482 // }
2483 // }
2484 // }
2485 //}
2486 //
2487 //if(mbs->GetTIit() > test_output_at_TIit)
2488 //{
2489 // GetMBS()->StopCalculation();
2490 //}
2491
2492
2493 // int test_output_at_TIit = mbs->GetModelDataContainer()->TreeGetInt("ANCFBeam3DTorsionTest.test_output_at_TIit", 0);
2494 //
2495 // if (test_output_at_TIit < 0)
2496 // {
2497 // return;
2498 // }
2499 //
2500 // if(mbs->GetTIit() > test_output_at_TIit)
2501 // {
2502 // GetMBS()->GetSolSet().endtime = GetMBS()->GetTime();
2503 // }
2504 //
2505 // if(mbs->GetTIit() == test_output_at_TIit && !test_output_written)
2506 // {
2507 // double xi = 0.38729833;
2508 // double x0 = xi*2./size.X();
2509 //
2510 // Vector xg(SOS()); for (int i=1; i<=SOS(); i++) xg(i) = XG(i);
2511 // //--------------------------------------------------------------
2512 // ConstMatrix<9*14> dL0dq1(9,14,1); GetdL0dqk(xi, 1, dL0dq1);
2513 // ConstMatrix<3*3*3> dde2dposxdposx(3,3*3,1); Getddeidposxdposx(xi, 2, dde2dposxdposx);
2514 // ConstMatrix<3*3*3> dde3dposxdposx(3,3*3,1); Getddeidposxdposx(xi, 3, dde3dposxdposx);
2515 // ConstMatrix<3*3> dde2dposxdrot(3,3,1); Getddeidposxdrot(xi, 2, dde2dposxdrot);
2516 // ConstMatrix<3*3> dde3dposxdrot(3,3,1); Getddeidposxdrot(xi, 3, dde3dposxdrot);
2517 // ConstVector<3> dde2drotdrot(3,1); Getddeidrotdrot(xi, 2, dde2drotdrot);
2518 // ConstVector<3> dde3drotdrot(3,1); Getddeidrotdrot(xi, 3, dde3drotdrot);
2519 // ConstMatrix<3*3*3> dde20dposxdposx(3,3*3,1); Getddei0dposxdposx(xi, 2, dde20dposxdposx);
2520 // ConstMatrix<3*3*3> dde30dposxdposx(3,3*3,1); Getddei0dposxdposx(xi, 3, dde30dposxdposx);
2521 // ConstMatrix<3*3*3> dde20hatdposxdposx(3,3*3,1); Getddei0hatdposxdposx(xi, 2, dde20hatdposxdposx);
2522 // ConstMatrix<3*3*3> dde30hatdposxdposx(3,3*3,1); Getddei0hatdposxdposx(xi, 3, dde30hatdposxdposx);
2523 // ConstMatrix<3*3> de20hatdposx(3,3,1); Getdei0hatdposx(xi, 2, de20hatdposx);
2524 // ConstMatrix<3*3> de30hatdposx(3,3,1); Getdei0hatdposx(xi, 3, de30hatdposx);
2525 // ConstVector<3> e20hat(3,1); Getei0hat(xi, 2, e20hat);
2526 // ConstVector<3> e30hat(3,1); Getei0hat(xi, 3, e30hat);
2527 // ConstMatrix<3*3*3> dde30hatde1de1(3,3*3,1); Getdde30hatde1de1(xi, dde30hatde1de1);
2528 // ConstMatrix<3*3*3> dde1dposxdposx(3,3*3,1); Getdde1dposxdposx(xi, dde1dposxdposx);
2529 // ConstMatrix<3*3> de1dposx(3,3,1); Getde1dposx(xi, de1dposx);
2530 // ConstMatrix<3*3> de30hatde1(3,3,1); Getde30hatde1(xi, de30hatde1);
2531 // //--------------------------------------------------------------
2532 // ConstMatrix<9*14> L0(9,14,1); GetL0(xi, L0);
2533 // ConstMatrix<3*14> de2dq(3, 14, 1); Getdeidq(xi, 2, de2dq);
2534 // ConstMatrix<3*14> de3dq(3, 14, 1); Getdeidq(xi, 3, de3dq);
2535 // ConstMatrix<3*3> de2dposx(3,3,1); Getdeidposx(xi, 2, de2dposx);
2536 // ConstMatrix<3*3> de3dposx(3,3,1); Getdeidposx(xi, 3, de3dposx);
2537 // ConstMatrix<3*3> de20dposx(3,3,1); Getdei0dposx(xi, 2, de20dposx);
2538 // ConstMatrix<3*3> de30dposx(3,3,1); Getdei0dposx(xi, 3, de30dposx);
2539 // ConstVector<3> de2drot(3,1); Getdeidrot(xi, 2, de2drot);
2540 // ConstVector<3> de3drot(3,1); Getdeidrot(xi, 3, de3drot);
2541 // Vector3D posx = GetPosx(xi);
2542 // double theta = GetRot(xi);
2543 // ConstVector<4> sfposx(4,1); for(int j=1; j<=4; j++) sfposx(j) = GetSFPosx(j,x0);
2544 // ConstVector<2> sfrot(2,1); for(int j=1; j<=2; j++) sfrot(j) = GetSFRot(j,xi);
2545 //
2546 // mbs->UO(UO_LVL_0) << "--------------------------------------------------------------------------------------------------------\n";
2547 // mbs->UO(UO_LVL_0) << "Test Output at step " << mbs->GetTIit() << "(" << mbs->GetTime() << " s):\n";
2548 // mbs->UO(UO_LVL_0) << "xi=" << xi << ", director = " << GetDirector(xi) << "\n";
2549 // mbs->UO(UO_LVL_0) << "XG()=\n" << xg << "\n" << "q0 = \n" << q0 << "\n" << "XG()+q0=\n" << xg+q0 << "\n";
2550 // mbs->UO(UO_LVL_0) << "--------------------------------------------------------------------------------------------------------\n";
2551 // mbs->UO(UO_LVL_0) << "dL0dq1=\n" << dL0dq1;
2552 // mbs->UO(UO_LVL_0) << "dde2dposxdposx=\n" << dde2dposxdposx;
2553 // mbs->UO(UO_LVL_0) << "dde3dposxdposx=\n" << dde3dposxdposx;
2554 // mbs->UO(UO_LVL_0) << "dde2dposxdrot=\n" << dde2dposxdrot;
2555 // mbs->UO(UO_LVL_0) << "dde3dposxdrot=\n" << dde3dposxdrot;
2556 // mbs->UO(UO_LVL_0) << "dde2drotdrot=\n" << dde2drotdrot << "\n";
2557 // mbs->UO(UO_LVL_0) << "dde3drotdrot=\n" << dde3drotdrot << "\n";
2558 // mbs->UO(UO_LVL_0) << "dde20dposxdposx=\n" << dde20dposxdposx;
2559 // mbs->UO(UO_LVL_0) << "dde30dposxdposx=\n" << dde30dposxdposx;
2560 // mbs->UO(UO_LVL_0) << "dde20hatdposxdposx=\n" << dde20hatdposxdposx;
2561 // mbs->UO(UO_LVL_0) << "dde30hatdposxdposx=\n" << dde30hatdposxdposx;
2562 // mbs->UO(UO_LVL_0) << "de20hatdposx=\n" << de20hatdposx;
2563 // mbs->UO(UO_LVL_0) << "de30hatdposx=\n" << de30hatdposx;
2564 // mbs->UO(UO_LVL_0) << "e20hat=\n" << e20hat << "\n";
2565 // mbs->UO(UO_LVL_0) << "e30hat=\n" << e30hat << "\n";
2566 // mbs->UO(UO_LVL_0) << "dde30hatde1de1=\n" << dde30hatde1de1;
2567 // mbs->UO(UO_LVL_0) << "dde1dposxdposx=\n" << dde1dposxdposx;
2568 // mbs->UO(UO_LVL_0) << "de1dposx=\n" << de1dposx;
2569 // mbs->UO(UO_LVL_0) << "de30hatde1=\n" << de30hatde1;
2570 // mbs->UO(UO_LVL_0) << "--------------------------------------------------------------------------------------------------------\n";
2571 // mbs->UO(UO_LVL_0) << "L0=\n" << L0;
2572 // mbs->UO(UO_LVL_0) << "de2dq=\n" << de2dq.PrintToMathematica() << "\n";
2573 // mbs->UO(UO_LVL_0) << "de3dq=\n" << de3dq.PrintToMathematica() << "\n";
2574 // mbs->UO(UO_LVL_0) << "de2dposx=\n" << de2dposx.PrintToMathematica() << "\n";
2575 // mbs->UO(UO_LVL_0) << "de3dposx=\n" << de3dposx.PrintToMathematica() << "\n";
2576 // mbs->UO(UO_LVL_0) << "de20dposx=\n" << de20dposx.PrintToMathematica() << "\n";
2577 // mbs->UO(UO_LVL_0) << "de30dposx=\n" << de30dposx.PrintToMathematica() << "\n";
2578 // mbs->UO(UO_LVL_0) << "Cos(theta)=" << Cos(theta) << "\n";
2579 // mbs->UO(UO_LVL_0) << "Sin(theta)=" << Sin(theta) << "\n";
2580 // mbs->UO(UO_LVL_0) << "de2drot=" << de2drot << "\n";
2581 // mbs->UO(UO_LVL_0) << "de3drot=" << de3drot << "\n";
2582 // mbs->UO(UO_LVL_0) << "posx=" << posx << "\n";
2583 // mbs->UO(UO_LVL_0) << "theta=" << theta << "\n";
2584 // mbs->UO(UO_LVL_0) << "sfposx=" << sfposx << "\n";
2585 // mbs->UO(UO_LVL_0) << "sfrot=" << sfrot << "\n";
2586 // mbs->UO(UO_LVL_0) << "--------------------------------------------------------------------------------------------------------\n";
2587 //
2588 // test_output_written = true;
2589 // }
2590 }
2591
2592
2593 // standard version:
GetQuadraticVelocityVector(const double & xi,Vector & qvv) const2594 void ANCFBeam3DTorsion::GetQuadraticVelocityVector(const double& xi, Vector& qvv) const //eqs.(47)-(48), xi in [-lx/2, lx/2]
2595 {
2596 qvv.SetAll(0);
2597 ConstMatrix<14*14> dMdqk(14, 14, 1); //nofill
2598 ConstVector<14> qdot(14, 1); //nofill
2599
2600 for (int k=1; k<=14; k++)
2601 {
2602 qdot(k)=XGP(k);
2603 }
2604 for (int k=1; k<=14; k++)
2605 {
2606 GetdMdqk(xi, k, dMdqk);
2607 qvv(k) += 0.5*(qdot*dMdqk*qdot);
2608 //qvv(k) -= qdot*dMdqk*qdot; //eq.(47) // both lines are equal! and summation wrong... right would be: (48) - 0.5 * (47) now, replace by qvv = -0.5 (47) which is faster than (48)!
2609 //qvv += qdot(k)*(qdot*dMdqk); //eq.(48)
2610 }
2611 }
2612
2613 // used for 2nd order lobatto integration (IPs are in nodes n=1 and n=2 (local indexing)):
GetQuadraticVelocityVectorAtNode(Vector & f,int n) const2614 void ANCFBeam3DTorsion::GetQuadraticVelocityVectorAtNode(Vector& f, int n) const
2615 {
2616 // for speedup of dynamic computation we assume 2nd order integration rule by Lobatto (integration points only at nodes),
2617 // then: 1.) dde2dposxdposx, dde3dposxdposx, dde2dposxdtheta, dde3dposxdtheta, dde2dthetadtheta, dde3dthetadtheta are calculated at nodes only, s.t. generalized coordinates may be used as input directly (instead of time consuming shape function evaluations). 2.) dL0dq(x0=-1 or x0=1) = (0, dde2dqdq, dde3dqdq) is sparse.
2618
2619 f.SetAll(0.);
2620
2621 int offset_ang = n-1;
2622 int offset_dir = 3*offset_ang;
2623 int offset_pos = 6*offset_ang;
2624
2625 double Iy = GetMaterial().BeamRhoIy();
2626 double Iz = GetMaterial().BeamRhoIz();
2627
2628 // evaluation at left node
2629 double drdx1 = XG(4+offset_pos)+q0(4+offset_pos);
2630 double drdx2 = XG(5+offset_pos)+q0(5+offset_pos);
2631 double drdx3 = XG(6+offset_pos)+q0(6+offset_pos);
2632 double theta = XG(13+offset_ang)+q0(13+offset_ang);
2633 double d1 = XData(1+offset_dir);
2634 double d2 = XData(2+offset_dir);
2635 double d3 = XData(3+offset_dir);
2636 Vector3D qdotpos(XGP(4+offset_pos),XGP(5+offset_pos),XGP(6+offset_pos));
2637 double qdottheta(XGP(13+offset_ang));
2638
2639 TArray<double> de, de11, de21, de31, de22, de32, de33, de4; //de44;
2640
2641 { // this part takes 3/4 CPU time of the whole function GetQuadraticVelocityVectorAtNode, thus a compound calculation (not split into 6 functions, where almost the same calculations are done) would be advisable.
2642 // however, the kinematic terms in total just need the third of CPU-time compared to the calculations on the work of interior forces...
2643 Getdeidposx_and_deidtheta(de,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2644 Getddeidposx1dposx1(de11,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2645 Getddeidposx2dposx1(de21,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2646 Getddeidposx3dposx1(de31,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2647 Getddeidposx2dposx2(de22,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2648 Getddeidposx3dposx2(de32,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2649 Getddeidposx3dposx3(de33,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2650 Getddeidthetadposx(de4,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2651 //Getddeidthetadtheta(de44,drdx1,drdx2,drdx3,theta,d1,d2,d3);
2652 }
2653
2654 Matrix3D de2dposx(de(1),de(4),de(7),de(2),de(5),de(8),de(3),de(6),de(9));
2655 Matrix3D de3dposx(de(13),de(16),de(19),de(14),de(17),de(20),de(15),de(18),de(21));
2656 Vector3D de2dtheta(de(10),de(11),de(12));
2657 Vector3D de3dtheta(de(22),de(23),de(24));
2658 Matrix3D dde2dposxdposx1(de11(1),de21(1),de31(1),de11(2),de21(2),de31(2),de11(3),de21(3),de31(3));
2659 Matrix3D dde3dposxdposx1(de11(4),de21(4),de31(4),de11(5),de21(5),de31(5),de11(6),de21(6),de31(6));
2660 Matrix3D dde2dposxdposx2(de21(1),de22(1),de32(1),de21(2),de22(2),de32(2),de21(3),de22(3),de32(3));
2661 Matrix3D dde3dposxdposx2(de21(4),de22(4),de32(4),de21(5),de22(5),de32(5),de21(6),de22(6),de32(6));
2662 Matrix3D dde2dposxdposx3(de31(1),de32(1),de33(1),de31(2),de32(2),de33(2),de31(3),de32(3),de33(3));
2663 Matrix3D dde3dposxdposx3(de31(4),de32(4),de33(4),de31(5),de32(5),de33(5),de31(6),de32(6),de33(6));
2664 //Matrix3D dde2dthetadposx(de4(1),de4(4),de4(7),de4(2),de4(5),de4(8),de4(3),de4(6),de4(9));
2665 //Matrix3D dde3dthetadposx(de4(10),de4(13),de4(16),de4(11),de4(14),de4(17),de4(12),de4(15),de4(18));
2666 Vector3D dde2dthetadposx1(de4(1),de4(2),de4(3));
2667 Vector3D dde3dthetadposx1(de4(10),de4(11),de4(12));
2668 Vector3D dde2dthetadposx2(de4(4),de4(5),de4(6));
2669 Vector3D dde3dthetadposx2(de4(13),de4(14),de4(15));
2670 Vector3D dde2dthetadposx3(de4(7),de4(8),de4(9));
2671 Vector3D dde3dthetadposx3(de4(16),de4(17),de4(18));
2672 //Vector3D dde2dthetadtheta(de44(1),de44(2),de44(3));
2673 //Vector3D dde3dthetadtheta(de44(4),de44(5),de44(6));
2674
2675 Vector3D qdot_de2dposx = de2dposx*(Iz*qdotpos);
2676 Vector3D qdot_de2dtheta = (Iz*qdottheta)*de2dtheta;
2677
2678 Vector3D qdot_de3dposx = de3dposx*(Iy*qdotpos);
2679 Vector3D qdot_de3dtheta = (Iy*qdottheta)*de3dtheta;
2680
2681 Vector3D dde2dposxdposx1_qdot = dde2dposxdposx1*qdotpos;
2682 Vector3D dde2dposxdposx2_qdot = dde2dposxdposx2*qdotpos;
2683 Vector3D dde2dposxdposx3_qdot = dde2dposxdposx3*qdotpos;
2684 Vector3D dde2dthetadposx1_qdot = dde2dthetadposx1*qdottheta;
2685 Vector3D dde2dthetadposx2_qdot = dde2dthetadposx2*qdottheta;
2686 Vector3D dde2dthetadposx3_qdot = dde2dthetadposx3*qdottheta;
2687 //Vector3D dde2dposxdtheta_qdot = dde2dthetadposx*qdotpos;
2688 //Vector3D dde2dthetadtheta_qdot = dde2dthetadtheta*qdottheta;
2689
2690 Vector3D dde3dposxdposx1_qdot = dde3dposxdposx1*qdotpos;
2691 Vector3D dde3dposxdposx2_qdot = dde3dposxdposx2*qdotpos;
2692 Vector3D dde3dposxdposx3_qdot = dde3dposxdposx3*qdotpos;
2693 Vector3D dde3dthetadposx1_qdot = dde3dthetadposx1*qdottheta;
2694 Vector3D dde3dthetadposx2_qdot = dde3dthetadposx2*qdottheta;
2695 Vector3D dde3dthetadposx3_qdot = dde3dthetadposx3*qdottheta;
2696 //Vector3D dde3dposxdtheta_qdot = dde3dthetadposx*qdotpos;
2697 //Vector3D dde3dthetadtheta_qdot = dde3dthetadtheta*qdottheta;
2698
2699 Vector3D fposx(
2700 (qdot_de2dposx+qdot_de2dtheta)*(dde2dposxdposx1_qdot+dde2dthetadposx1_qdot) + (qdot_de3dposx+qdot_de3dtheta)*(dde3dposxdposx1_qdot+dde3dthetadposx1_qdot),
2701 (qdot_de2dposx+qdot_de2dtheta)*(dde2dposxdposx2_qdot+dde2dthetadposx2_qdot) + (qdot_de3dposx+qdot_de3dtheta)*(dde3dposxdposx2_qdot+dde3dthetadposx2_qdot),
2702 (qdot_de2dposx+qdot_de2dtheta)*(dde2dposxdposx3_qdot+dde2dthetadposx3_qdot) + (qdot_de3dposx+qdot_de3dtheta)*(dde3dposxdposx3_qdot+dde3dthetadposx3_qdot));
2703 //double ftheta = (qdot_de2dposx+qdot_de2dtheta)*(dde2dposxdtheta_qdot+dde2dthetadtheta_qdot) + (qdot_de3dposx+qdot_de3dtheta)*(dde3dposxdtheta_qdot+dde3dthetadtheta_qdot); // equals zero!!!!
2704
2705 double fac = 0.25*size.X(); // = 0.5*det, det = 0.5*lx;
2706 f(4+offset_pos) = fac*fposx(1);
2707 f(5+offset_pos) = fac*fposx(2);
2708 f(6+offset_pos) = fac*fposx(3);
2709 //f(13+offset_ang) = fac*ftheta; // always 0, since d(deidt^2)/dq13=0 at xi=-0.5*lx and d(deidt^2)/dq14=0 at xi=0.5*lx
2710 }
2711
GetM(const double & xi,Matrix & m) const2712 void ANCFBeam3DTorsion::GetM(const double& xi, Matrix& m) const //eq.(49), xi in [-lx/2, lx/2]
2713 {
2714 m.SetAll(0);
2715 ConstMatrix<9*14> L0(9, 14, 1); //nofill
2716 GetL0(xi, L0);
2717
2718 double sqrt_rhoA = sqrt(GetMaterial().BeamRhoA());
2719 double sqrt_rhoIy = sqrt(GetMaterial().BeamRhoIy());
2720 double sqrt_rhoIz = sqrt(GetMaterial().BeamRhoIz());
2721
2722 L0.MulRow(1, sqrt_rhoA);
2723 L0.MulRow(2, sqrt_rhoA);
2724 L0.MulRow(3, sqrt_rhoA);
2725 L0.MulRow(4, sqrt_rhoIz);
2726 L0.MulRow(5, sqrt_rhoIz);
2727 L0.MulRow(6, sqrt_rhoIz);
2728 L0.MulRow(7, sqrt_rhoIy);
2729 L0.MulRow(8, sqrt_rhoIy);
2730 L0.MulRow(9, sqrt_rhoIy);
2731
2732 MultTp(L0,L0,m);
2733 }
2734
GetdMdqk(const double & xi,const int k,Matrix & dMdqk) const2735 void ANCFBeam3DTorsion::GetdMdqk(const double& xi, const int k, Matrix& dMdqk) const //eq.(51), xi in [-lx/2, lx/2], k in {1,..,14}
2736 {
2737 dMdqk.SetAll(0);
2738
2739 ConstMatrix<9*14> L0(9, 14, 1); //nofill
2740 ConstMatrix<9*14> dL0dqk(9, 14, 1); //nofill
2741 GetL0(xi, L0);
2742 GetdL0dqk(xi, k, dL0dqk);
2743
2744 L0.MulRow(1, GetMaterial().BeamRhoA());
2745 L0.MulRow(2, GetMaterial().BeamRhoA());
2746 L0.MulRow(3, GetMaterial().BeamRhoA());
2747 L0.MulRow(4, GetMaterial().BeamRhoIz());
2748 L0.MulRow(5, GetMaterial().BeamRhoIz());
2749 L0.MulRow(6, GetMaterial().BeamRhoIz());
2750 L0.MulRow(7, GetMaterial().BeamRhoIy());
2751 L0.MulRow(8, GetMaterial().BeamRhoIy());
2752 L0.MulRow(9, GetMaterial().BeamRhoIy());
2753
2754 MultTp(L0, dL0dqk, dMdqk);
2755 }
2756
GetL0(const double & xi,Matrix & L0) const2757 void ANCFBeam3DTorsion::GetL0(const double& xi, Matrix& L0) const //eq.(42), xi in [-lx/2, lx/2]
2758 {
2759 double x0 = xi*2./size.X();
2760
2761 if(0)
2762 {
2763 L0.SetAll(0);
2764
2765 ConstMatrix<3*14> deidq(3, 14, 1); //nofill
2766
2767 Getdeidq(xi, 2, deidq);
2768 L0.SetSubmatrix(deidq, 3+1, 1);
2769
2770 Getdeidq(xi, 3, deidq);
2771 L0.SetSubmatrix(deidq, 2*3+1, 1);
2772
2773 int offset = 0;
2774 for (int i = 1; i<=NSPos(); i++)
2775 {
2776 double sf_val = GetSFPos(i, x0);
2777 for (int j = 1; j<=Dim(); j++)
2778 {
2779 L0(j, j+offset) = sf_val;
2780 }
2781 offset += Dim();
2782 }
2783 }
2784 else //faster
2785 {
2786 TArray<double> de;
2787 Vector3D d = GetDirector(xi);
2788 Vector3D drdx = GetPosx(xi);
2789 double theta = GetRot(xi);
2790 Getdeidposx_and_deidtheta(de, drdx(1), drdx(2), drdx(3), theta, d(1), d(2), d(3));
2791
2792 Matrix3D de2dposx(de(1),de(4),de(7),de(2),de(5),de(8),de(3),de(6),de(9));
2793 Matrix3D de3dposx(de(13),de(16),de(19),de(14),de(17),de(20),de(15),de(18),de(21));
2794 Vector3D de2dtheta(de(10),de(11),de(12));
2795 Vector3D de3dtheta(de(22),de(23),de(24));
2796
2797 Vector sf(4);
2798 GetShapesPos(sf, x0);
2799 Vector sfx(4);
2800 GetShapesPosx(sfx, x0);
2801 Vector sfrot(2);
2802 GetShapesRot(sfrot, xi);
2803
2804 for (int i=1; i<=3; i++)
2805 {
2806 int ip3 = i+3;
2807 int ip6 = i+6;
2808 for (int j=1; j<=14; j++)
2809 {
2810 L0(i,j)=0.;
2811 }
2812 for (int j=1; j<=4; j++)
2813 {
2814 L0(i,i+(j-1)*3)=sf(j);
2815 }
2816 for (int j=1; j<=3; j++)
2817 {
2818 for (int k=1; k<=4; k++)
2819 {
2820 L0(ip3,j+(k-1)*3)=de2dposx(i,j)*sfx(k);
2821 L0(ip6,j+(k-1)*3)=de3dposx(i,j)*sfx(k);
2822 }
2823 }
2824 for (int k=1; k<=2; k++)
2825 {
2826 L0(ip3,k+12)=de2dtheta(i)*sfrot(k);
2827 L0(ip6,k+12)=de3dtheta(i)*sfrot(k);
2828 }
2829 }
2830 }
2831 }
2832
GetdL0dqk(const double & xi,const int k,Matrix & dL0dqk) const2833 void ANCFBeam3DTorsion::GetdL0dqk(const double& xi, const int k, Matrix& dL0dqk) const //eq.(53), xi in [-lx/2, lx/2], k in {1,..,14}
2834 {
2835 dL0dqk.SetAll(0);
2836
2837 ConstMatrix<3*14> ddeidqdqk(3, 14, 1); //nofill
2838
2839 Getddeidqdqk(xi, 2, k, ddeidqdqk);
2840 dL0dqk.SetSubmatrix(ddeidqdqk, 3+1, 1);
2841
2842 Getddeidqdqk(xi, 3, k, ddeidqdqk);
2843 dL0dqk.SetSubmatrix(ddeidqdqk, 2*3+1, 1);
2844 }
2845
Getddeidqdqk(const double & xi,const int i,const int k,Matrix & ddeidqdqk) const2846 void ANCFBeam3DTorsion::Getddeidqdqk(const double& xi, const int i, const int k, Matrix& ddeidqdqk) const //eq.(81), xi in [-lx/2, lx/2], i in {2,3}, k in {1,..,14}
2847 {
2848 ddeidqdqk.SetAll(0);
2849
2850 // dd ei / dq dqk = ( [ dd ei / dd (r',ang) ] . [ d (r',ang) / dqk ] ) . [ d (r',ang) / dq ] + [ d ei / d (r',ang) ] . [ dd (r',ang) / dqdqk ]
2851 // = ( [ dd ei / dd (r',ang) ] . [ d (r',ang) / dqk ] ) . [ d (r',ang) / dq ] + 0
2852
2853 ConstMatrix<3*3*3> ddeidposxdposx(3,3*3,1); //nofill
2854 ConstMatrix<3*3> ddeidposxdrot(3,3,1); //nofill
2855 ConstVector<3> ddeidrotdrot(3,1); //nofill
2856
2857 Getddeidposxdposx(xi, i, ddeidposxdposx);
2858 Getddeidposxdrot(xi, i, ddeidposxdrot);
2859 Getddeidrotdrot(xi, i, ddeidrotdrot);
2860
2861 ConstMatrix<3*3> ddeidposxdposx_times_dposxdqk_plus_ddeidrotdposx_times_drotdqk(3,3,1); //nofill
2862 ConstVector<3> ddeidrotdrot_times_drotdqk_plus_ddeidposxdrot_times_dposxdqk(3,1); //nofill
2863
2864 double x0 = xi*2./size.X();
2865
2866 if (k >= 1 && k <= 12)
2867 {
2868 int posx_dim = (k-1)%Dim() + 1;
2869 int sf_idx = (k-1)/Dim()+1;
2870 for (int d=1; d<=Dim(); d++)
2871 {
2872 ddeidrotdrot_times_drotdqk_plus_ddeidposxdrot_times_dposxdqk(d) = ddeidposxdrot(d,posx_dim)*GetSFPosx(sf_idx,x0);
2873 for (int e=1; e<=Dim(); e++)
2874 {
2875 ddeidposxdposx_times_dposxdqk_plus_ddeidrotdposx_times_drotdqk(d,e) = ddeidposxdposx(d,(posx_dim-1)*Dim()+e)*GetSFPosx(sf_idx,x0);
2876 }
2877 }
2878 }
2879 else if (k==13 || k==14)
2880 {
2881 int sf_idx = k-NSPos()*Dim();
2882 for (int d=1; d<=Dim(); d++)
2883 {
2884 ddeidrotdrot_times_drotdqk_plus_ddeidposxdrot_times_dposxdqk(d) = ddeidrotdrot(d)*GetSFRot(sf_idx,xi);
2885 for (int e=1; e<=Dim(); e++)
2886 {
2887 ddeidposxdposx_times_dposxdqk_plus_ddeidrotdposx_times_drotdqk(d,e) = ddeidposxdrot(d,e)*GetSFRot(sf_idx,xi);
2888 }
2889 }
2890 }
2891 else
2892 {
2893 assert(0);
2894 }
2895
2896 for (int d=1; d<=Dim(); d++)
2897 {
2898 for (int j=1; j<=NSPos(); j++)
2899 {
2900 for (int e=1; e<=Dim(); e++)
2901 {
2902 ddeidqdqk(d,e+Dim()*(j-1)) = ddeidposxdposx_times_dposxdqk_plus_ddeidrotdposx_times_drotdqk(d,e)*GetSFPosx(j,x0);
2903 }
2904 }
2905 for (int j=1; j<=NSRot(); j++)
2906 {
2907 ddeidqdqk(d,Dim()*NSPos()+j) = ddeidrotdrot_times_drotdqk_plus_ddeidposxdrot_times_dposxdqk(d)*GetSFRot(j,xi);
2908 }
2909 }
2910 }
2911
Getddeidposxdposx(const double & xi,const int i,Matrix & ddeidposxdposx) const2912 void ANCFBeam3DTorsion::Getddeidposxdposx(const double& xi, const int i, Matrix& ddeidposxdposx) const //eq.(79)+(91), xi in [-lx/2, lx/2], i in {2,3}
2913 {
2914 ConstMatrix<3*3*3> ddei0dposxdposx(3,3*3,1); //nofill
2915 double theta = GetRot(xi);
2916
2917 if (i==2)
2918 {
2919 Getddei0dposxdposx(xi, 2, ddei0dposxdposx);
2920 ddeidposxdposx = Cos(theta)*ddei0dposxdposx;
2921 Getddei0dposxdposx(xi, 3, ddei0dposxdposx);
2922 ddeidposxdposx += Sin(theta)*ddei0dposxdposx;
2923 }
2924 else if (i == 3)
2925 {
2926 Getddei0dposxdposx(xi, 2, ddei0dposxdposx);
2927 ddeidposxdposx = -Sin(theta)*ddei0dposxdposx;
2928 Getddei0dposxdposx(xi, 3, ddei0dposxdposx);
2929 ddeidposxdposx += Cos(theta)*ddei0dposxdposx;
2930 }
2931 else
2932 {
2933 assert(0);
2934 }
2935 }
2936
Getddei0hatdposxdposx(const double & xi,const int i,Matrix & ddei0hatdposxdposx) const2937 void ANCFBeam3DTorsion::Getddei0hatdposxdposx(const double& xi, const int i, Matrix& ddei0hatdposxdposx) const //eq.(80)-(84), xi in [-lx/2, lx/2], i in {2,3}
2938 {
2939 if ( i<2 || i>3 )
2940 {
2941 assert(0);
2942 }
2943
2944 if (i==2)
2945 {
2946 ddei0hatdposxdposx.SetAll(0.);
2947 }
2948 else if (i==3)
2949 {
2950 // dde30hatdposxdposx = ((ddei0hatde1de1 de1dposx) de1dposx) + dei0hatde1 dde1dposxdposx where e1 = posx/|posx|
2951
2952 // v.. vector, depending on vector x, and vector x depending on vector y
2953 // chain rule:
2954 // dv(j)dy(c1) = dv(j)dx(s1) dx(s1)dy(c1) (j: row index, c1: first column index, s1: first summation index)
2955 // ddv(j)dy(c1)dy(c2) = ddv(j)dx(s1)dx(s2) dx(s2)dy(c2) dx(s1)dy(c1) + dv(j)dx(s1) ddx(s1)dy(c1)dy(c2) (c2: second column index, s2: second summation index)
2956
2957 IVector offset(Dim()); //helper
2958 for(int j=1; j<=Dim(); j++)
2959 {
2960 offset(j) = (j-1)*Dim();
2961 }
2962
2963 ConstMatrix<27> dde30hatde1de1(3,9,1); //nofill
2964 Getdde30hatde1de1(xi, dde30hatde1de1);
2965 ConstMatrix<9> de1dposx(3,3,1); //nofill
2966 Getde1dposx(xi, de1dposx);
2967 ConstMatrix<9> de30hatde1(3,3,1); //nofill
2968 Getde30hatde1(xi, de30hatde1);
2969 ConstMatrix<27> dde1dposxdposx(3,9,1); //nofill
2970 Getdde1dposxdposx(xi, dde1dposxdposx);
2971
2972 ddei0hatdposxdposx.SetAll(0.);
2973 for (int j=1; j<=Dim(); j++) //row index
2974 {
2975 for (int c1=1; c1<=Dim(); c1++) // first column index
2976 {
2977 for (int c2=1; c2<=c1; c2++) // second column index
2978 {
2979 for (int s1=1; s1<=Dim(); s1++) // first summation index
2980 {
2981 ddei0hatdposxdposx(j, offset(c1) + c2) += de30hatde1(j, s1)*dde1dposxdposx(s1, offset(c1) + c2);
2982
2983 for (int s2=1; s2<=Dim(); s2++) // second summation index
2984 {
2985 ddei0hatdposxdposx(j, offset(c1) + c2) += dde30hatde1de1(j, s1 + offset(s2))*de1dposx(s2, c2)*de1dposx(s1, c1);
2986 }
2987 }
2988
2989 if (c2 < c1)
2990 {
2991 ddei0hatdposxdposx(j, offset(c2) + c1) = ddei0hatdposxdposx(j, offset(c1) + c2); //symmetric components w.r.t. differentiation variables
2992 }
2993 }
2994 }
2995 }
2996 }
2997 }
2998
2999
3000
Getddei0dposxdposx(const double & xi,const int i,Matrix & ddei0dposxdposx) const3001 void ANCFBeam3DTorsion::Getddei0dposxdposx(const double& xi, const int i, Matrix& ddei0dposxdposx) const //eq.(57)-(58)+(79)+(91), xi in [-lx/2, lx/2], i in {2,3}
3002 {
3003 ConstVector<3> ei0hat(3,1); //nofill
3004 Getei0hat(xi, i, ei0hat);
3005 ConstMatrix<3*3> dei0hatdposx(3,3,1); //nofill
3006 Getdei0hatdposx(xi, i, dei0hatdposx);
3007 ConstMatrix<3*3*3> ddei0hatdposxdposx(3,3*3,1); //nofill
3008 Getddei0hatdposxdposx(xi, i, ddei0hatdposxdposx);
3009
3010 ConstVector<3> dei0hatdposxj(3,1); //nofill
3011 ConstVector<3> dei0hatdposxk(3,1); //nofill
3012 ConstVector<3> ddei0hatdposxjdposxk(3,1); //nofill
3013 ConstVector<3> ddei0dposxjdposxk(3,1); //nofill
3014
3015 for (int j=1; j<=3; j++)
3016 {
3017 int offset = (j-1)*Dim();
3018 dei0hatdposx.GetColVec(j, dei0hatdposxj);
3019 for (int k=1; k<=j; k++)
3020 {
3021 ddei0hatdposxdposx.GetColVec(offset+k, ddei0hatdposxjdposxk);
3022
3023 if (j==k)
3024 {
3025 GetddFOverAbsFdxdx(ei0hat, dei0hatdposxj, ddei0hatdposxjdposxk, ddei0dposxjdposxk);
3026 }
3027 else
3028 {
3029 dei0hatdposx.GetColVec(k, dei0hatdposxk);
3030 GetddFOverAbsFdxdy(ei0hat, dei0hatdposxj, dei0hatdposxk, ddei0hatdposxjdposxk, ddei0dposxjdposxk);
3031 }
3032
3033 ddei0dposxdposx.SetColVec(ddei0dposxjdposxk, offset+k);
3034 if (k<j)
3035 {
3036 ddei0dposxdposx.SetColVec(ddei0dposxjdposxk, (k-1)*Dim()+j); //symmetric components
3037 }
3038 }
3039 }
3040 }
3041
Getddeidposxdrot(const double & xi,const int i,Matrix & ddeidposxdrot) const3042 void ANCFBeam3DTorsion::Getddeidposxdrot(const double& xi, const int i, Matrix& ddeidposxdrot) const //eq.(87)+(92), xi in [-lx/2, lx/2], i in {2,3}
3043 {
3044 ConstMatrix<3*3> dei0dposx(3,3,1); //nofill
3045 double theta = GetRot(xi);
3046
3047 if (i==2)
3048 {
3049 Getdei0dposx(xi, 2, dei0dposx);
3050 ddeidposxdrot = -Sin(theta)*dei0dposx;
3051 Getdei0dposx(xi, 3, dei0dposx);
3052 ddeidposxdrot += Cos(theta)*dei0dposx;
3053 }
3054 else if (i == 3)
3055 {
3056 Getdei0dposx(xi, 2, dei0dposx);
3057 ddeidposxdrot = -Cos(theta)*dei0dposx;
3058 Getdei0dposx(xi, 3, dei0dposx);
3059 ddeidposxdrot += -Sin(theta)*dei0dposx;
3060 }
3061 else
3062 {
3063 assert(0);
3064 }
3065 }
3066
Getddeidrotdrot(const double & xi,const int i,Vector & ddeidrotdrot) const3067 void ANCFBeam3DTorsion::Getddeidrotdrot(const double& xi, const int i, Vector& ddeidrotdrot) const //eq.(88)+(93), xi in [-lx/2, lx/2], i in {2,3}
3068 {
3069 ConstVector<3> ei0(3,1); //nofill
3070 double theta = GetRot(xi);
3071
3072 if (i==2)
3073 {
3074 Getei0(xi, 2, ei0);
3075 ddeidrotdrot = -Cos(theta)*ei0;
3076 Getei0(xi, 3, ei0);
3077 ddeidrotdrot += -Sin(theta)*ei0;
3078 }
3079 else if (i == 3)
3080 {
3081 Getei0(xi, 2, ei0);
3082 ddeidrotdrot = Sin(theta)*ei0;
3083 Getei0(xi, 3, ei0);
3084 ddeidrotdrot += -Cos(theta)*ei0;
3085 }
3086 else
3087 {
3088 assert(0);
3089 }
3090 }
3091
Getdeidq(const double & xi,const int i,Matrix & deidq) const3092 void ANCFBeam3DTorsion::Getdeidq(const double& xi, const int i, Matrix& deidq) const //eq.(66), xi in [-lx/2, lx/2]
3093 {
3094 deidq.SetAll(0);
3095
3096 // delta deidq = [ d ei / d (r',ang) ] . [ d (r',ang) / dq ]
3097 ConstMatrix<3*3> deidposx(3,3,1); //nofill
3098 ConstVector<3> deidrot(3,1); //nofill
3099
3100 Getdeidposx(xi, i, deidposx);
3101 Getdeidrot(xi, i, deidrot);
3102
3103 double x0 = xi*2./size.X();
3104
3105 for (int d=1; d<=Dim(); d++)
3106 {
3107 for (int k=1; k<=Dim(); k++)
3108 {
3109 for (int j=1; j<=NSPos(); j++)
3110 {
3111 deidq(d,k+Dim()*(j-1)) = deidposx(d,k)*GetSFPosx(j,x0);
3112 }
3113 }
3114 for (int k=1; k<=NSRot(); k++)
3115 {
3116 deidq(d,Dim()*NSPos()+k) = deidrot(d)*GetSFRot(k,xi);
3117 }
3118 }
3119 }
3120
Getdeidposx(const double & xi,const int i,Matrix & deidposx) const3121 void ANCFBeam3DTorsion::Getdeidposx(const double& xi, const int i, Matrix& deidposx) const //eq.(67)+(79), xi in [-lx/2, lx/2], i in {2,3}
3122 {
3123 ConstMatrix<3*3> dei0dposx(3,3,1); //nofill
3124 double theta = GetRot(xi);
3125
3126 if (i==2)
3127 {
3128 Getdei0dposx(xi, 2, dei0dposx);
3129 deidposx = Cos(theta)*dei0dposx;
3130 Getdei0dposx(xi, 3, dei0dposx);
3131 deidposx += Sin(theta)*dei0dposx;
3132 }
3133 else if (i==3)
3134 {
3135 Getdei0dposx(xi, 2, dei0dposx);
3136 deidposx = -Sin(theta)*dei0dposx;
3137 Getdei0dposx(xi, 3, dei0dposx);
3138 deidposx += Cos(theta)*dei0dposx;
3139 }
3140 else
3141 {
3142 assert(0);
3143 }
3144 }
3145
Getdei0dposx(const double & xi,const int i,Matrix & dei0dposx) const3146 void ANCFBeam3DTorsion::Getdei0dposx(const double& xi, const int i, Matrix& dei0dposx) const //eq.(69)-(76) + (55)-(56), xi in [-lx/2, lx/2], i in {2,3}
3147 {
3148 ConstVector<3> ei0hat(3,1); //nofill
3149 Getei0hat(xi, i, ei0hat);
3150 ConstMatrix<3*3> dei0hatdposx(3,3,1); //nofill
3151 Getdei0hatdposx(xi, i, dei0hatdposx);
3152
3153 ConstVector<3> dei0hatdposxj(3,1);//nofill
3154 ConstVector<3> dei0dposxj(3,1);//nofill
3155
3156 for (int j=1; j<=3; j++)
3157 {
3158
3159 dei0hatdposx.GetColVec(j, dei0hatdposxj);
3160 GetdFOverAbsFdx(ei0hat, dei0hatdposxj, dei0dposxj);
3161 dei0dposx.SetColVec(dei0dposxj, j);
3162 }
3163 }
3164
Getdei0hatdposx(const double & xi,const int i,Matrix & dei0hatdposx) const3165 void ANCFBeam3DTorsion::Getdei0hatdposx(const double& xi, const int i, Matrix& dei0hatdposx) const //eq.(69)-(76), xi in [-lx/2, lx/2], i in {2,3}
3166 {
3167 if (i==2)
3168 {
3169 Vector3D d = GetDirector(xi);
3170 // dei0hatdposx = skew(d)
3171 dei0hatdposx(1,1) = 0;
3172 dei0hatdposx(2,2) = 0;
3173 dei0hatdposx(3,3) = 0;
3174 dei0hatdposx(1,2) = -d(3);
3175 dei0hatdposx(2,1) = d(3);
3176 dei0hatdposx(1,3) = d(2);
3177 dei0hatdposx(3,1) = -d(2);
3178 dei0hatdposx(2,3) = -d(1);
3179 dei0hatdposx(3,2) = d(1);
3180 }
3181 else if (i==3)
3182 {
3183 // dei0hatdposx = de30hatde1.de1dposx
3184 ConstMatrix<3*3> de30hatde1(3,3,1); //nofill
3185 Getde30hatde1(xi, de30hatde1);
3186 ConstMatrix<3*3> de1dposx(3,3,1); //nofill
3187 Getde1dposx(xi, de1dposx);
3188
3189 dei0hatdposx = de30hatde1*de1dposx;
3190 }
3191 else
3192 {
3193 assert(0);
3194 }
3195 }
3196
Getde1dposx(const double & xi,Matrix & de1dposx) const3197 void ANCFBeam3DTorsion::Getde1dposx(const double& xi, Matrix& de1dposx) const //xi in [-lx/2, lx/2]
3198 {
3199 //de1dposx = (1/|posx|) I - (1/|posx|�) posx posx^T where e1=posx/|posx|
3200 Vector3D posx = GetPosx(xi);
3201 double posx_abs_square = posx*posx;
3202 double posx_abs = sqrt(posx_abs_square);
3203 double posx_abs_cubic = posx_abs_square*posx_abs;
3204 Vector3D d = GetDirector(xi);
3205
3206 double diag = 1./posx_abs;
3207 for (int j=1; j<=3; j++)
3208 {
3209 for (int k=1; k<=3; k++)
3210 {
3211 de1dposx(j,k) = -posx(j)*posx(k)/posx_abs_cubic;
3212 }
3213 de1dposx(j,j) += diag;
3214 }
3215 }
3216
Getdde1dposxdposx(const double & xi,Matrix & dde1dposxdposx) const3217 void ANCFBeam3DTorsion::Getdde1dposxdposx(const double& xi, Matrix& dde1dposxdposx) const //xi in [-lx/2, lx/2], k in {1,2,3}, dde1dposxdposx has 3 rows (according to dde1) and 3*3 columns (according to dposxdposx)
3218 {
3219 //dde1dposxdposx = (dde1dposxdposxk)_k\in{1,2,3}, dde1dposxdposxk = posxk/|posx|^3 (e1 e1^T - I) - 1/|posx|(de1dposxk e1^T + e1 de1dposxk^T), where e1 = posx/|posx| and I is identity
3220 Vector3D posx = GetPosx(xi);
3221 double posx_abs_square = posx*posx;
3222 double posx_abs = sqrt(posx_abs_square);
3223 double posx_abs_cubic = posx_abs_square*posx_abs;
3224
3225 Vector3D e1((1./posx_abs)*posx);
3226 ConstMatrix<3*3> de1dposx(3,3);
3227 Getde1dposx(xi, de1dposx);
3228
3229 for (int k=1; k<=3; k++)
3230 {
3231 double fact = posx(k)/posx_abs_cubic;
3232 for (int i=1; i<=3; i++)
3233 {
3234 for (int j=1; j<=k; j++)
3235 {
3236 dde1dposxdposx(i,j+(k-1)*3) = fact*(e1(i)*e1(j) - (double)(i==j)) - (1./posx_abs)*(de1dposx(i,k)*e1(j) + e1(i)*de1dposx(j,k));
3237 if (j < k)
3238 {
3239 dde1dposxdposx(i,k+(j-1)*3) = dde1dposxdposx(i,j+(k-1)*3); // symmetric components
3240 }
3241 }
3242 }
3243 }
3244 }
3245
Getde30hatde1(const double & xi,Matrix & de30hatde1) const3246 void ANCFBeam3DTorsion::Getde30hatde1(const double& xi, Matrix& de30hatde1) const //xi in [-lx/2, lx/2]
3247 {
3248 // de30hatde1 = - e1 d^T - (e1^T d) I where e1=posx/|posx|
3249 Vector3D posx = GetPosx(xi);
3250 double posx_abs_square = posx*posx;
3251 double posx_abs = sqrt(posx_abs_square);
3252 Vector3D d = GetDirector(xi);
3253
3254 Vector3D e1 = (1/posx_abs)*posx;
3255 double diag = -(e1*d);
3256 for (int j=1; j<=3; j++)
3257 {
3258 for (int k=1; k<=3; k++)
3259 {
3260 de30hatde1(j,k) = -e1(j)*d(k);
3261 }
3262 de30hatde1(j,j) += diag;
3263 }
3264 }
3265
Getdde30hatde1de1(const double & xi,Matrix & dde30hatde1de1) const3266 void ANCFBeam3DTorsion::Getdde30hatde1de1(const double& xi, Matrix& dde30hatde1de1) const //xi in [-lx/2, lx/2], dde30hatde1de1 has 3 rows (according to de30hat) and 3*3 columns (according to de1de1)
3267 {
3268 // dde30hatde1de1 = (dde30hatde1de1k)_k\in{1,2,3}, dde30hatde1de1k = - Ek d^T - d_k I, where E1 = (1,0,0)^T, E2 = (0,1,0)^T, E3 = (0,0,1)^T, e1=posx/|posx|
3269
3270 dde30hatde1de1.SetAll(0.);
3271 Vector3D d = GetDirector(xi);
3272
3273 for(int k=1; k<=3; k++)
3274 {
3275 int offset = Dim()*(k-1);
3276 for (int j=1; j<=3; j++)
3277 {
3278 dde30hatde1de1(k,j+offset) -= d(j);
3279 dde30hatde1de1(j,j+offset) -= d(k);
3280 }
3281 }
3282 }
3283
Getdeidrot(const double & xi,const int i,Vector & deidrot) const3284 void ANCFBeam3DTorsion::Getdeidrot(const double& xi, const int i, Vector& deidrot) const //eq.(68)+(80), xi in [-lx/2, lx/2], i in {2,3}
3285 {
3286 ConstVector<3> ei0(3,1); //nofill
3287 double theta = GetRot(xi);
3288
3289 if (i==2)
3290 {
3291 Getei0(xi, 2, ei0);
3292 deidrot = -Sin(theta)*ei0;
3293 Getei0(xi, 3, ei0);
3294 deidrot += Cos(theta)*ei0;
3295 }
3296 else if (i==3)
3297 {
3298 Getei0(xi, 2, ei0);
3299 deidrot = -Cos(theta)*ei0;
3300 Getei0(xi, 3, ei0);
3301 deidrot += -Sin(theta)*ei0;
3302 }
3303 else
3304 {
3305 assert(0);
3306 }
3307 }
3308
Getei0(const double & xi,const int i,Vector & ei0) const3309 void ANCFBeam3DTorsion::Getei0(const double& xi, const int i, Vector& ei0) const //eq.(59)-(62) + (54), xi in [-lx/2, lx/2], i in {2,3}
3310 {
3311 ConstVector<3> ei0hat(3,1); //nofill
3312 Getei0hat(xi, i, ei0hat);
3313 GetFOverAbsF(ei0hat, ei0);
3314 }
3315
Getei0hat(const double & xi,const int i,Vector & ei0hat) const3316 void ANCFBeam3DTorsion::Getei0hat(const double& xi, const int i, Vector& ei0hat) const //eq.(59)-(62), xi in [-lx/2, lx/2], i in {2,3}
3317 {
3318 Vector3D d = GetDirector(xi);
3319 Vector3D posx = GetPosx(xi);
3320 Vector3D ei0hat_3d;
3321
3322 if (i==2)
3323 {
3324 ei0hat_3d = d.Cross(posx);
3325 }
3326 else if (i==3)
3327 {
3328 // Gramm Schmitt Projektion
3329 ei0hat_3d = d-(d*posx)/(posx*posx)*posx;
3330 }
3331 else
3332 {
3333 assert(0);
3334 }
3335
3336 ei0hat = ei0hat_3d;
3337 }
3338
GetFOverAbsF(const Vector & f,Vector & f_over_abs_f) const3339 void ANCFBeam3DTorsion::GetFOverAbsF(const Vector& f, Vector& f_over_abs_f) const //eq.(54) computes (f/|f|)', where f maps a scalar to a vector //move to linalg.h/cpp
3340 {
3341 f_over_abs_f = (1/sqrt(f*f))*f;
3342 }
3343
GetdFOverAbsFdx(const Vector & f,const Vector & dfdx,Vector & d_f_over_abs_f_prime_dx) const3344 void ANCFBeam3DTorsion::GetdFOverAbsFdx(const Vector& f, const Vector& dfdx, Vector& d_f_over_abs_f_prime_dx) const //eq.(55)-(56) computes (f/|f|)', where f maps a scalar to a vector //move to linalg.h/cpp
3345 {
3346 double f_abs_square = f*f;
3347 double f_abs = sqrt(f_abs_square);
3348 d_f_over_abs_f_prime_dx = (-(f*dfdx)/(f_abs_square*f_abs))*f + (1/f_abs)*dfdx;
3349 }
3350
GetddFOverAbsFdxdx(const Vector & f,const Vector & dfdx,const Vector & ddfdxdx,Vector & dd_f_over_abs_f_dxdx) const3351 void ANCFBeam3DTorsion::GetddFOverAbsFdxdx(const Vector& f, const Vector& dfdx, const Vector& ddfdxdx, Vector& dd_f_over_abs_f_dxdx) const //eq.(57)-(58) computes (f/|f|)'', where f maps a scalar to a vector //move to linalg.h/cpp
3352 {
3353 double f_f = f*f;
3354 double f_abs_to_the_fifth = pow(f_f,5./2.);
3355 double f_dfdx = f*dfdx;
3356 double dfdx_dfdx = dfdx*dfdx;
3357 double f_ddfdxdx = f*ddfdxdx;
3358
3359 dd_f_over_abs_f_dxdx =
3360 ((3*f_dfdx*f_dfdx - (dfdx_dfdx + f_ddfdxdx)*f_f)/f_abs_to_the_fifth) * f
3361 + (-2.*f_f*f_dfdx/f_abs_to_the_fifth) * dfdx
3362 + (f_f*f_f/f_abs_to_the_fifth) * ddfdxdx;
3363 }
3364
GetddFOverAbsFdxdy(const Vector & f,const Vector & dfdx,const Vector & dfdy,const Vector & ddfdxdy,Vector & dd_f_over_abs_f_dxdy) const3365 void ANCFBeam3DTorsion::GetddFOverAbsFdxdy(const Vector& f, const Vector& dfdx, const Vector& dfdy, const Vector& ddfdxdy, Vector& dd_f_over_abs_f_dxdy) const //eq.(57)-(58) computes (f/|f|)'', where f maps a scalar to a vector //move to linalg.h/cpp
3366 {
3367 double f_f = f*f;
3368 double f_abs_to_the_fifth = pow(f_f,5./2.);
3369 double f_dfdx = f*dfdx;
3370 double f_dfdy = f*dfdy;
3371 double dfdx_dfdy = dfdx*dfdy;
3372 double f_ddfdxdy = f*ddfdxdy;
3373
3374 dd_f_over_abs_f_dxdy =
3375 ((3*f_dfdx*f_dfdy - (dfdx_dfdy + f_ddfdxdy)*f_f)/f_abs_to_the_fifth) * f
3376 + (-f_f*f_dfdy/f_abs_to_the_fifth) * dfdx
3377 + (-f_f*f_dfdx/f_abs_to_the_fifth) * dfdy
3378 + (f_f*f_f/f_abs_to_the_fifth) * ddfdxdy;
3379 }
3380
3381
3382
3383
3384
3385
3386
3387 //kopiert von ANCFBeam3D und ComputeStress-Aufrufe auskommentiert
DrawElement()3388 void ANCFBeam3DTorsion::DrawElement()
3389 {
3390 mbs->SetColor(col);
3391
3392 //Vector3D p1 = GetPos3D0D(Vector3D(-1,0.,0.));
3393 //Vector3D p2 = GetPos3D0D(Vector3D(1,0.,0.));
3394
3395 //UO() << "p1=" << p1 << "\n";
3396 //UO() << "p2=" << p2 << "\n";
3397
3398
3399 double lx1 = 1; double ly1 = 1*GetMBS()->GetMagnifyYZ(); double lz1 = 1*GetMBS()->GetMagnifyYZ();
3400 double def_scale = GetMBS()->GetDOption(105); //deformation scaling
3401
3402 int linemode = 1; //0=no lines, 1=outline+color, 2=outline, 3=elementline+color, 4=elementline
3403 if (GetMBS()->GetIOption(110) && !GetMBS()->GetIOption(111))
3404 {
3405 linemode = 2;
3406 }
3407 if (!GetMBS()->GetIOption(110) && GetMBS()->GetIOption(111))
3408 {
3409 linemode = 0;
3410 }
3411 if (!GetMBS()->GetIOption(110) && !GetMBS()->GetIOption(111))
3412 {
3413 linemode = 4;
3414 }
3415
3416 int colormode = 0;
3417 if (GetMBS()->GetActualPostProcessingFieldVariable() != NULL) colormode = 1;
3418 //if (GetMBS()->GetDrawMode() != 0) colormode = 1;//Yuri
3419 else
3420 {
3421 colormode = 0;
3422 }
3423
3424 //GetMBS()->UO(0) << "colormode = " << colormode << ", linemode = " << linemode << "\n";
3425
3426 //int comp1, comp2, type;
3427 //GetMBS()->GetDrawTypeComponents(type, comp1, comp2);
3428
3429 if (colormode)
3430 {
3431 double modeval = 0;
3432 int xgset = 0;
3433
3434 double tilex = GetMBS()->GetIOption(137);
3435 double tiley = GetMBS()->GetIOption(138);
3436 TArray<Vector3D> points((int)(tilex+1)*(int)(tiley+1));
3437 TArray<double> vals((int)(tilex+1)*(int)(tiley+1));
3438 double v=0;
3439
3440 for (int side=1; side <= 6; side++)
3441 {
3442 points.SetLen(0); vals.SetLen(0);
3443 Vector3D p0, vx, vy;
3444 int tileyn = (int)tiley;
3445 int tilexn = (int)tilex;
3446
3447 if (side == 1)
3448 { //bottom
3449 p0 = Vector3D(-lx1,-ly1,-lz1);
3450 vx = Vector3D(2.*lx1/tilexn,0,0);
3451 vy = Vector3D(0,0,2.*lz1/tileyn);
3452 }
3453 else if (side == 2)
3454 { //top
3455 p0 = Vector3D(-lx1, ly1, lz1);
3456 vx = Vector3D(2.*lx1/tilexn,0,0);
3457 vy = Vector3D(0,0,-2.*lz1/tileyn);
3458 }
3459 else if (side == 3)
3460 { //front
3461 p0 = Vector3D(-lx1,-ly1, lz1);
3462 vx = Vector3D(2.*lx1/tilexn,0,0);
3463 vy = Vector3D(0,2.*ly1/tileyn,0);
3464 }
3465 else if (side == 4)
3466 { //back
3467 p0 = Vector3D(-lx1, ly1,-lz1);
3468 vx = Vector3D(2.*lx1/tilexn,0,0);
3469 vy = Vector3D(0,-2.*ly1/tileyn,0);
3470 }
3471 else if (side == 5)
3472 { //left
3473 p0 = Vector3D(-lx1, ly1,-lz1);
3474 vx = Vector3D(0,-2.*ly1/tilexn,0);
3475 vy = Vector3D(0,0,2.*lz1/tileyn);
3476 }
3477 else if (side == 6)
3478 { //right
3479 p0 = Vector3D( lx1,-ly1,-lz1);
3480 vx = Vector3D(0,2.*ly1/tilexn,0);
3481 vy = Vector3D(0,0,2.*lz1/tileyn);
3482 }
3483
3484 for (double iy = 0; iy <= tileyn+1e-10; iy++)
3485 {
3486 for (double ix = 0; ix <= tilexn+1e-10; ix++)
3487 {
3488 Vector3D ploc = (p0+ix*vx+iy*vy);//-1<=p0<=+1
3489 Vector3D ploc_scaled(ploc(1)*size.X()*0.5,ploc(2)*size.Y()*0.5,ploc(3)*size.Z()*0.5);//-l/2<=ploc_scaled<=+l/2
3490 Vector3D pg = GetPos3D0D(ploc, def_scale);
3491 //Vector3D p(pg);//p=pg
3492 points.Add(pg);
3493 if (colormode)
3494 v = GetFieldVariableValue(*GetMBS()->GetActualPostProcessingFieldVariable(), ploc_scaled, true);
3495 vals.Add(v);
3496
3497 //if (colormode) ComputeStressD(ploc,type,comp1,comp2,v);//old_KN
3498 //vals.Add(v);
3499 }
3500 }
3501 mbs->DrawColorQuads(points,vals,(int)tilexn+1,(int)tileyn+1,colormode,linemode);
3502 //mbs->UO()<<"points"<<points(1)<<"\n";
3503 }
3504 }
3505 else
3506 {
3507 int drawgrid = 0;
3508 double thickness = 1;
3509 //double tiling = 20;
3510 double tiling = GetMBS()->GetIOption(136);
3511 mbs->SetDrawlines(0);
3512 mbs->SetDrawlinesH(0);
3513 Vector3D p1,p2,p3,p4,p5,p6,p7,p8;
3514 for (double i = 0; i < tiling; i++)
3515 {
3516 double l1 = -lx1+2*lx1*i/tiling;
3517 double l2 = -lx1+2*lx1*(i+1)/tiling;
3518 if (i == 0)
3519 {
3520 p8 = Vector3D(GetPos3D0D(Vector3D(l1,-ly1,-lz1)));
3521 p7 = Vector3D(GetPos3D0D(Vector3D(l1,-ly1, lz1)));
3522 p4 = Vector3D(GetPos3D0D(Vector3D(l1, ly1,-lz1)));
3523 p3 = Vector3D(GetPos3D0D(Vector3D(l1, ly1, lz1)));
3524 if (drawgrid)
3525 {
3526 mbs->MyDrawLine(p8,p7,thickness);
3527 mbs->MyDrawLine(p7,p3,thickness);
3528 mbs->MyDrawLine(p4,p3,thickness);
3529 mbs->MyDrawLine(p4,p8,thickness);
3530 }
3531 }
3532 else
3533 {
3534 p8 = p6;
3535 p7 = p5;
3536 p4 = p2;
3537 p3 = p1;
3538 }
3539 p6 = Vector3D(GetPos3D0D(Vector3D(l2,-ly1,-lz1)));
3540 p5 = Vector3D(GetPos3D0D(Vector3D(l2,-ly1, lz1)));
3541 p2 = Vector3D(GetPos3D0D(Vector3D(l2, ly1,-lz1)));
3542 p1 = Vector3D(GetPos3D0D(Vector3D(l2, ly1, lz1)));
3543 int dout = 0;
3544 if (i == 0 || i == tiling-1) dout = 1;
3545 if (drawgrid)
3546 {
3547 mbs->MyDrawLine(p6,p5,thickness);
3548 mbs->MyDrawLine(p5,p1,thickness);
3549 mbs->MyDrawLine(p2,p1,thickness);
3550 mbs->MyDrawLine(p2,p6,thickness);
3551 mbs->MyDrawLine(p6,p8,thickness);
3552 mbs->MyDrawLine(p5,p7,thickness);
3553 mbs->MyDrawLine(p2,p4,thickness);
3554 mbs->MyDrawLine(p1,p3,thickness);
3555 }
3556 else
3557 {
3558 mbs->DrawHex(p1,p2,p3,p4,p5,p6,p7,p8,dout);
3559 }
3560 }
3561
3562 mbs->SetDrawlines(1);
3563
3564 // draw directors
3565 Vector3D position, director;
3566 double drawlength = max(size.Y(),size.Z())*2.;
3567 double linethickness = max(2.,0.04*mbs->GetDOption(120));
3568 Vector3D color(.0, .5, .0);
3569
3570 position = GetPos3D0D(Vector3D(-1, 0., 0.)); //left director
3571 director = GetDirector1(1);
3572 director.Normalize();
3573 director *= drawlength;
3574 mbs->MyDrawLine(position, position+director, linethickness, color);
3575
3576 position = GetPos3D0D(Vector3D(1, 0., 0.)); //right director
3577 director = GetDirector2(1);
3578 director.Normalize();
3579 director *= drawlength;
3580 mbs->MyDrawLine(position, position+director, linethickness, color);
3581 }
3582 };
3583
3584
GetAvailableFieldVariables(TArray<FieldVariableDescriptor> & variables)3585 void ANCFBeam3DTorsion::GetAvailableFieldVariables(TArray<FieldVariableDescriptor> & variables)
3586 {
3587 // add all the field variables of the parent class
3588 Body3D::GetAvailableFieldVariables(variables);
3589 //FVT_position,FVT_displacement, FVT_velocity: implemented in Element
3590 // possibility to remove entries does not exist yet, just do not use the Function of the parent class
3591
3592 FieldVariableDescriptor::AddTypeIntoArray(variables, FieldVariableDescriptor::FVT_beam_axial_extension);
3593 FieldVariableDescriptor::AddTypeIntoArray(variables, FieldVariableDescriptor::FVT_beam_force_axial);
3594 FieldVariableDescriptor::AddTypeIntoArray(variables, FieldVariableDescriptor::FVT_beam_curvature, FieldVariableDescriptor::FVCI_z);
3595 FieldVariableDescriptor::AddTypeIntoArray(variables, FieldVariableDescriptor::FVT_beam_moment, FieldVariableDescriptor::FVCI_z);
3596 FieldVariableDescriptor::AddTypeIntoArray(variables, FieldVariableDescriptor::FVT_beam_torsion);
3597 FieldVariableDescriptor::AddTypeIntoArray(variables, FieldVariableDescriptor::FVT_beam_moment_torsional);
3598 }
3599
GetFieldVariableValue(const FieldVariableDescriptor & fvd,const Vector3D & ploc,bool flagD)3600 double ANCFBeam3DTorsion::GetFieldVariableValue(const FieldVariableDescriptor & fvd, const Vector3D & ploc, bool flagD)
3601 {
3602 // ploc is local position in [-lx/2., +lx/2.] x [-ly/2., +ly/2.] x [-lz/2., +lz/2.]
3603
3604 double xi = ploc.X();
3605
3606 double kappa1; GetKappa1(xi,kappa1,flagD);
3607 double kappa2; GetKappa2(xi,kappa2,flagD);
3608 double kappa3; GetKappa3(xi,kappa3,flagD);
3609 double gamma1; GetGamma1(xi,gamma1,flagD);
3610
3611 double beamGJ = GetMaterial().BeamGJkx();
3612 double beamEIy = GetMaterial().BeamEIy();
3613 double beamEIz = GetMaterial().BeamEIz();
3614 double beamEA = GetMaterial().BeamEA();
3615
3616 switch(fvd.VariableType())
3617 {
3618 case FieldVariableDescriptor::FVT_displacement: return fvd.GetComponent(GetDisplacement(ploc, flagD));
3619 case FieldVariableDescriptor::FVT_beam_axial_extension: return gamma1;
3620 case FieldVariableDescriptor::FVT_beam_curvature: return fvd.GetComponent(Vector3D(kappa1, kappa2, kappa3));
3621 case FieldVariableDescriptor::FVT_beam_torsion: return kappa1;
3622 case FieldVariableDescriptor::FVT_beam_force_axial: return beamEA*gamma1;
3623 case FieldVariableDescriptor::FVT_beam_moment: return fvd.GetComponent(Vector3D(beamGJ*kappa1, beamEIy*kappa2, beamEIz*kappa3));
3624 case FieldVariableDescriptor::FVT_beam_moment_torsional: return beamGJ*kappa1;
3625 default: return Body3D::GetFieldVariableValue(fvd, ploc, flagD);
3626 }
3627
3628 return FIELD_VARIABLE_NO_VALUE;
3629 }
3630
3631
3632