proteus 1.9.0
C/C++/Fortran libraries
Loading...
Searching...
No Matches
ProtChMoorings.h
Go to the documentation of this file.
1//#pragma once
2
3#define _USE_MATH_DEFINES
4
5#include <iostream>
6#include <math.h>
7#include <string>
8#include "chrono/physics/ChSystem.h"
9#include "chrono/physics/ChSystemSMC.h"
10#include "chrono/physics/ChLoadContainer.h"
11#include "chrono/physics/ChLinkMate.h"
12#include "chrono/physics/ChBodyEasy.h"
13#include "chrono/physics/ChContactMaterial.h"
14#include "chrono/physics/ChContactMaterialSMC.h"
15#include "chrono/fea/ChElementBeamANCF_3333.h"
16#include "chrono/fea/ChElementCableANCF.h"
17#include "chrono/fea/ChElementBeamEuler.h"
18#include "chrono/fea/ChBeamSection.h"
19#include "chrono/fea/ChMesh.h"
20#include "chrono/fea/ChLinkNodeNode.h"
21#include "chrono/fea/ChLinkNodeFrame.h"
22#include "chrono/fea/ChLinkNodeSlopeFrame.h"
23#include "chrono/fea/ChLoadsBeam.h"
24#include "chrono/fea/ChContactSurfaceNodeCloud.h"
25#include "chrono/timestepper/ChTimestepper.h"
26
27
28//using namespace std;
29using namespace chrono;
30using namespace fea;
31
32
33// override some functions of ChElement
34
35class ChElementCableANCFmod : public ChElementCableANCF {
36private:
37 ChVectorN<double, 12> m_GenForceVec0;
38 virtual void SetupInitial(ChSystem* system) override {
39 assert(GetSection());
40
41 // ChElementANCF (a base of ChElementCableANCF) tracks each element's
42 // active-DOF count in m_element_dof (default-constructed to 0) plus
43 // m_full_dof/m_mapping_dof for the case where some node DOFs are fixed.
44 // ChElementCableANCF::SetupInitial() computes these, but it's private
45 // in the base class so it can't be called directly from here -- this
46 // override replaces it entirely rather than extending it, and without
47 // this block m_element_dof silently stays 0. Chrono's system assembly
48 // sizes this element's contribution off GetNumCoordsPosLevelActive()
49 // (== m_element_dof), so leaving it at 0 while ComputeInternalForces()
50 // below still writes a full 12-entry result is a real size mismatch --
51 // confirmed via gdb to segfault inside Eigen's dense assignment kernel,
52 // called from here by way of ComputeInternalForces_Impl.
53 m_element_dof = 0;
54 for (int i = 0; i < 2; i++) {
55 m_element_dof += (i == 0 ? GetNodeA() : GetNodeB())->GetNumCoordsPosLevel();
56 }
57 m_full_dof = (m_element_dof == 2 * 6);
58 if (!m_full_dof) {
59 m_mapping_dof.resize(m_element_dof);
60 int dof = 0;
61 for (int i = 0; i < 2; i++) {
62 auto node = (i == 0 ? GetNodeA() : GetNodeB());
63 for (unsigned int j = 0; j < node->GetNumCoordsPosLevel(); j++)
64 m_mapping_dof(dof++) = i * 6 + j;
65 }
66 }
67
68 // Compute rest length, mass:
69 //double length2 = (nodes[1]->GetX0() - nodes[0]->GetX0()).Length();
70 //this->mass = this->length * GetSection()->Area * GetSection()->density;
71 this->mass = this->length * GetDensity();
72
73 // Here we calculate the internal forces in the initial configuration
74 // Contribution of initial configuration in elastic forces is automatically subtracted
75 ChVectorDynamic<> FVector0(12);
76 FVector0.setZero();
77 m_GenForceVec0.setZero();
78 ComputeInternalForces(FVector0);
79 m_GenForceVec0 = FVector0;
80
81 // Compute mass matrix
82 ComputeMassMatrix();
83 };
84};
85
86// --- Chrono-agnostic access to ChElementBeamEuler::q_element_ref_rot ---
87// This data member is private in stock/upstream Chrono. ChElementBeamEulermod
88// below needs to WRITE it in its own SetupInitial() override -- an override
89// that exists in the first place because ChElementBeamEuler::SetupInitial()
90// is *itself* private, so it cannot be called by name from a subclass and
91// must be fully reimplemented; UpdateRotation()/ComputeInternalJacobians()/
92// etc (inherited unmodified, not overridden) then read *this exact* member,
93// so it has to be the real one, not a same-named shadow declared in the
94// subclass (that was the original bug here: a shadow left the base's own
95// copy stuck at its default/identity value).
96//
97// Rather than depend on a Chrono fork/patch promoting the member to
98// protected (which then only compiles against that patched Chrono, not
99// e.g. conda-forge's stock prebuilt pychrono package), use the standard
100// (legal, if obscure) C++ "steal a private member via explicit template
101// instantiation" idiom: forming a pointer-to-member as an explicit template
102// argument isn't access-checked the way a normal member-access expression
103// is, and dereferencing the resulting pointer-to-member isn't
104// access-checked at all -- so this compiles and works regardless of the
105// member's actual access specifier, with no Chrono source changes needed.
106// See e.g. https://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html
107template <typename Tag, typename Tag::type Member>
109 friend typename Tag::type chronoPrivateMemberThief(Tag) { return Member; }
110};
111
113 using type = ChQuaternion<> chrono::fea::ChElementBeamEuler::*;
115};
117 &chrono::fea::ChElementBeamEuler::q_element_ref_rot>;
118
119inline ChQuaternion<>& q_element_ref_rot_of(chrono::fea::ChElementBeamEuler& el) {
120 return el.*chronoPrivateMemberThief(ChElementBeamEuler_q_element_ref_rot_tag());
121}
122
123class ChElementBeamEulermod : public ChElementBeamEuler {
124private:
125 virtual void SetupInitial(ChSystem* system) override {
126 assert(GetSection());
127
128 // Compute rest length, mass:
129 //this->length = (nodes[1]->GetX0().GetPos() - nodes[0]->GetX0().GetPos()).Length();
130 //this->mass = this->length * GetSection()->Area * GetSection()->density;
131 this->mass = this->length * GetDensity();
132
133 // Compute initial rotation
134 ChMatrix33<> A0;
135 auto node0 = GetNodeA();
136 auto node1 = GetNodeB();
137 ChVector3d mXele = node1->GetX0().GetPos() - node0->GetX0().GetPos();
138 // Matches the base class's own average-of-both-nodes computation
139 // (ChElementBeamEuler::SetupInitial): using only node0's Y-axis here
140 // instead is only equivalent when both nodes already share the same
141 // reference rotation.
142 ChVector3d myele = (node0->GetX0().GetRotMat().GetAxisY()
143 + node1->GetX0().GetRotMat().GetAxisY()).GetNormalized();
144 A0.SetFromAxisX(mXele, myele);
145 q_element_ref_rot_of(*this) = A0.GetQuaternion();
146
147 // Set each node's reference rotation relative to the element's own
148 // frame (q_refrotA/q_refrotB, read by UpdateRotation() to remove the
149 // effect of each node's own reference-to-current rotation offset when
150 // computing the corotational frame). This override previously never
151 // called these -- unlike ChBuilderBeamEuler::BuildBeam(), the official
152 // way to build these elements -- leaving q_refrotA/q_refrotB stuck at
153 // their default-constructed identity, which is only correct by
154 // coincidence when a node's own initial rotation already matches the
155 // element's. Matches ChBuilderBeamEuler::BuildBeam()'s own logic
156 // exactly (chrono/fea/ChBuilderBeam.cpp).
157 SetNodeAreferenceRot(q_element_ref_rot_of(*this).GetConjugate() * node0->GetX0().GetRot());
158 SetNodeBreferenceRot(q_element_ref_rot_of(*this).GetConjugate() * node1->GetX0().GetRot());
159
160 // Compute local stiffness matrix:
161 ComputeStiffnessMatrix();
162
163 // Compute local geometric stiffness matrix normalized by pull force P: Kg/P
164 // (this override previously skipped this entirely -- ChElementBeamEuler::
165 // ComputeInternalJacobians() reads the resulting Kg matrix, and leaving it
166 // at its default-constructed size/contents is the same class of bug fixed
167 // above for ChElementCableANCFmod: a Chrono-expected setup step silently
168 // skipped by this override.)
169 ComputeGeometricStiffnessMatrix();
170 };
171};
172
173
174class MyLoaderTriangular : public ChLoaderUdistributed {
175public:
176 // Useful: a constructor that also sets ChLoadable
177 ChVector3d Fa;
178 ChVector3d Fb;
179 MyLoaderTriangular(std::shared_ptr<ChLoadableU> mloadable):
180 ChLoaderUdistributed(mloadable) {
181 Fa = ChVector3d(0.,0.,0.);
182 Fb = ChVector3d(0.,0.,0.);
183 };
184 // Compute F=F(u)
185 // This is the function that you have to implement. It should return the
186 // load at U. For Eulero beams, loads are expected as 6-rows vectors, containing
187 // a wrench: forceX, forceY, forceZ, torqueX, torqueY, torqueZ.
188 virtual void ComputeF(const double U,
189 ChVectorDynamic<>& F,
190 ChVectorDynamic<>* state_x,
191 ChVectorDynamic<>* state_w
192 ) {
193 double Fy_max = 0.005;
194 ChVector3d force = Fa*abs(-1+U)/2.+Fb*(1+U)/2.;
195 F(0) = force.x();
196 F(1) = force.y();
197 F(2) = force.z();
198 }
199 void SetF(ChVector3d Fa_in, ChVector3d Fb_in) {
200 Fa = Fa_in;
201 Fb = Fb_in;
202 }
203 // Needed because inheriting ChLoaderUdistributed. Use 1 because linear load fx.
204 virtual int GetIntegrationPointsU() { return 1; }
205};
206// Create the load (and handle it with a shared pointer).
207// The ChLoad is a 'container' for your ChLoader.
208// It is created using templates, that is instancing a ChLoad<a_loader_class>()
209//std::shared_ptr<ChLoad<MyLoaderTriangular>> mloadtri(new ChLoad<MyLoaderTriangular>(melementA));
210//mloadcontainer->Add(mloadtri); // do not forget to add the load to the load container.
211
212
213class cppCable {
214public:
215 std::shared_ptr<ChSystem> system; // global system
216 std::shared_ptr<ChMesh> mesh; // mesh
217 int nb_elems; // number of nodes along cable
218 std::vector<double> length_per_elem; // length of each element on the cable
219 double Cd_axial; // drag coeff in axial direction
220 double Cd_normal; // drag coeff in normal direction
221 double Cm_axial; // added mass coeff in axial direction
222 double Cm_normal; // added mass coeff in normal direction
223 std::vector<ChVector3d> mvecs; // vectors (nodes coordinates)
224 std::vector<ChVector3d> mvecs_tangents; // vectors (tangents at nodes coordinates)
225 std::vector<ChVector3d> mvecs_middle;
226 std::vector<ChVector3d> mdirs; // vectors (nodes coordinates)
227 double d, rho, E, length; // diameter, density, Young's modulus, length of cable
228 double A0; // unstretched diameter
229 double L0 = 0; // initial length along cable
230 double Iyy;
235 std::string beam_type;
236 std::vector<std::shared_ptr<ChNodeFEAxyzD>> nodes; // array nodes coordinates and direction
237 std::vector<std::shared_ptr<ChNodeFEAxyzDD>> nodesDD; // array nodes coordinates and direction
238 std::vector<std::shared_ptr<ChElementCableANCF>> elemsCableANCF; // array of elements */
239 std::vector<std::shared_ptr<ChElementBeamEuler>> elemsBeamEuler; // array of elements */
240 std::vector<std::shared_ptr<ChNodeFEAxyzrot>> nodesRot; // array nodes coordinates and direction
241 std::vector<std::shared_ptr<ChElementCableANCF>> elems_cable; // array of elements */
242 std::shared_ptr<ChBeamSectionCable> msection_cable; // cable material
243 std::shared_ptr<ChBeamSectionAdvanced> msection_advanced; // cable material
244 std::vector<double> elems_length; // array of elements
245 std::vector<ChVector3d> fluid_velocity;
246 std::vector<ChVector3d> fluid_acceleration;
247 std::vector<double> fluid_density;
248 std::vector<double> nodes_density; // density of (cable-fluid) at nodes
249 cppCable(std::shared_ptr<ChSystem> system, std::shared_ptr<ChMesh> mesh, double length,
250 int nb_elems, double d, double rho, double E, double L0, std::string beam_type); // constructor
251 void setFluidVelocityAtNodes(std::vector<ChVector3d> vel);
252 void setFluidAccelerationAtNodes(std::vector<ChVector3d> acc);
253 void setFluidDensityAtNodes(std::vector<double> vof);
254 std::vector<std::shared_ptr<ChVector3d>> getNodalPositions();
255 std::vector<std::shared_ptr<ChVector3d>> forces_drag;
256 std::vector<std::shared_ptr<ChVector3d>> forces_addedmass;
257 /* std::vector<std::shared_ptr<ChLoadBeamWrenchDistributed>> elems_loads_distributed; */
258 std::vector<std::shared_ptr<ChLoad>> elems_loads_triangular;
259 std::vector<std::shared_ptr<ChLoad>> elems_loads_volumetric;
260 /* std::vector<std::shared_ptr<ChLoadBeamWrench>> elems_loads; */
261 void buildVectors(); // builds location vectors for the nodes
262 void buildNodes(bool last_node); // builds the nodes for the mesh
263 void buildNodesBeamEuler(bool last_node); // builds the nodes for the mesh
264 void buildNodesCableANCF(bool last_node); // builds the nodes for the mesh
265 void buildElements(bool set_lastnodes); // builds the elements for the mesh
266 void buildElementsBeamEuler(bool set_lastnodes); // builds the elements for the mesh
267 void buildElementsCableANCF(bool set_lastnodes); // builds the elements for the mesh
268 void buildMesh(bool add_lastnode); // builds the mesh
269 void buildMeshBeamEuler(bool add_lastnode); // builds the mesh
270 void buildMeshCableANCF(bool add_lastnode); // builds the mesh
271 void setDragForce(); // calculates the drag force per nodes
272 void setAddedMassForce(); // calculates the added mass force per nodes
273 void applyForces();
274 void addNodestoContactCloud(std::shared_ptr<ChContactSurfaceNodeCloud> cloud);
275 void setDragCoefficients(double axial, double normal);
276 void setAddedMassCoefficients(double axial, double normal);
277 void setRestLengthPerElement(std::vector<double> length_array);
278 void setIyy(double Iyy_in);
279};
280
282public:
283 std::shared_ptr<ChSystem> system; // global system
284 std::string beam_type;
285 std::shared_ptr<ChContactMaterialSMC> mysurfmaterial;
286 std::shared_ptr<ChMesh> mesh; // mesh
287 std::shared_ptr<ChBody> fairleadd;
288 std::shared_ptr<ChLinkNodeFrame> fairlead2;
289 std::vector<int> nb_nodes; // number of nodes along cable
290 std::vector<int> nb_elems; // number of nodes along cable
291 std::vector<ChVector3d> mvecs; // vectors (nodes coordinates)
292 std::vector<std::shared_ptr<cppCable>> cables;
293 std::shared_ptr<ChContactMaterialSMC> contact_material; // mesh
294 std::vector<double> d;
295 std::vector<double> rho;
296 std::vector<double> E;
297 std::vector<double> length; // diameter, density, Young's modulus, length of cable
298 std::vector<std::shared_ptr<ChNodeFEAxyzD>> nodes; // array nodes coordinates and direction
299 std::vector<std::shared_ptr<ChNodeFEAxyzDD>> nodesDD; // array nodes coordinates and direction
300 std::vector<std::shared_ptr<ChNodeFEAxyzrot>> nodesRot; // array nodes coordinates and direction
301 std::vector<ChVector3d> fluid_velocity;
302 std::vector<ChVector3d> fluid_acceleration;
303 std::vector<double> fluid_density;
304 std::vector<std::shared_ptr<ChElementCableANCF>> elemsCableANCF; // array of elements */
305 std::vector<std::shared_ptr<ChElementBeamEuler>> elemsBeamEuler; // array of elements */
306 std::shared_ptr<ChLinkBase> constraint_front;
307 std::shared_ptr<ChLinkBase> constraint_back;
308 std::vector<std::shared_ptr<ChVector3d>> forces_drag;
309 std::vector<std::shared_ptr<ChVector3d>> forces_addedmass;
310 std::shared_ptr<ChBody> body_back;
311 std::shared_ptr<ChBody> body_front;
317 cppMultiSegmentedCable(std::shared_ptr<ChSystem> system,
318 std::shared_ptr<ChMesh> mesh,
319 std::vector<double> length,
320 std::vector<int> nb_nodes,
321 std::vector<double> d,
322 std::vector<double> rho,
323 std::vector<double> E,
324 std::string beam_type);
325 void setFluidVelocityAtNodes(std::vector<ChVector3d> vel);
326 void setFluidAccelerationAtNodes(std::vector<ChVector3d> vel);
327 void setFluidDensityAtNodes(std::vector<double> dens);
328 void updateDragForces();
330 void applyForces();
331 std::vector<std::shared_ptr<ChVector3d>> getNodalPositions();
332 void buildNodes();
333 void buildElements();
334 void buildCable(); // builds the multi-segmented cable
336
337 void attachBackNodeToBody(std::shared_ptr<ChBody> body);
338 void attachFrontNodeToBody(std::shared_ptr<ChBody> body);
339 void setContactMaterial(std::shared_ptr<ChContactMaterialSMC> material);
340 void buildNodesCloud();
341 ChVector3d getTensionElement(int i, double eta);
342};
343
344
346 std::shared_ptr<ChMesh> mesh,
347 std::vector<double> length,
348 std::vector<int> nb_elems,
349 std::vector<double> d,
350 std::vector<double> rho,
351 std::vector<double> E,
352 std::string beam_type="CableANCF"):
353 system(system),
354 mesh(mesh),
355 length(length),
357 d(d),
358 rho(rho),
359 E(E),
361{
362 nodes_built = false;
363 elems_built = false;
364 nodes_chlink = true; // build links (true) or link elements directly (false)
365
366 std::shared_ptr<cppCable> segment;
367 double L0 = 0;
368 for (int i = 0; i < length.size(); ++i) {
369 segment = std::make_shared<cppCable>(system,
370 mesh,
371 length[i],
372 nb_elems[i],
373 d[i],
374 rho[i],
375 E[i],
376 L0,
377 beam_type);
378 cables.push_back(segment);
379 L0 = L0 + length[i];
380 }
381}
382
384 nodes.clear();
385 nodesRot.clear();
386 for (int i = 0; i < cables.size(); ++i) {
387 if (beam_type == "BeamEuler") {
388 cables[i]->buildNodes(true);
389 nodesRot.insert(nodesRot.end(),
390 cables[i]->nodesRot.begin(),
391 cables[i]->nodesRot.end());
392 nb_nodes_tot = nodesRot.size();
393 }
394 else if (beam_type == "CableANCF") {
395 if (nodes_chlink == false && i < cables.size()-1) {
396 cables[i]->buildNodes(false);
397 }
398 else {
399 cables[i]->buildNodes(true);
400 }
401 nodes.insert(nodes.end(),
402 cables[i]->nodes.begin(),
403 cables[i]->nodes.end());
404 nb_nodes_tot = nodes.size();
405 }
406 }
407 nodes_built = true;
408}
409
411 elemsCableANCF.clear();
412 elemsBeamEuler.clear();
413 for (int i = 0; i < cables.size(); ++i) {
414 if (i < cables.size()-1 && nodes_chlink == false) {
415 cables[i]->buildElements(false);
416 if (beam_type == "CableANCF") {
417 cables[i]->elemsCableANCF[cables[i]->elemsCableANCF.size()-1]->SetNodes(cables[i]->nodes[cables[i]->nodes.size()-1], cables[i+1]->nodes[0]);
418 }
419 else if (beam_type == "BeamEuler") {
420 cables[i]->elemsBeamEuler[cables[i]->elemsBeamEuler.size()-1]->SetNodes(cables[i]->nodesRot[cables[i]->nodesRot.size()-1], cables[i+1]->nodesRot[0]);
421 }
422 }
423 else {
424 cables[i]->buildElements(true);
425 }
426 if (beam_type == "CableANCF") {
427 elemsCableANCF.insert(elemsCableANCF.end(), cables[i]->elemsCableANCF.begin(), cables[i]->elemsCableANCF.end());
429 }
430 else if (beam_type == "BeamEuler") {
431 elemsBeamEuler.insert(elemsBeamEuler.end(), cables[i]->elemsBeamEuler.begin(), cables[i]->elemsBeamEuler.end());
433 }
434 }
435 elems_built = true;
436}
437
439 /* builds all cable segments and updates their link
440 (no duplicate node added to mesh) */
441 if (nodes_built == false) {
442 buildNodes();
443 }
444 if (elems_built == false) {
446 }
447 for (int i = 0; i < cables.size(); ++i) {
448 if (i < cables.size()-1 && nodes_chlink == false) {
449 cables[i]->buildMesh(false);
450 }
451 else {
452 cables[i]->buildMesh(true);
453 }
454 if (nodes_chlink == true) {
455 if (i>0) {
456 if (beam_type == "BeamEuler") {
457 auto con1 = chrono_types::make_shared<ChLinkMateSpherical>();
458 auto nodeA = cables[i]->nodesRot.front();
459 auto nodeB = cables[i-1]->nodesRot.back();
460 con1->Initialize(nodeA, nodeB, false, nodeA->GetPos(), nodeA->GetPos());
461 system->Add(con1);
462 }
463 else if (beam_type == "CableANCF") {
464 auto con1 = chrono_types::make_shared<ChLinkNodeNode>();
465 auto nodeA = cables[i]->nodes.front();
466 auto nodeB = cables[i-1]->nodes.back();
467 con1->Initialize(nodeA, nodeB);
468 system->Add(con1);
469 }
470 }
471 }
472 forces_drag.insert(forces_drag.end(), cables[i]->forces_drag.begin(), cables[i]->forces_drag.end());
473 forces_addedmass.insert(forces_addedmass.end(), cables[i]->forces_addedmass.begin(), cables[i]->forces_addedmass.end());
474 }
476 fluid_velocity.clear();
477 fluid_acceleration.clear();
478 fluid_density.clear();
479 if (beam_type == "BeamEuler") {
480 nb_nodes_tot = nodesRot.size();
481 }
482 else if (beam_type == "CableANCF") {
483 nb_nodes_tot = nodes.size();
484 }
485 for (int i = 0; i < nb_nodes_tot; ++i) {
486 fluid_velocity.push_back(ChVector3d(0.,0.,0.));
487 fluid_acceleration.push_back(ChVector3d(0.,0.,0.));
488 fluid_density.push_back(0.);
489 }
493}
494
496 fluid_acceleration = acc;
497 int node_nb = 0;
498 int node_nb_prev = node_nb;
499 for (int i = 0; i < cables.size(); ++i) {
500 if (beam_type == "BeamEuler") {
501 node_nb += cables[i]->nodesRot.size();
502 }
503 else if (beam_type == "CableANCF") {
504 node_nb += cables[i]->nodes.size();
505 }
506 std::vector<ChVector3d> fluid_acc(fluid_acceleration.begin()+node_nb_prev,
507 fluid_acceleration.begin()+node_nb);
508 cables[i]->setFluidAccelerationAtNodes(fluid_acc);
509 node_nb_prev = node_nb;
510 }
511}
512
515 int node_nb = 0;
516 int node_nb_prev = node_nb;
517 for (int i = 0; i < cables.size(); ++i) {
518 if (beam_type == "BeamEuler") {
519 node_nb += cables[i]->nodesRot.size();
520 }
521 else if (beam_type == "CableANCF") {
522 node_nb += cables[i]->nodes.size();
523 }
524 std::vector<ChVector3d> fluid_vel(fluid_velocity.begin()+node_nb_prev,
525 fluid_velocity.begin()+node_nb);
526 cables[i]->setFluidVelocityAtNodes(fluid_vel);
527 node_nb_prev = node_nb;
528 }
529}
530
532 fluid_density = dens;
533 int node_nb = 0;
534 int node_nb_prev = 0;
535 for (int i = 0; i < cables.size(); ++i) {
536 if (beam_type == "BeamEuler") {
537 node_nb += cables[i]->nodesRot.size();
538 }
539 else if (beam_type == "CableANCF") {
540 node_nb += cables[i]->nodes.size();
541 }
542 std::vector<double> fluid_dens(fluid_density.begin()+node_nb_prev,
543 fluid_density.begin() + node_nb);
544 cables[i]->setFluidDensityAtNodes(fluid_dens);
545 node_nb_prev = node_nb;
546 }
547}
548
549
551 for (int i = 0; i < cables.size(); ++i) {
552 cables[i]->setDragForce();
553 };
554}
555
557 for (int i = 0; i < cables.size(); ++i) {
558 cables[i]->setAddedMassForce();
559 };
560}
561
563 for (int i = 0; i < cables.size(); ++i) {
564 cables[i]->applyForces();
565 };
566}
567
568ChVector3d cppMultiSegmentedCable::getTensionElement(int i, const double eta=0.) {
569
570 auto force = ChVector3d();
571 auto torque = ChVector3d();
572 if (beam_type == "CableANCF") {
573 elemsCableANCF[i]->EvaluateSectionForceTorque(eta,
574 force,
575 torque);
576 elemsCableANCF[i]->EvaluateSectionStrain(eta,
577 force);
578 }
579 else if (beam_type == "BeamEuler") {
580 auto mat2 = ChMatrixDynamic<>();
581 elemsBeamEuler[i]->EvaluateSectionForceTorque(eta,
582 force,
583 torque);
584 }
585 return force;
586}
587
588std::vector<std::shared_ptr<ChVector3d>> cppMultiSegmentedCable::getNodalPositions() {
589 std::vector<std::shared_ptr<ChVector3d>> nodal_positions;
590 for (int i = 0; i < nodes.size(); ++i) {
591 auto pos = nodes[i]->GetPos();
592 double x = pos.x();
593 double y = pos.y();
594 double z = pos.z();
595 auto nodal_position = chrono_types::make_shared<ChVector3d>(x, y, z);
596 nodal_positions.push_back(nodal_position);
597 }
598 return nodal_positions;
599}
600
601void cppMultiSegmentedCable::attachBackNodeToBody(std::shared_ptr<ChBody> body) {
602 if (beam_type == "BeamEuler") {
603 auto constraint = chrono_types::make_shared<ChLinkMateSpherical>();
604 constraint->Initialize(nodesRot.back(), body, false, nodesRot.back()->GetPos(), nodesRot.back()->GetPos());
605 system->Add(constraint);
606 body_back = body;
607 constraint_back = constraint;
608 }
609 else {
610 auto constraint = chrono_types::make_shared<ChLinkNodeFrame>();
611 constraint->Initialize(nodes.back(), body);
612 system->Add(constraint);
613 body_back = body;
614 constraint_back = constraint;
615 }
616};
617
618void cppMultiSegmentedCable::attachFrontNodeToBody(std::shared_ptr<ChBody> body) {
619 if (beam_type == "BeamEuler") {
620 auto constraint = chrono_types::make_shared<ChLinkMateSpherical>();
621 constraint->Initialize(nodesRot.front(), body, false, nodesRot.front()->GetPos(), nodesRot.front()->GetPos());
622 system->Add(constraint);
623 body_front = body;
624 constraint_front = constraint;
625 }
626 else if (beam_type == "CableANCF") {
627 auto constraint = chrono_types::make_shared<ChLinkNodeFrame>();
628 constraint->Initialize(nodes.front(), body);
629 system->Add(constraint);
630 body_front = body;
631 constraint_front = constraint;
632 }
633};
634
635void cppMultiSegmentedCable::setContactMaterial(std::shared_ptr<ChContactMaterialSMC> material) {
636 contact_material = material;
637};
638
640 if (contact_material) {
641 // Use DEM surface material properties
642 auto contact_cloud = chrono_types::make_shared<ChContactSurfaceNodeCloud>(contact_material);
643 //auto contact_cloud = chrono_types::make_shared<ChContactSurfaceNodeCloud>();
644 mesh->AddContactSurface(contact_cloud);
645 //contact_cloud->SetMaterialSurface(contact_material);
646 // add cable nodes to cloud
647 for (int i = 0; i < cables.size(); ++i) {
648 cables[i]->addNodestoContactCloud(contact_cloud);
649 }
650 }
651};
652
653
654cppCable::cppCable(std::shared_ptr<ChSystem> system, // system in which the cable belong
655 std::shared_ptr<ChMesh> mesh, // mesh of the cable
656 double length, // length of cable
657 int nb_elems, // number of nodes along cable
658 double d, // diameter of cable
659 double rho, // density of cable (kg/m3)
660 double E, // Young's modulus
661 double L0 = 0,
662 std::string beam_type = "CableANCF"
663 ) :
664 system(system),
665 mesh(mesh),
666 length(length),
668 d(d),
669 rho(rho),
670 E(E),
671 L0(L0),
673{
674 Cd_axial = 1.15; // studless chain
675 Cd_normal = 1.4; // studless chain
676 Cm_axial = 0.5; //studless chain
677 Cm_normal = 1.; // studless chain
678 A0 = d*d/4*M_PI;
679 /* Iyy = 1e-12; */
680 applyDrag = true;
681 applyAddedMass = true;
682 applyBuoyancy = true;
683 for (int i = 0; i < nb_elems; i++) {
685 }
686 if (beam_type == "CableANCF") {
687 msection_cable = chrono_types::make_shared<ChBeamSectionCable>();
688 msection_cable->SetDiameter(d);
689 msection_cable->SetYoungModulus(E);
690 msection_cable->SetDensity(rho);
691 /* msection_cable->SetInertia(Iyy); */
692 Iyy = msection_cable->GetInertia();
693 }
694 else if (beam_type == "BeamEuler") {
695 msection_advanced = chrono_types::make_shared<ChBeamSectionAdvanced>();
696 msection_advanced->SetYoungModulus(E);
697 // NOTE: this was hardcoded to 1e-6 -- with E often ~1e10, that's a
698 // stiffness ratio of ~1e16 between axial/bending and shear/torsional
699 // rigidity, which is numerically catastrophic for the solver (drove a
700 // clean simulation to explode to ~1e163 within a handful of Newton
701 // iterations on the very first timestep). Derive G from E via a
702 // plausible Poisson's ratio instead, using Chrono's own convenience
703 // method (same one its default constructor uses).
704 msection_advanced->SetShearModulusFromPoisson(0.3);
705 msection_advanced->SetDensity(rho);
706 msection_advanced->SetAsCircularSection(d);
707 /* msection_advanced->SetIyy(Iyy); */
708 /* msection_advanced->SetIzz(Iyy); */
709 Iyy = msection_advanced->GetIyy();
710 }
711}
712
713void cppCable::setIyy(double Iyy_in) {
714 Iyy = Iyy_in;
715 if (beam_type == "CableANCF") {
716 msection_cable->SetInertia(Iyy);
717 }
718 else if (beam_type == "BeamEuler") {
719 msection_advanced->SetIyy(Iyy);
720 msection_advanced->SetIzz(Iyy);
721 }
722}
723
724void cppCable::buildNodes(bool last_node=true) {
725 if (beam_type == "CableANCF") {buildNodesCableANCF(last_node);}
726 else if (beam_type == "BeamEuler") {buildNodesBeamEuler(last_node);}
727}
728
729void cppCable::buildNodesBeamEuler(bool last_node) {
730 nodesRot.clear();
731 forces_drag.clear();
732 forces_addedmass.clear();
733 std::shared_ptr<ChNodeFEAxyzrot> node;
734 ChVector3d dir; // direction of node
735 ChVector3d ref = ChVector3d(1.,0.,0.);
736 ChQuaternion<> frame_quat;
737 for (int i = 0; i < mvecs.size() - 1; ++i) {
738 dir = mvecs_tangents[i];
739 dir.Normalize();
740 double ang = acos(dir^ref); // inner product
741 auto axis = ref%dir; // cross product
742 axis.Normalize();
743 frame_quat.SetFromAngleAxis(ang, axis);
744 node = chrono_types::make_shared<ChNodeFEAxyzrot>(ChFrame<>(mvecs[i],
745 frame_quat));
746 nodesRot.push_back(node);
747 std::shared_ptr<ChVector3d> drag0 = chrono_types::make_shared<ChVector3d>(0.,0.,0.);
748 std::shared_ptr<ChVector3d> am0 = chrono_types::make_shared<ChVector3d>(0.,0.,0.);
749 forces_drag.push_back(drag0);
750 forces_addedmass.push_back(am0);
751 } // last node
752 if (last_node == true) {
753 dir = mvecs_tangents[mvecs.size()-1];
754 dir.Normalize();
755 // NOTE: this used to be `-acos(dir^ref)` (opposite sign from every
756 // other node's angle above), which pointed this node's local X-axis
757 // backward (antiparallel to the tangent) instead of forward like all
758 // the other nodes -- the ANCF equivalent (buildNodesCableANCF above)
759 // treats its last node identically to every other node, with no such
760 // flip, confirming this was a bug rather than a deliberate convention.
761 // It went unnoticed because nothing read a node's reference rotation
762 // until ChElementBeamEulermod::SetupInitial() started calling
763 // SetNodeAreferenceRot/SetNodeBreferenceRot: with the flipped sign,
764 // the last element's q_refrotA/q_refrotB pointed opposite directions,
765 // so UpdateRotation()'s (myele_wA + myele_wB) nearly canceled to a
766 // near-zero vector, sending SetFromAxisX/GetDirectionAxesAsX a
767 // degenerate input and crashing (SIGBUS) in Chrono's unbounded search
768 // loop for a non-parallel suggested axis.
769 double ang = acos(dir^ref); // inner product
770 auto axis = ref%dir; // cross product
771 axis.Normalize();
772 frame_quat.SetFromAngleAxis(ang, axis);
773 node = chrono_types::make_shared<ChNodeFEAxyzrot>(ChFrame<>(mvecs[mvecs.size()-1],
774 frame_quat));
775 nodesRot.push_back(node);
776 nb_nodes = nodesRot.size();
777 nb_elems = nb_nodes-1;
778 std::shared_ptr<ChVector3d> drag0 = chrono_types::make_shared<ChVector3d>(0.,0.,0.);
779 std::shared_ptr<ChVector3d> am0 = chrono_types::make_shared<ChVector3d>(0.,0.,0.);
780 forces_drag.push_back(drag0);
781 forces_addedmass.push_back(am0);
782 }
783 else {
784 nb_nodes = nodesRot.size();
786 }
787}
788
789void cppCable::buildNodesCableANCF(bool last_node) {
790 nodes.clear();
791 forces_drag.clear();
792 forces_addedmass.clear();
793 std::shared_ptr<ChNodeFEAxyzD> node;
794 ChVector3d dir; // direction of node
795 ChCoordsys<> coordsys; // coordinate system of node
796 for (int i = 0; i < mvecs.size() - 1; ++i) {
797 dir = mvecs_tangents[i];
798 dir.Normalize();
799 node = chrono_types::make_shared<ChNodeFEAxyzD>(mvecs[i], dir);
800 nodes.push_back(node);
801 std::shared_ptr<ChVector3d> drag0 = chrono_types::make_shared<ChVector3d>(0.,0.,0.);
802 std::shared_ptr<ChVector3d> am0 = chrono_types::make_shared<ChVector3d>(0.,0.,0.);
803 forces_drag.push_back(drag0);
804 forces_addedmass.push_back(am0);
805 } // last node
806 if (last_node == true) {
807 dir = mvecs_tangents[mvecs_tangents.size()-1];
808 dir.Normalize();
809 node = chrono_types::make_shared<ChNodeFEAxyzD>(mvecs[mvecs.size()-1], dir);
810 nodes.push_back(node);
811 nb_nodes = nodes.size();
812 nb_elems = nb_nodes-1;
813 std::shared_ptr<ChVector3d> drag0 = chrono_types::make_shared<ChVector3d>(0.,0.,0.);
814 std::shared_ptr<ChVector3d> am0 = chrono_types::make_shared<ChVector3d>(0.,0.,0.);
815 forces_drag.push_back(drag0);
816 forces_addedmass.push_back(am0);
817 }
818 else {
819 nb_nodes = nodes.size();
821 }
822}
823
824void cppCable::buildElements(bool set_lastnodes=true) {
825 if (beam_type == "CableANCF") {
826 buildElementsCableANCF(set_lastnodes);
827 }
828 else if (beam_type == "BeamEuler") {
829 buildElementsBeamEuler(set_lastnodes);
830 }
831}
832
833void cppCable::buildElementsCableANCF(bool set_lastnodes) {
834 auto loadcontainer = chrono_types::make_shared<ChLoadContainer>();
835 system->Add(loadcontainer);
836 mesh->SetAutomaticGravity(false); // proteus already applies gravity manually below via ChLoaderGravity
837 // build elements
838 elemsCableANCF.clear();
839 /* elems_loads_distributed.clear(); */
842 /* elems_loads.clear(); */
843 for (int i = 0; i < nb_elems; ++i) {
844 auto element = chrono_types::make_shared<ChElementCableANCFmod>();
845 auto load_distributed = chrono_types::make_shared<ChLoadBeamWrenchDistributed>(element);
846 auto load = chrono_types::make_shared<ChLoadBeamWrench>(element);
847 auto gravity = chrono_types::make_shared<ChLoaderGravity>(element);
848 gravity->SetGravitationalAcceleration(system->GetGravitationalAcceleration());
849 std::shared_ptr<ChLoad> loadtri(new ChLoad(gravity));
850 auto load_volumetric = chrono_types::make_shared<ChLoad>(gravity);
851 /* loadcontainer->Add(load_distributed); */
852 /* loadcontainer->Add(load); */
853 // NOTE: loadtri and load_volumetric both wrap the same `gravity`
854 // ChLoaderGravity instance; adding both to the loadcontainer applied
855 // gravity twice. Only load_volumetric is added now; loadtri is left
856 // constructed (and still pushed to elems_loads_triangular below) in
857 // case other code expects a valid object there, but it no longer
858 // contributes force.
859 loadcontainer->Add(load_volumetric);
860 elemsCableANCF.push_back(element);
861 /* elems_loads_distributed.push_back(load_distributed); */
862 /* elems_loads.push_back(load); */
863 elems_loads_triangular.push_back(loadtri);
864 elems_loads_volumetric.push_back(load_volumetric);
865 element->SetSection(msection_cable);
866 element->SetRestLength(length_per_elem[i]);
867 if (i < nb_elems-1) {
868 element->SetNodes(nodes[i], nodes[i + 1]);
869 }
870 else {
871 if (set_lastnodes == true) {
872 element->SetNodes(nodes[i], nodes[i + 1]);
873 }
874 }
875 }
876}
877
878void cppCable::buildElementsBeamEuler(bool set_lastnodes) {
879 auto loadcontainer = chrono_types::make_shared<ChLoadContainer>();
880 system->Add(loadcontainer);
881 mesh->SetAutomaticGravity(false); // proteus already applies gravity manually below via ChLoaderGravity
882 // build elements
883 elemsBeamEuler.clear();
884 /* elems_loads_distributed.clear(); */
886 /* elems_loads.clear(); */
887 for (int i = 0; i < nodesRot.size() - 1; ++i) {
888 auto element = chrono_types::make_shared<ChElementBeamEulermod>();
889 auto load_distributed = chrono_types::make_shared<ChLoadBeamWrenchDistributed>(element);
890 auto load = chrono_types::make_shared<ChLoadBeamWrench>(element);
891 auto gravity = chrono_types::make_shared<ChLoaderGravity>(element);
892 gravity->SetGravitationalAcceleration(system->GetGravitationalAcceleration());
893 std::shared_ptr<ChLoad> loadtri(new ChLoad(gravity));
894 auto load_volumetric = chrono_types::make_shared<ChLoad>(gravity);
895 /* loadcontainer->Add(load_distributed); */
896 /* loadcontainer->Add(load); */
897 // NOTE: loadtri and load_volumetric both wrap the same `gravity`
898 // ChLoaderGravity instance; adding both to the loadcontainer applied
899 // gravity twice. Only load_volumetric is added now; loadtri is left
900 // constructed (and still pushed to elems_loads_triangular below) in
901 // case other code expects a valid object there, but it no longer
902 // contributes force.
903 loadcontainer->Add(load_volumetric);
904 elemsBeamEuler.push_back(element);
905 /* elems_loads_distributed.push_back(load_distributed); */
906 /* elems_loads.push_back(load); */
907 elems_loads_triangular.push_back(loadtri);
908 elems_loads_volumetric.push_back(load_volumetric);
909 element->SetSection(msection_advanced);
910 element->SetRestLength(length/nb_elems);
911 if (i < nb_elems-1) {
912 element->SetNodes(nodesRot[i], nodesRot[i + 1]);
913 }
914 else {
915 if (set_lastnodes == true) {
916 element->SetNodes(nodesRot[i], nodesRot[i + 1]);
917 }
918 }
919 }
920}
921
922void cppCable::buildMesh(bool add_lastnode=true) {
923 if (beam_type == "CableANCF") {
924 buildMeshCableANCF(add_lastnode);
925 }
926 else if (beam_type == "BeamEuler") {
927 buildMeshBeamEuler(add_lastnode);
928 }
929}
930
931void cppCable::buildMeshBeamEuler(bool add_lastnode) {
932 // build the mesh (nodes and elements)
933 auto node = elemsBeamEuler[0]->GetNodeA();
934 mesh->AddNode(node);
935 for (int i = 0; i < elemsBeamEuler.size()-1; ++i) {
936 auto node = elemsBeamEuler[i]->GetNodeB();
937 mesh->AddNode(node);
938 mesh->AddElement(elemsBeamEuler[i]);
939 }
940 if (add_lastnode == true) {
941 auto node = elemsBeamEuler[elemsBeamEuler.size()-1]->GetNodeB();
942 mesh->AddNode(node);
943 }
944 mesh->AddElement(elemsBeamEuler[elemsBeamEuler.size()-1]);
945}
946
947void cppCable::buildMeshCableANCF(bool add_lastnode) {
948 // build the mesh (nodes and elements)
949 auto node = elemsCableANCF[0]->GetNodeA();
950 mesh->AddNode(node);
951 for (int i = 0; i < elemsCableANCF.size()-1; ++i) {
952 auto node = elemsCableANCF[i]->GetNodeB();
953 mesh->AddElement(elemsCableANCF[i]);
954 mesh->AddNode(node);
955 }
956 if (add_lastnode == true) {
957 auto node = elemsCableANCF[elemsCableANCF.size()-1]->GetNodeB();
958 mesh->AddNode(node);
959 }
960 mesh->AddElement(elemsCableANCF[elemsCableANCF.size()-1]);
961}
962void cppCable::setFluidAccelerationAtNodes(std::vector<ChVector3d> acc) {
963 fluid_acceleration = acc;
964}
965
966void cppCable::setFluidVelocityAtNodes(std::vector<ChVector3d> vel) {
968}
969
970void cppCable::setFluidDensityAtNodes(std::vector<double> dens) {
971 fluid_density = dens;
972}
973
974void cppCable::setDragCoefficients(double axial, double normal) {
975 Cd_axial = axial;
976 Cd_normal = normal;
977}
978
979
980void cppCable::setAddedMassCoefficients(double axial, double normal) {
981 Cm_axial = axial;
982 Cm_normal = normal;
983}
984
985void cppCable::setRestLengthPerElement(std::vector<double> length_array) {
986 length_per_elem = length_array;
987}
988
990 /*
991 * setFluidVelocityAtNodes and setFluidDensityAtNodes
992 * must be called before this function
993 */
994 ChVector3d u_ch; // velocity from chrono
995 ChVector3d u_prot; // velocity from proteus
996 ChVector3d u_rel; // relative velocity of node with surrounding fluid
997 ChVector3d t_dir; // tangent at node
998 ChVector3d Fd_a; // axial (tangential) drag force
999 ChVector3d Fd_n; // normal(transversal) drag force
1000 ChVector3d Fd; // total drag force
1001 ChVector3d Va;
1002 ChVector3d Vn;
1003 double rho_f;
1004 // clear current drag forces
1005 double length_elem = length / (nb_nodes - 1);
1006 for (int i = 0; i < nb_nodes; ++i) {
1007 if (beam_type == "CableANCF") {
1008 t_dir = nodes[i]->GetSlope1();
1009 u_ch = nodes[i]->GetPosDt();
1010 }
1011 else if (beam_type == "BeamEuler") {
1012 t_dir = nodesRot[i]->GetRot().GetVector();
1013 u_ch = nodesRot[i]->GetPosDt();
1014 }
1015 // get velocity u_prot from proteus // TO CHANGE !!
1016 double ux_prot = fluid_velocity[i][0];
1017 double uy_prot = fluid_velocity[i][1];
1018 double uz_prot = fluid_velocity[i][2];
1019 u_prot = ChVector3d(ux_prot, uy_prot, uz_prot);
1020 u_rel = u_prot - u_ch;
1021 // CAREFUL HERE: ChBeamElementANCF, GetD() does not give direction but normal
1022 rho_f = fluid_density[i];
1023 double dot = u_rel^t_dir;
1024 Va = t_dir*dot;
1025 Vn = u_rel-Va;
1026 Fd_a = 0.5*rho_f*Cd_axial*M_PI*d*Va.Length()*Va;//(force per unit length)
1027 Fd_n = 0.5*rho_f*Cd_normal*d*Vn.Length()*Vn;//(force per unit length)
1028 Fd = Fd_a + Fd_n;
1029 forces_drag[i]->Set(Fd);
1030 }
1031}
1032
1033
1035 /*
1036 * setFluidVelocityAtNodes and setFluidDensityAtNodes
1037 * must be called before this function
1038 */
1039 ChVector3d a_ch; // acceleration from chrono
1040 ChVector3d a_prot; // acceleration from proteus
1041 ChVector3d a_rel; // relative acceleration of node with surrounding fluid
1042 ChVector3d t_dir; // tangent at node
1043 ChVector3d Fm_a; // axial (tangential) added mass force
1044 ChVector3d Fm_n; // normal(transversal) added mass force
1045 ChVector3d Fm_f; // fluid part added mass force
1046 ChVector3d Fm; // total added mass force
1047 ChVector3d Va;
1048 ChVector3d Vn;
1049 double rho_f;
1050 // clear current drag forces
1051 double length_elem = length / (nb_nodes - 1);
1052 for (int i = 0; i < nb_nodes; ++i) {
1053 if (beam_type == "CableANCF") {
1054 t_dir = nodes[i]->GetSlope1();
1055 a_ch = nodes[i]->GetPosDt2();
1056 }
1057 else if (beam_type == "BeamEuler") {
1058 t_dir = nodesRot[i]->GetRot().GetVector();
1059 a_ch = nodesRot[i]->GetPosDt2();
1060 }
1061 // get velocity u_prot from proteus // TO CHANGE !!
1062 double ax_prot = fluid_acceleration[i][0];
1063 double ay_prot = fluid_acceleration[i][1];
1064 double az_prot = fluid_acceleration[i][2];
1065 a_prot = ChVector3d(ax_prot, ay_prot, az_prot);
1066 a_rel = a_prot - a_ch;
1067 rho_f = fluid_density[i];
1068 double dot = a_rel^t_dir;
1069 Va = t_dir*dot;
1070 Vn = a_rel-Va;
1071 Fm_a = rho_f*Cm_axial*M_PI*d*d/4.*Va;//(force per unit length)
1072 Fm_n = rho_f*Cm_normal*M_PI*d*d/4.*Vn;//(force per unit length)
1073 Fm_f = rho_f*M_PI*d*d/4.*a_prot;
1074 Fm = Fm_a + Fm_n + Fm_f;
1075 forces_addedmass[i]->Set(Fm);
1076 }
1077}
1078
1080 for (int i = 0; i < nb_nodes-1; ++i) {
1081 ChVector3d Fa = ChVector3d(0.,0.,0.);
1082 ChVector3d Fb = ChVector3d(0.,0.,0.);
1083 if (applyDrag == true) {
1084 Fa = Fa+*forces_drag[i].get();
1085 Fb = Fb+*forces_drag[i+1].get();
1086 }
1087 if (applyAddedMass == true) {
1088 Fa = Fa+*forces_addedmass[i].get();
1089 Fb = Fb+*forces_addedmass[i+1].get();
1090 }
1091 /* elems_loads_triangular[i]->loader.SetF(Fa, Fb); */
1092 // buoyancy
1093 if (applyBuoyancy == true) {
1094 if (mesh->GetAutomaticGravity() == true) {
1095 /* elems_loads_volumetric[i]->loader.SetBodyAppliedForce(-fluid_density[i]/rho*system->GetBodyAppliedForce()); */
1096 }
1097 else {
1098 /* elems_loads_volumetric[i]->loader.SetBodyAppliedForce((1-fluid_density[i]/rho)*system->GetBodyAppliedForce()); */
1099 }
1100 }
1101 }
1102};
1103
1104void cppCable::addNodestoContactCloud(std::shared_ptr<ChContactSurfaceNodeCloud> cloud) {
1105 for (int i = 0; i < nb_nodes-1; ++i) {
1106 if (beam_type == "BeamEuler") {
1107 cloud->AddNode(nodesRot[i], d);
1108 }
1109 else if (beam_type == "CableANCF") {
1110 cloud->AddNode(nodes[i], d);
1111 }
1112 }
1113};
1114
1115cppMultiSegmentedCable * newMoorings(std::shared_ptr<ChSystem> system,
1116 std::shared_ptr<ChMesh> mesh,
1117 std::vector<double> length,
1118 std::vector<int> nb_elems,
1119 std::vector<double> d,
1120 std::vector<double> rho,
1121 std::vector<double> E,
1122 std::string beam_type)
1123{
1124 return new cppMultiSegmentedCable(system,
1125 mesh,
1126 length,
1127 nb_elems,
1128 d,
1129 rho,
1130 E,
1131 beam_type);
1132}
1133
1134
1136 int node1,
1137 cppMultiSegmentedCable* cable2,
1138 int node2) {
1139 auto con1 = chrono_types::make_shared<ChLinkNodeNode>();
1140 auto nodeA = cable1->nodes[node1];
1141 auto nodeB = cable2->nodes[node2];
1142 con1->Initialize(nodeA, nodeB);
1143 cable1->system->Add(con1);
1144}
1145
1147 int node1,
1148 cppMultiSegmentedCable* cable2,
1149 int node2) {
1150 auto con1 = chrono_types::make_shared<ChLinkMateSpherical>();
1151 auto nodeA = cable1->nodesRot[node1];
1152 auto nodeB = cable2->nodesRot[node2];
1153 con1->Initialize(nodeA, nodeB, false, nodeA->GetPos(), nodeA->GetPos());
1154 cable1->system->Add(con1);
1155}
Double U
Definition Headers.h:88
Double * z
Definition Headers.h:49
cppMultiSegmentedCable * newMoorings(std::shared_ptr< ChSystem > system, std::shared_ptr< ChMesh > mesh, std::vector< double > length, std::vector< int > nb_elems, std::vector< double > d, std::vector< double > rho, std::vector< double > E, std::string beam_type)
void cppAttachNodeToNodeFEAxyzrot(cppMultiSegmentedCable *cable1, int node1, cppMultiSegmentedCable *cable2, int node2)
ChQuaternion & q_element_ref_rot_of(chrono::fea::ChElementBeamEuler &el)
void cppAttachNodeToNodeFEAxyzD(cppMultiSegmentedCable *cable1, int node1, cppMultiSegmentedCable *cable2, int node2)
void SetF(ChVector3d Fa_in, ChVector3d Fb_in)
virtual int GetIntegrationPointsU()
MyLoaderTriangular(std::shared_ptr< ChLoadableU > mloadable)
virtual void ComputeF(const double U, ChVectorDynamic<> &F, ChVectorDynamic<> *state_x, ChVectorDynamic<> *state_w)
void buildNodesBeamEuler(bool last_node)
std::vector< std::shared_ptr< ChNodeFEAxyzrot > > nodesRot
std::vector< std::shared_ptr< ChLoad > > elems_loads_triangular
void buildMeshBeamEuler(bool add_lastnode)
std::vector< std::shared_ptr< ChElementCableANCF > > elemsCableANCF
std::vector< ChVector3d > mvecs
std::vector< ChVector3d > fluid_velocity
bool applyBuoyancy
void setDragForce()
void buildNodes(bool last_node)
cppCable(std::shared_ptr< ChSystem > system, std::shared_ptr< ChMesh > mesh, double length, int nb_elems, double d, double rho, double E, double L0, std::string beam_type)
std::vector< double > length_per_elem
void buildVectors()
std::vector< std::shared_ptr< ChElementBeamEuler > > elemsBeamEuler
std::vector< std::shared_ptr< ChVector3d > > forces_addedmass
double Cm_normal
double Cd_axial
void setAddedMassForce()
std::shared_ptr< ChMesh > mesh
std::vector< std::shared_ptr< ChElementCableANCF > > elems_cable
std::vector< std::shared_ptr< ChNodeFEAxyzD > > nodes
double Cm_axial
std::vector< std::shared_ptr< ChLoad > > elems_loads_volumetric
std::vector< ChVector3d > mdirs
void setIyy(double Iyy_in)
std::vector< std::shared_ptr< ChVector3d > > forces_drag
void setAddedMassCoefficients(double axial, double normal)
void buildElementsBeamEuler(bool set_lastnodes)
void buildElementsCableANCF(bool set_lastnodes)
void setDragCoefficients(double axial, double normal)
std::vector< ChVector3d > fluid_acceleration
double Cd_normal
void buildMeshCableANCF(bool add_lastnode)
std::vector< double > fluid_density
void addNodestoContactCloud(std::shared_ptr< ChContactSurfaceNodeCloud > cloud)
bool applyAddedMass
std::vector< std::shared_ptr< ChNodeFEAxyzDD > > nodesDD
std::vector< ChVector3d > mvecs_middle
std::vector< double > elems_length
std::shared_ptr< ChBeamSectionAdvanced > msection_advanced
std::shared_ptr< ChSystem > system
void setFluidVelocityAtNodes(std::vector< ChVector3d > vel)
std::vector< double > nodes_density
void setRestLengthPerElement(std::vector< double > length_array)
void setFluidAccelerationAtNodes(std::vector< ChVector3d > acc)
void buildMesh(bool add_lastnode)
std::string beam_type
void setFluidDensityAtNodes(std::vector< double > vof)
std::vector< std::shared_ptr< ChVector3d > > getNodalPositions()
void buildElements(bool set_lastnodes)
void applyForces()
void buildNodesCableANCF(bool last_node)
double length
std::shared_ptr< ChBeamSectionCable > msection_cable
std::vector< ChVector3d > mvecs_tangents
void setFluidAccelerationAtNodes(std::vector< ChVector3d > vel)
std::vector< int > nb_nodes
std::shared_ptr< ChContactMaterialSMC > mysurfmaterial
std::vector< double > rho
void attachFrontNodeToBody(std::shared_ptr< ChBody > body)
cppMultiSegmentedCable(std::shared_ptr< ChSystem > system, std::shared_ptr< ChMesh > mesh, std::vector< double > length, std::vector< int > nb_nodes, std::vector< double > d, std::vector< double > rho, std::vector< double > E, std::string beam_type)
std::vector< std::shared_ptr< ChVector3d > > getNodalPositions()
std::vector< int > nb_elems
std::vector< double > E
std::vector< std::shared_ptr< ChNodeFEAxyzrot > > nodesRot
std::shared_ptr< ChBody > body_front
std::vector< ChVector3d > fluid_acceleration
std::vector< std::shared_ptr< cppCable > > cables
std::shared_ptr< ChBody > fairleadd
std::vector< std::shared_ptr< ChNodeFEAxyzD > > nodes
std::shared_ptr< ChLinkBase > constraint_back
void setFluidVelocityAtNodes(std::vector< ChVector3d > vel)
std::shared_ptr< ChLinkNodeFrame > fairlead2
std::vector< double > d
ChVector3d getTensionElement(int i, double eta)
std::vector< std::shared_ptr< ChElementCableANCF > > elemsCableANCF
void attachBackNodeToBody(std::shared_ptr< ChBody > body)
std::shared_ptr< ChSystem > system
std::vector< std::shared_ptr< ChNodeFEAxyzDD > > nodesDD
std::vector< std::shared_ptr< ChVector3d > > forces_drag
std::shared_ptr< ChBody > body_back
std::vector< double > fluid_density
std::vector< double > length
std::vector< std::shared_ptr< ChVector3d > > forces_addedmass
std::shared_ptr< ChMesh > mesh
void setContactMaterial(std::shared_ptr< ChContactMaterialSMC > material)
std::vector< ChVector3d > mvecs
std::shared_ptr< ChLinkBase > constraint_front
std::vector< ChVector3d > fluid_velocity
void setFluidDensityAtNodes(std::vector< double > dens)
std::shared_ptr< ChContactMaterialSMC > contact_material
std::vector< std::shared_ptr< ChElementBeamEuler > > elemsBeamEuler
void vel(double rS, double norm_v, double r, double theta, double *vR, double *vTHETA)
ChQuaternion<> chrono::fea::ChElementBeamEuler::* type
friend type chronoPrivateMemberThief(ChElementBeamEuler_q_element_ref_rot_tag)
friend Tag::type chronoPrivateMemberThief(Tag)