Skip to content

Commit eb9bdfd

Browse files
committed
fix/feat: Fixed viscoelastic bug by initalizing sub-segment stretch as non-zero, added viscoelastic test based on polyester test
1 parent 053cfad commit eb9bdfd

File tree

3 files changed

+112
-23
lines changed

3 files changed

+112
-23
lines changed

source/Line.cpp

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,6 @@ Line::setup(int number_in,
247247
phi_dot.assign(N + 1, 0.0); // synch model frequency
248248
yd_rms_old.assign(N + 1, 0.0); // node old yd_rms
249249
ydd_rms_old.assign(N + 1, 0.0); // node old ydd_rms
250-
251-
// give a random distribution between 0 and 2pi for inital phase of lift force to avoid initial transient
252-
for (unsigned int i = 1; i < N; i++) phi[i] = (i/moordyn::real(N))*2*pi; // internal nodes only. Change if end node viv included
253250
}
254251

255252
// ensure end moments start at zero
@@ -580,6 +577,20 @@ Line::initialize()
580577
LOGDBG << "Vertical linear initial profile for Line " << number << endl;
581578
}
582579

580+
// If using the viscoelastic model, initalize the deltaL_1 to the delta L of the segment.
581+
// This is required here to initalize the state as non-zero, which avoids an initial
582+
// transient where the segment goes from unstretched to stretched in one time step.
583+
if (ElasticMod > 1) {
584+
for (unsigned int i = 0; i < N; i++) {
585+
lstr[i] = unitvector(qs[i], r[i], r[i + 1]);
586+
dl_1[i] = lstr[i] - l[i]; // delta l of the segment
587+
}
588+
}
589+
590+
// If using the VIV model, initalize as a distribution between 0 and 2pi for inital phase of lift force to avoid initial transient
591+
if (Cl > 0)
592+
for (unsigned int i = 1; i < N; i++) phi[i] = (i/moordyn::real(N))*2*pi; // internal nodes only. Change if end node viv included
593+
583594
LOGMSG << "Initialized Line " << number << endl;
584595

