Skip to content

Commit 269cc73

Browse files
feat(core)!: Line breaking utilities
1 parent 26bad3b commit 269cc73

13 files changed

Lines changed: 375 additions & 6 deletions

File tree

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
cmake_minimum_required(VERSION 3.10)
22
set(MOORDYN_MAJOR_VERSION 2)
3-
set(MOORDYN_MINOR_VERSION 6)
4-
set(MOORDYN_PATCH_VERSION 2)
3+
set(MOORDYN_MINOR_VERSION 7)
4+
set(MOORDYN_PATCH_VERSION 0)
55
set(MOORDYN_VERSION ${MOORDYN_MAJOR_VERSION}.${MOORDYN_MINOR_VERSION})
66
project(Moordyn VERSION ${MOORDYN_VERSION})
77

source/MoorDyn2.cpp

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,38 @@ moordyn::MoorDyn::Step(const double* x,
795795
return MOORDYN_SUCCESS;
796796
}
797797

798+
void
799+
MoorDyn::BreakLine(moordyn::Point* point, moordyn::Line* line)
800+
{
801+
// Detach the line from the point
802+
moordyn::EndPoints end_point;
803+
auto pt_attachments = point->getLines();
804+
for (auto attachment : pt_attachments) {
805+
if (attachment.line == line) {
806+
end_point = attachment.end_point;
807+
}
808+
}
809+
point->removeLine(line);
810+
// Create the new point
811+
moordyn::Point *pt = new Point(point, PointList.size());
812+
PointList.push_back(pt);
813+
waves->addPoint(pt);
814+
_t_integrator->AddPoint(pt);
815+
// Set the state of the point
816+
auto state = _t_integrator->r(0);
817+
pt->initialize(state->get(pt));
818+
for (unsigned int i = 0; i < _t_integrator->GetNDeriv(); i++) {
819+
_t_integrator->rd(i)->get(pt).row(0)(Eigen::seqN(0, 3)) =
820+
state->get(pt).row(0)(Eigen::seqN(3, 3));
821+
// NOTE: Although when cloning free points we can actually get the
822+
// acceleration, I (Jose Luis Cercos-Pita) do not think is worthy, so
823+
// I am simply setting no acceleration
824+
_t_integrator->rd(i)->get(pt).row(0)(Eigen::seqN(3, 3)) = vec::Zero();
825+
}
826+
// Attach the line to the point
827+
pt->addLine(line, end_point);
828+
}
829+
798830
std::vector<uint64_t>
799831
MoorDyn::Serialize(void)
800832
{
@@ -1155,8 +1187,7 @@ moordyn::MoorDyn::ReadInFile()
11551187
env->WtrDpth = -r0[2];
11561188
LOGWRN << "\t Water depth set to point " << PointList.size() + 1
11571189
<< " z position because point was specified below the "
1158-
"seabed"
1159-
<< endl;
1190+
"seabed" << endl;
11601191
}
11611192

11621193
// Check point ID is sequential starting from 1
@@ -2896,6 +2927,28 @@ MoorDyn_GetFASTtens(MoorDyn system,
28962927
return MOORDYN_SUCCESS;
28972928
}
28982929

