@@ -666,18 +666,16 @@ Line::setPin(std::vector<real> p)
666666}
667667
668668void
669- Line::setState (std::vector<vec> pos, std::vector<vec> vel)
669+ Line::setState (const std::vector<vec>& pos, const std::vector<vec>& vel)
670670{
671671 if ((pos.size () != N - 1 ) || (vel.size () != N - 1 )) {
672672 LOGERR << " Invalid input size" << endl;
673673 throw moordyn::invalid_value_error (" Invalid input size" );
674674 }
675675
676676 // set interior node positions and velocities based on state vector
677- for (unsigned int i = 1 ; i < N; i++) {
678- r[i] = pos[i - 1 ];
679- rd[i] = vel[i - 1 ];
680- }
677+ std::copy (pos.begin (), pos.end (), r.begin () + 1 );
678+ std::copy (vel.begin (), vel.end (), rd.begin () + 1 );
681679}
682680
683681void
@@ -769,8 +767,8 @@ Line::getEndSegmentMoment(EndPoints end_point, EndPoints rod_end_point) const
769767 return qEnd * EIEnd / dlEnd;
770768}
771769
772- std::pair<std::vector<vec>, std::vector<vec>>
773- Line::getStateDeriv ()
770+ void
771+ Line::getStateDeriv (std::vector<vec>& vel, std::vector<vec>& acc )
774772{
775773 // NOTE:
776774 // Jose Luis Cercos-Pita: This is by far the most consuming function of the
@@ -802,6 +800,22 @@ Line::getStateDeriv()
802800 ldstr[i] = qs[i].dot (rd[i + 1 ] - rd[i]); // strain rate of segment
803801
804802 // V[i] = A * l[i]; // volume attributed to segment
803+
804+ if (nEApoints)
805+ E = getNonlinearE (lstr[i], l[i]);
806+
807+ if (lstr[i] > l[i]) {
808+ T[i] = E * A * (lstr[i] - l[i]) / l[i] * qs[i];
809+ } else {
810+ // cable can't "push" ...
811+ // or can it, if bending stiffness is nonzero? <<<<<<<<<
812+ T[i] = vec::Zero ();
813+ }
814+
815+ // line internal damping force
816+ if (nCpoints)
817+ c = getNonlinearC (ldstr[i], l[i]);
818+ Td[i] = c * A * ldstr[i] / l[i] * qs[i];
805819 }
806820
807821 // calculate unit tangent vectors (q) for each internal node. note: I've
@@ -876,51 +890,9 @@ Line::getStateDeriv()
876890 }
877891 // ============================================================================================
878892
879- // calculate mass matrix
880- for (unsigned int i = 0 ; i <= N; i++) {
881- real m_i; // node mass
882- real v_i; // node submerged volume
883-
884- if (i == 0 ) {
885- m_i = pi / 8 . * d * d * l[0 ] * rho;
886- v_i = 0.5 * F[0 ] * V[0 ];
887- } else if (i == N) {
888- m_i = pi / 8 . * d * d * l[N - 1 ] * rho;
889- v_i = 0.5 * F[i - 1 ] * V[i - 1 ];
890- } else {
891- m_i = pi / 8 . * (d * d * rho * (l[i] + l[i - 1 ]));
892- v_i = 0.5 * (F[i - 1 ] * V[i - 1 ] + F[i] * V[i]);
893- }
894-
895- // Make node mass matrix
896- const mat I = mat::Identity ();
897- const mat Q = q[i] * q[i].transpose ();
898- M[i] = m_i * I + env->rho_w * v_i * (Can * (I - Q) + Cat * Q);
899- }
900-
901893 // ============ CALCULATE FORCES ON EACH NODE
902894 // ===============================
903895
904- // loop through the segments
905- for (unsigned int i = 0 ; i < N; i++) {
906- // line tension
907- if (nEApoints > 0 )
908- E = getNonlinearE (lstr[i], l[i]);
909-
910- if (lstr[i] / l[i] > 1.0 ) {
911- T[i] = E * A * (lstr[i] - l[i]) / l[i] * qs[i];
912- } else {
913- // cable can't "push" ...
914- // or can it, if bending stiffness is nonzero? <<<<<<<<<
915- T[i] = vec::Zero ();
916- }
917-
918- // line internal damping force
919- if (nCpoints > 0 )
920- c = getNonlinearC (ldstr[i], l[i]);
921- Td[i] = c * A * ldstr[i] / l[i] * qs[i];
922- }
923-
924896 // Bending loads
925897 // first zero out the forces from last run
926898 for (unsigned int i = 0 ; i <= N; i++) {
@@ -1092,95 +1064,76 @@ Line::getStateDeriv()
10921064 }
10931065 }
10941066
1067+ // This mostly just simplifies the code, but also sometimes helps the
1068+ // compiler avoid repeated pointer lookup.
1069+ const real rho_w = env->rho_w ;
1070+ const real g = env->g ;
1071+
10951072 // loop through the nodes
10961073 for (unsigned int i = 0 ; i <= N; i++) {
1097- W[i][0 ] = W[i][1 ] = 0.0 ;
1074+ // Nodes are considered to have a line length of half the length of the
1075+ // line on either side.
1076+ const real length_left = i == 0 ? 0.0 : l[i - 1 ];
1077+ const real length_right = i == N ? 0.0 : l[i];
1078+ const real length = 0.5 * (length_left + length_right);
1079+ const real submergence_left = i == 0 ? 0.0 : F[i - 1 ];
1080+ const real submergence_right = i == N ? 0.0 : F[i];
1081+ // Submerged length is half the submerged length of the neighboring
1082+ // segments
1083+ const real submerged_length = 0.5 * (length_left * submergence_left +
1084+ length_right * submergence_right);
1085+
1086+ const real submerged_volume = submerged_length * A;
1087+
1088+ const real m_i = A * length * rho; // node mass
1089+ const real v_i = submerged_volume; // node submerged volume
1090+
1091+ // Make node mass matrix
1092+ const mat I = mat::Identity ();
1093+ const mat Q = q[i] * q[i].transpose ();
1094+ // calculate mass matrix
1095+ M[i] = m_i * I + rho_w * v_i * (Can * (I - Q) + Cat * Q);
1096+
10981097 // submerged weight (including buoyancy)
1099- if (i == 0 )
1100- W[i][2 ] = 0.5 * A * (l[i] * (rho - F[i] * env->rho_w )) * (-env->g );
1101- else if (i == N)
1102- W[i][2 ] = 0.5 * A * (l[i - 1 ] * (rho - F[i - 1 ] * env->rho_w )) *
1103- (-env->g ); // missing the "W[i][2] =" previously!
1104- else
1105- W[i][2 ] = 0.5 * A *
1106- (l[i] * (rho - F[i] * env->rho_w ) +
1107- l[i - 1 ] * (rho - F[i - 1 ] * env->rho_w )) *
1108- (-env->g );
1098+ W[i][0 ] = W[i][1 ] = 0.0 ;
1099+ W[i][2 ] = -g * (m_i - v_i * rho_w);
11091100
11101101 // relative flow velocity over node
11111102 const vec vi = U[i] - rd[i];
11121103 // tangential relative flow component
11131104 // <<<<<<< check sign since I've reversed q
1114- const moordyn:: real vql = vi.dot (q[i]);
1105+ const real vql = vi.dot (q[i]);
11151106 const vec vq = vql * q[i];
11161107 // transverse relative flow component
11171108 const vec vp = vi - vq;
11181109
1119- const moordyn:: real vq_mag = vq.norm ();
1120- const moordyn:: real vp_mag = vp.norm ();
1110+ const real vq_mag = vq.norm ();
1111+ const real vp_mag = vp.norm ();
11211112
1113+ const real shared_part = 0.5 * rho_w * d * submerged_length;
11221114 // transverse drag
1123- if (i == 0 )
1124- Dp[i] = 0.25 * vp_mag * env->rho_w * Cdn * d * (F[i] * l[i]) * vp;
1125- else if (i == N)
1126- Dp[i] = 0.25 * vp_mag * env->rho_w * Cdn * d *
1127- (F[i - 1 ] * l[i - 1 ]) * vp;
1128- else
1129- Dp[i] = 0.25 * vp_mag * env->rho_w * Cdn * d *
1130- (F[i] * l[i] + F[i - 1 ] * l[i - 1 ]) * vp;
1131-
1115+ Dp[i] = vp_mag * Cdn * shared_part * vp;
11321116 // tangential drag
1133- if (i == 0 )
1134- Dq[i] =
1135- 0.25 * vq_mag * env->rho_w * Cdt * pi * d * (F[i] * l[i]) * vq;
1136- else if (i == N)
1137- Dq[i] = 0.25 * vq_mag * env->rho_w * Cdt * pi * d *
1138- (F[i - 1 ] * l[i - 1 ]) * vq;
1139- else
1140- Dq[i] = 0.25 * vq_mag * env->rho_w * Cdt * pi * d *
1141- (F[i] * l[i] + F[i - 1 ] * l[i - 1 ]) * vq;
1117+ Dq[i] = vq_mag * Cdt * pi * shared_part * vq;
11421118
1143- // tangential component of fluid acceleration
11441119 // <<<<<<< check sign since I've reversed q
1145- const moordyn:: real aql = Ud[i].dot (q[i]);
1120+ const real aql = Ud[i].dot (q[i]);
11461121 const vec aq = aql * q[i];
11471122 // normal component of fluid acceleration
11481123 const vec ap = Ud[i] - aq;
11491124
11501125 // transverse Froude-Krylov force
1151- if (i == 0 )
1152- Ap[i] = env->rho_w * (1 . + Can) * 0.5 * (F[i] * V[i]) * ap;
1153- else if (i == N)
1154- Ap[i] = env->rho_w * (1 . + Can) * 0.5 * (F[i - 1 ] * V[i - 1 ]) * ap;
1155- else
1156- Ap[i] = env->rho_w * (1 . + Can) * 0.5 *
1157- (F[i] * V[i] + F[i - 1 ] * V[i - 1 ]) * ap;
1126+ Ap[i] = rho_w * (1 . + Can) * submerged_volume * ap;
11581127 // tangential Froude-Krylov force
1159- if (i == 0 )
1160- Aq[i] = env->rho_w * (1 . + Cat) * 0.5 * (F[i] * V[i]) * aq;
1161- else if (i == N)
1162- Aq[i] = env->rho_w * (1 . + Cat) * 0.5 * (F[i - 1 ] * V[i - 1 ]) * aq;
1163- else
1164- Aq[i] = env->rho_w * (1 . + Cat) * 0.5 *
1165- (F[i] * V[i] + F[i - 1 ] * V[i - 1 ]) * aq;
1128+ Aq[i] = rho_w * (1 . + Cat) * submerged_volume * aq;
11661129
11671130 // bottom contact (stiffness and damping, vertical-only for now) -
11681131 // updated for general case of potentially anchor or fairlead end in
11691132 // contact
11701133 const real waterDepth = getWaterDepth (r[i][0 ], r[i][1 ]);
11711134 if (r[i][2 ] < waterDepth) {
1172- if (i == 0 )
1173- B[i][2 ] =
1174- ((waterDepth - r[i][2 ]) * env->kb - rd[i][2 ] * env->cb ) *
1175- 0.5 * d * (l[i]);
1176- else if (i == N)
1177- B[i][2 ] =
1178- ((waterDepth - r[i][2 ]) * env->kb - rd[i][2 ] * env->cb ) *
1179- 0.5 * d * (l[i - 1 ]);
1180- else
1181- B[i][2 ] =
1182- ((waterDepth - r[i][2 ]) * env->kb - rd[i][2 ] * env->cb ) *
1183- 0.5 * d * (l[i - 1 ] + l[i]);
1135+ B[i][2 ] = ((waterDepth - r[i][2 ]) * env->kb - rd[i][2 ] * env->cb ) *
1136+ d * (length);
11841137
11851138 // new rough-draft addition of seabed friction
11861139 real FrictionMax =
@@ -1223,44 +1176,16 @@ Line::getStateDeriv()
12231176 Bs[i] + Pb[i];
12241177 }
12251178
1226- // if (t > 5)
1227- // {
1228- // cout << " in getStateDeriv of line " << number << endl;
1229- //
1230- // B[0][0] = 0.001; // meaningless
1231- // }
1232-
12331179 // loop through internal nodes and compute the accelerations
1234- std::vector<vec> u, a;
1235- u.reserve (N - 1 );
1236- a.reserve (N - 1 );
1180+ vel.reserve (N - 1 );
1181+ acc.reserve (N - 1 );
12371182 for (unsigned int i = 1 ; i < N; i++) {
1238- // double M_out[9];
1239- // double F_out[3];
1240- // for (int I=0; I<3; I++)
1241- // { F_out[I] = Fnet[i][I];
1242- // for (int J=0; J<3; J++) M_out[3*I + J] = M[i][I][J];
1243- // }
1244-
1245- // solve for accelerations in [M]{a}={f} using LU decomposition
1246- // double LU[9]; // serialized matrix that will
1247- // hold LU matrices combined Crout(3, M_out, LU); //
1248- // perform LU decomposition on mass matrix double acc[3]; //
1249- // acceleration vector to solve for solveCrout(3, LU, F_out, acc);
1250- // // solve for acceleration vector
1251-
1252- // LUsolve3(M[i], acc, Fnet[i]);
1253-
1254- // Solve3(M[i], acc, (const double*)Fnet[i]);
1255-
12561183 // For small systems it is usually faster to compute the inverse
12571184 // of the matrix. See
12581185 // https://eigen.tuxfamily.org/dox/group__TutorialLinearAlgebra.html
1259- a. push_back ( M[i].inverse () * Fnet[i]) ;
1260- u. push_back ( rd[i]) ;
1186+ acc[i - 1 ] = M[i].inverse () * Fnet[i];
1187+ vel[i - 1 ] = rd[i];
12611188 }
1262-
1263- return make_pair (u, a);
12641189};
12651190
12661191// write output file for line (accepts time parameter since retained time value
0 commit comments