585596
// NOTE: becasue Line.hpp is the only user of this function, no need to return any state information
@@ -755,8 +766,10 @@ Line::setState(const InstanceStateVarView state)
755766
for (unsigned int i = 0; i < (ElasticMod > 1 ? N : N-1); i++) {
756767
// node number is i+1
757768
// segment number is i
758-
r[i+1] = state.row(i).head<3>();
759-
rd[i+1] = state.row(i).segment<3>(3);
769+
if (i < N-1) { // only assign the internal nodes
770+
r[i+1] = state.row(i).head<3>();
771+
rd[i+1] = state.row(i).segment<3>(3);
772+
}
760773

761774
if (ElasticMod > 1) dl_1[i] = state.row(i).tail<1>()[0]; // [0] needed becasue tail<1> returns a one element vector. Viscoelastic state is always the last element in the row
762775

@@ -771,6 +784,12 @@ Line::setState(const InstanceStateVarView state)
771784
void
772785
Line::setEndKinematics(vec pos, vec vel, EndPoints end_point)
773786
{
787+
if (t < 5 && int(t / dtm0) % 20 == 0) {
788+
LOGDBG << "------" << endl;
789+
LOGDBG << "Setting end kinematics for end point " << end_point << endl;
790+
LOGDBG << "Position: " << pos.transpose() << ", Velocity: " << vel.transpose() << endl;
791+
}
792+
774793
switch (end_point) {
775794
case ENDPOINT_TOP:
776795
endTypeB = PINNED; // indicate pinned
@@ -925,7 +944,8 @@ Line::getStateDeriv(InstanceStateVarView drdt)
925944
for (unsigned int i = 0; i < N; i++) {
926945
// calculate current (Stretched) segment lengths and unit tangent
927946
// vectors (qs) for each segment (this is used for bending and stiffness calculations)
928-
lstr[i] = unitvector(qs[i], r[i], r[i + 1]);
947+
948+
lstr[i] = unitvector(qs[i], r[i], r[i + 1]); // if using the viscoelastic model this is redundant for the first time step, as it is also called by Line::initalize
929949

930950
ldstr[i] = qs[i].dot(rd[i + 1] - rd[i]); // strain rate of segment
931951

tests/Mooring/polyester/visco.txt

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ vbeta = KRD2 * MBL = 0.35 * 25.3e6 = 8.855e6
1111
----------------------- LINE TYPES ------------------------------------------
1212
TypeName Diam Mass/m EA BA/-zeta EI Cd Ca CdAx CaAx
1313
(name) (m) (kg/m) (N) (N-s/-) (N-m^2) (-) (-) (-) (-)
14-
Polyester_290mm 0.217 52.0 3.39e8|4.048e8|8.855e6 -1.0|1e11 0.0 1.6 1.79 0.008 0.0
14+
Polyester_290mm 0.217 52.0 3.39e8|4.048e8|8.855e6 -1|1e10 0.0 1.6 1.79 0.008 0.0
1515
---------------------- POINT PROPERTIES --------------------------------
1616
ID Type X Y Z Mass Volume CdA Ca
1717
(#) (-) (m) (m) (m) (kg) (mˆ3) (m^2) (-)
@@ -20,23 +20,19 @@ ID Type X Y Z Mass Volume CdA Ca
2020
---------------------- LINES ----------------------------------------
2121
ID LineType AttachA AttachB UnstrLen NumSegs LineOutputs
2222
(#) (name) (#) (#) (m) (-) (-)
23-
1 Polyester_290mm 1 2 1400.0 70 p
23+
1 Polyester_290mm 1 2 1400.0 70 -
2424
---------------------- OPTIONS -----------------------------------------
2525
2 writeLog Write a log file
26-
0.0005 dtM time step to use in mooring integration (s)
26+
0.00005 dtM time step to use in mooring integration (s)
2727
1.0e5 kBot bottom stiffness (Pa/m)
2828
1.0e4 cBot bottom damping (Pa-s/m)
2929
9.80665 g gravitational constant (m/s^2)
3030
1025.0 WtrDnsty water density (kg/m^3)
3131
372.3 WtrDpth water depth (m)
3232
4.0 CdScaleIC factor by which to scale drag coefficients during dynamic relaxation (-)
33-
1 ICgenDynamic
3433
0.5 FrictionCoefficient general bottom friction coefficient, as a start (-)
35-
5.0 dtIC time interval for analyzing convergence during IC gen (s)
36-
00 TmaxIC max time for ic gen (s)
37-
0.0000001 threshIC threshold for IC convergence (-)
38-
0.001 dtOut
39-
------------------------- Outputs -------------------------
40-
Fairten1
41-
POINT1PX
34+
0.1 dtIC time interval for analyzing convergence during IC gen (s)
35+
100 TmaxIC max time for ic gen (s)
36+
0.01 threshIC threshold for IC convergence (-)
37+
0.01 dtOut
4238
------------------------- need this line --------------------------------------

tests/polyester.cpp

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,85 @@ TEST_CASE("Ramp up, stabilization and cycles")
170170
}
171171

172172

173-
// TEST_CASE("Visco-elastic testing")
174-
// {
175-
// // TODO: static dynamic stiffness
173+
TEST_CASE("Visco-elastic testing")
174+
{
175+
// this is the same as the above test, but the static and dynamic stiffness coefficients have been added to MD instead of calculated externally.
176+
MoorDyn system = MoorDyn_Create("Mooring/polyester/visco.txt");
177+
REQUIRE(system);
178+
unsigned int n_dof;
179+
REQUIRE(MoorDyn_NCoupledDOF(system, &n_dof) == MOORDYN_SUCCESS);
180+
REQUIRE(n_dof == 3);
181+
182+
double r[3], dr[3];
183+
auto anchor = MoorDyn_GetPoint(system, 1);
184+
REQUIRE(anchor);
185+
auto fairlead = MoorDyn_GetPoint(system, 2);
186+
REQUIRE(fairlead);
187+
auto line = MoorDyn_GetLine(system, 1);
188+
REQUIRE(line);
189+
190+
double l0;
191+
REQUIRE(MoorDyn_GetLineUnstretchedLength(line, &l0) == MOORDYN_SUCCESS);
192+
193+
REQUIRE(MoorDyn_GetPointPos(fairlead, r) == MOORDYN_SUCCESS);
194+
std::fill(dr, dr + 3, 0.0);
195+
REQUIRE(MoorDyn_Init(system, r, dr) == MOORDYN_SUCCESS);
176196

177-
// // TODO: load dependent dynamic stiffness
197+
// Read the csv with the motions
198+
std::ifstream csv("Mooring/polyester/motion.csv");
199+
aria::csv::CsvParser csv_parser(csv);
178200

179-
// REQUIRE(MoorDyn_Close(system) == MOORDYN_SUCCESS);
180-
// }
201+
std::vector<double> tdata, xdata;
202+
unsigned int skip = 2;
203+
for (auto& row : csv_parser) {
204+
if (skip > 0) {
205+
skip--;
206+
continue;
207+
}
208+
if (row.size() < 2)
209+
continue;
210+
tdata.push_back(std::stod(row.at(0)));
211+
xdata.push_back(std::stod(row.at(1)));
212+
}
213+
214+
// Time to move
215+
double t = 0.0, dt;
216+
// For checking the performance
217+
std::deque<double> times;
218+
std::deque<double> tensions;
219+
std::deque<double> ttimes(TTIMES);
220+
std::deque<double> tmeans(TMEANS); // tension means
221+
for (unsigned int i = 0; i < tdata.size(); i++) {
222+
REQUIRE(MoorDyn_GetPointPos(fairlead, r) == MOORDYN_SUCCESS);
223+
double t_dst = tdata.at(i);
224+
double dt = t_dst - t;
225+
double x_dst = xdata.at(i);
226+
dr[0] = (x_dst - r[0]) / dt;
227+
double f[3];
228+
REQUIRE(MoorDyn_Step(system, r, dr, f, &t, &dt) == MOORDYN_SUCCESS);
229+
times.push_back(t);
230+
tensions.push_back(get_average_tension(line, anchor, fairlead));
231+
232+
// Let's check and tweak the line if there is info enough
233+
if (times.back() - times.front() < TC)
234+
continue;
235+
236+
double tension = 0.0;
237+
for (auto f : tensions)
238+
tension += f;
239+
tension /= tensions.size();
240+
times.pop_front();
241+
tensions.pop_front();
242+
243+
if (t >= ttimes.front()) {
244+
const double tmean = tmeans.front();
245+
ttimes.pop_front();
246+
tmeans.pop_front();
247+
REQUIRE(
248+
fabs(tension / MBL - tmean) < 0.025);
249+
}
250+
}
251+
252+
REQUIRE(MoorDyn_Close(system) == MOORDYN_SUCCESS);
253+
}
181254

0 commit comments

Comments
 (0)