2930+
int DECLDIR
2931+
MoorDyn_BreakLine(MoorDyn system,
2932+
MoorDynPoint point,
2933+
MoorDynLine line)
2934+
{
2935+
CHECK_SYSTEM(system);
2936+
2937+
moordyn::error_id err = MOORDYN_SUCCESS;
2938+
string err_msg;
2939+
try {
2940+
((moordyn::MoorDyn*)system)->BreakLine((moordyn::Point*)point,
2941+
(moordyn::Line*)line);
2942+
}
2943+
MOORDYN_CATCHER(err, err_msg);
2944+
if (err != MOORDYN_SUCCESS) {
2945+
cerr << "Error (" << err << ") at " << __FUNC_NAME__ << "():" << endl
2946+
<< err_msg << endl;
2947+
return err;
2948+
}
2949+
return MOORDYN_SUCCESS;
2950+
}
2951+
28992952
int DECLDIR
29002953
MoorDyn_GetDt(MoorDyn system, double* dt)
29012954
{

source/MoorDyn2.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,21 @@ MoorDyn_GetFASTtens(MoorDyn system,
435435
float AnchHTen[],
436436
float AnchVTen[]);
437437

438+
/** @brief Break a line on a specific point
439+
*
440+
* This method is dettaching a line from the point, and in exchange is
441+
* creating a point duplicate of type moordyn::Point::types::FREE
442+
* @param system The Moordyn system
443+
* @param point The discconection point
444+
* @param line The line that is dettaching from the point
445+
* @throw MOORDYN_SUCESS If the line is correctly dettached, an error code
446+
* otherwise (see @ref moordyn_errors)
447+
*/
448+
int DECLDIR
449+
MoorDyn_BreakLine(MoorDyn system,
450+
MoorDynPoint point,
451+
MoorDynLine line);
452+
438453
/** @brief Get the current model time step
439454
* @param system The Moordyn system
440455
* @param dt The output time step

source/MoorDyn2.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,17 @@ class MoorDyn final : public io::IO
268268
waves->setWaveKinematics(U, Ud);
269269
}
270270

271+
/** @brief Break a line on a specific point
272+
*
273+
* This method is dettaching a line from the point, and in exchange is
274+
* creating a point duplicate of type moordyn::Point::types::FREE
275+
* @param point The discconection point
276+
* @param line The line that is dettaching from the point
277+
* @throw moordyn::invalid_value_error If the line is not attached to the
278+
* point.
279+
*/
280+
void BreakLine(moordyn::Point* point, moordyn::Line* line);
281+
271282
/** @brief Produce the packed data to be saved
272283
*
273284
* The produced data can be used afterwards to restore the saved information

source/Point.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,35 @@ namespace moordyn {
3838

3939
Point::Point(moordyn::Log* log, size_t id)
4040
: Instance(log)
41+
, waves(nullptr)
4142
, seafloor(nullptr)
4243
, pointId(id)
4344
{
4445
vtk.set_binary();
4546
}
4647

48+
Point::Point(Point* visitor, size_t id)
49+
: Instance(visitor->GetLogger())
50+
, env(visitor->env)
51+
, waves(visitor->waves)
52+
, seafloor(visitor->seafloor)
53+
, pointM(visitor->pointM)
54+
, pointV(visitor->pointV)
55+
, pointF(visitor->pointF)
56+
, pointCdA(visitor->pointCdA)
57+
, r(visitor->r)
58+
, rd(visitor->rd)
59+
, Fnet(visitor->rd)
60+
, t(visitor->t)
61+
, M(visitor->M)
62+
, acc(visitor->acc)
63+
, pointId(id)
64+
, number(id + 1)
65+
, type(types::FREE)
66+
{
67+
vtk.set_binary();
68+
}
69+
4770
Point::~Point() {}
4871

4972
void
@@ -150,7 +173,9 @@ Point::initialize()
150173
seafloor ? seafloor->getDepthAt(r[0], r[1]) : -env->WtrDpth;
151174
if (waterDepth > r[2]) {
152175
LOGERR << "Error: water depth is shallower than Point " << number
153-
<< "." << endl;
176+
<< "." << endl
177+
<< "\tseabed z = " << waterDepth << endl
178+
<< "\tpoint = " << r << endl;
154179
throw moordyn::invalid_value_error("Invalid water depth");
155180
}
156181
}

source/Point.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,15 @@ class DECLDIR Point final
7474
*/
7575
Point(moordyn::Log* log, size_t id);
7676

77+
/** @brief Point duplicator
78+
*
79+
* The duplicated point will have the same dynamics of the original point.
80+
* It will be a ::types::FREE kind of point though
81+
* @param visitor Point to duplicate
82+
* @param id Unique identifier of this instance
83+
*/
84+
Point(Point* visitor, size_t id);
85+
7786
/** @brief Destructor
7887
*/
7988
~Point();

source/Time.hpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,26 @@ class Scheme : public io::IO
256256
*/
257257
virtual void Step(real& dt) { t_local += dt; };
258258

259+
/** @brief Get the number of state variables
260+
* @return The number of state variables
261+
*/
262+
virtual const unsigned int GetNState() const = 0;
263+
264+
/** @brief Get the number of state derivative variables
265+
* @return The number of state derivative variables
266+
*/
267+
virtual const unsigned int GetNDeriv() const = 0;
268+
259269
/** @brief Get the state variable
260270
* @param i The index of the state variable to take
261271
* @return The state variable
272+
* @{
262273
*/
263274
virtual moordyn::state::State GetState(unsigned int i = 0) = 0;
275+
virtual moordyn::state::State* r(unsigned int i = 0) = 0;
276+
/**
277+
* @}
278+
*/
264279

265280
/** @brief Resume the simulation from the stationary solution
266281
* @param state The stationary solution
@@ -288,6 +303,17 @@ class Scheme : public io::IO
288303
{
289304
}
290305

306+
/** @brief Get the state derivative variable
307+
* @param i The index of the state derivative variable to take
308+
* @return The state derivative variable
309+
* @{
310+
*/
311+
virtual moordyn::state::State GetDeriv(unsigned int i = 0) = 0;
312+
virtual moordyn::state::State* rd(unsigned int i = 0) = 0;
313+
/**
314+
* @}
315+
*/
316+
291317
protected:
292318
/** @brief Constructor
293319
* @param log Logging handler
@@ -623,6 +649,16 @@ class SchemeBase : public Scheme
623649
*/
624650
virtual void Step(real& dt) { Scheme::Step(dt); };
625651

652+
/** @brief Get the number of state variables
653+
* @return The number of state variables
654+
*/
655+
inline const unsigned int GetNState() const { return NSTATE; }
656+
657+
/** @brief Get the number of state derivative variables
658+
* @return The number of state derivative variables
659+
*/
660+
inline const unsigned int GetNDeriv() const { return NDERIV; }
661+
626662
/** @brief Get the state
627663
* @param i The index of the state variable to take
628664
* @return The state variable
@@ -720,6 +756,7 @@ class SchemeBase : public Scheme
720756
* @return The state derivative
721757
* @throws moordyn::invalid_value_error if the @p i index is greater or
722758
* equal than the number of state derivatives
759+
* @{
723760
*/
724761
inline state::State* rd(unsigned int i = 0)
725762
{
@@ -732,6 +769,11 @@ class SchemeBase : public Scheme
732769
return _rd[i];
733770
}
734771

772+
inline state::State GetDeriv(unsigned int i = 0) { return *rd(i); }
773+
/**
774+
* @}
775+
*/
776+
735777
/** @brief Produce the packed data to be saved
736778
*
737779
* The produced data can be used afterwards to restore the saved information

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ set(CATCH2_TESTS
5555
midpoint
5656
aca
5757
wilson
58+
line_break
5859
)
5960

6061
function(make_executable test_name, extension)

tests/line_break.cpp

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright (c) 2022 Jose Luis Cercos-Pita <jlc@core-marine.com>
3+
*
4+
* Redistribution and use in source and binary forms, with or without
5+
* modification, are permitted provided that the following conditions are met:
6+
*
7+
* 1. Redistributions of source code must retain the above copyright notice,
8+
* this list of conditions and the following disclaimer.
9+
*
10+
* 2. Redistributions in binary form must reproduce the above copyright notice,
11+
* this list of conditions and the following disclaimer in the documentation
12+
* and/or other materials provided with the distribution.
13+
*
14+
* 3. Neither the name of the copyright holder nor the names of its
15+
* contributors may be used to endorse or promote products derived from
16+
* this software without specific prior written permission.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
* POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
31+
/** @file minimal.cpp
32+
* Minimal tests that only checks the library is correctly initialized,
33+
* running and closing
34+
*/
35+
36+
#include "MoorDyn2.h"
37+
#include <algorithm>
38+
#include <cmath>
39+
#include <catch2/catch_test_macros.hpp>
40+
41+
// #define SAVE_VTK
42+
43+
using namespace std;
44+
45+
TEST_CASE("Breaker")
46+
{
47+
MoorDyn system = MoorDyn_Create("Mooring/lines.txt");
48+
REQUIRE(system);
49+
50+
unsigned int n_dof;
51+
REQUIRE(MoorDyn_NCoupledDOF(system, &n_dof) == MOORDYN_SUCCESS);
52+
REQUIRE(n_dof == 9);
53+
54+
int err;
55+
double x[9], dx[9];
56+
// Get the initial positions from the config file
57+
for (unsigned int i = 0; i < 3; i++) {
58+
// 4 = first fairlead id
59+
auto point = MoorDyn_GetPoint(system, i + 4);
60+
REQUIRE(point);
61+
REQUIRE(MoorDyn_GetPointPos(point, x + 3 * i) == MOORDYN_SUCCESS);
62+
}
63+
64+
auto point = MoorDyn_GetPoint(system, 4);
65+
REQUIRE(point);
66+
auto line = MoorDyn_GetLine(system, 1);
67+
REQUIRE(line);
68+
69+
std::fill(dx, dx + 9, 0.0);
70+
REQUIRE(MoorDyn_Init(system, x, dx) == MOORDYN_SUCCESS);
71+
#ifdef SAVE_VTK
72+
REQUIRE(MoorDyn_SaveVTK(system, "line_break.000.vtm") == MOORDYN_SUCCESS);
73+
#endif
74+
// Let's move the system at a 10.0m/s speed during 0.5 seconds
75+
double f[9];
76+
dx[0] = 10.0;
77+
double t = 0.0, dt = 0.5;
78+
REQUIRE(MoorDyn_Step(system, x, dx, f, &t, &dt) == MOORDYN_SUCCESS);
79+
#ifdef SAVE_VTK
80+
REQUIRE(MoorDyn_SaveVTK(system, "line_break.001.vtm") == MOORDYN_SUCCESS);
81+
#endif
82+
x[0] += dx[0] * dt;
83+
84+
// Break a line and repeat 3 times
85+
REQUIRE(MoorDyn_BreakLine(system, point, line) == MOORDYN_SUCCESS);
86+
REQUIRE(MoorDyn_Step(system, x, dx, f, &t, &dt) == MOORDYN_SUCCESS);
87+
#ifdef SAVE_VTK
88+
REQUIRE(MoorDyn_SaveVTK(system, "line_break.002.vtm") == MOORDYN_SUCCESS);
89+
#endif
90+
x[0] += dx[0] * dt;
91+
REQUIRE(MoorDyn_Step(system, x, dx, f, &t, &dt) == MOORDYN_SUCCESS);
92+
#ifdef SAVE_VTK
93+
REQUIRE(MoorDyn_SaveVTK(system, "line_break.003.vtm") == MOORDYN_SUCCESS);
94+
#endif
95+
x[0] += dx[0] * dt;
96+
REQUIRE(MoorDyn_Step(system, x, dx, f, &t, &dt) == MOORDYN_SUCCESS);
97+
#ifdef SAVE_VTK
98+
REQUIRE(MoorDyn_SaveVTK(system, "line_break.004.vtm") == MOORDYN_SUCCESS);
99+
#endif
100+
x[0] += dx[0] * dt;
101+
102+
REQUIRE(MoorDyn_Close(system) == MOORDYN_SUCCESS);
103+
}

0 commit comments

Comments
 (0)