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