From ebb5f92d15c99dd8f9de7596da9cdef81f60f90d Mon Sep 17 00:00:00 2001 From: kylerf229 Date: Mon, 4 Aug 2025 14:58:48 -0600 Subject: [PATCH 1/5] =?UTF-8?q?Changes=20made:=20Setting=20submergence=20c?= =?UTF-8?q?hange=20to=20openfast=20logic.=20Added=20more=20outputs=20for?= =?UTF-8?q?=20rods=20in=20the=20input=20file=20for=20additional=20analysis?= =?UTF-8?q?=20of=20data=20(Dp,=20Ap,=20=E2=80=A6).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/Misc.hpp | 24 +++++- source/MoorDyn2.cpp | 27 +++++-- source/Rod.cpp | 184 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 223 insertions(+), 12 deletions(-) diff --git a/source/Misc.hpp b/source/Misc.hpp index b8178363..0f669be8 100644 --- a/source/Misc.hpp +++ b/source/Misc.hpp @@ -1240,7 +1240,29 @@ enum QTypeEnum : int MZ = 25, Sub = 26, TenA = 27, - TenB = 28 + TenB = 28, + WZ = 31, + DpX = 32, + DpY = 33, + DpZ = 34, + DqX = 35, + DqY = 36, + DqZ = 37, + ApX = 38, + ApY = 39, + ApZ = 40, + AqX = 41, + AqY = 42, + AqZ = 43, + PdX = 44, + PdY = 45, + PdZ = 46, + BX = 47, + BY = 48, + BZ = 49, + BoX = 50, + BoY = 51, + BoZ = 52 }; // The following are some definitions for use with the output options in diff --git a/source/MoorDyn2.cpp b/source/MoorDyn2.cpp index 38430a6a..bb3310d5 100644 --- a/source/MoorDyn2.cpp +++ b/source/MoorDyn2.cpp @@ -69,12 +69,27 @@ namespace moordyn { /// The list of units for the output const char* UnitList[] = { - "(s) ", "(m) ", "(m) ", "(m) ", "(deg) ", - "(deg) ", "(deg) ", "(m/s) ", "(m/s) ", "(m/s) ", - "(deg/s) ", "(deg/s) ", "(deg/s) ", "(m/s2) ", "(m/s2) ", - "(m/s2) ", "(deg/s2) ", "(deg/s2) ", "(deg/s2) ", "(N) ", - "(N) ", "(N) ", "(N) ", "(Nm) ", "(Nm) ", - "(Nm) ", "(frac) " + "s", // 0: Time + "m", "m", "m", // 1: PosX 2: PosY 3: PosZ + "deg", "deg", "deg", // 4: RX 5: RY 6: RZ + "m/s", "m/s", "m/s", // 7: VelX 8: VelY 9: VelZ + "deg/s", "deg/s", "deg/s", // 10: RVelX 11: RVelY 12: RVelZ + "m/s^2", "m/s^2", "m/s^2", // 13: AccX 14: AccY 15: AccZ + "deg/s^2", "deg/s^2", "deg/s^2", // 16: RAccX 17: RAccY 18: RAccZ + "N", // 19: Ten + "N", "N", "N", // 20: FX 21: FY 22: FZ + "N*m", "N*m", "N*m", // 23: MX 24: MY 25: MZ + "(frac)", // 26: Sub + "N", "N", // 27: TenA 28: TenB + "N", // 29: WZ + "N", "N", "N", // 30: BoX 31: BoY 32: BoZ + "N", "N", "N", // 33: DpX 34: DpY 35: DpZ + "N*m", "N*m", "N*m", // 36: DqX 37: DqY 38: DqZ + "N", "N", "N", // 39: ApX 40: ApY 41: ApZ + "N", "N", "N", // 42: AqX 43: AqY 44: AqZ + "Pa", "Pa", "Pa", // 45: PdX 46: PdY 47: PdZ + "N", "N", "N", // 48: BX 49: BY 50: BZ + "N", "N", "N" // 51: BoX 52: BoY 53: BoZ }; std::atomic __systems_counter(0); diff --git a/source/Rod.cpp b/source/Rod.cpp index de5b8f3e..35949d3e 100644 --- a/source/Rod.cpp +++ b/source/Rod.cpp @@ -33,6 +33,7 @@ #include "Line.hpp" #include "Waves.hpp" #include +#include #ifdef USE_VTK #include @@ -267,6 +268,54 @@ Rod::openoutput() << i << "Fz \t "; } } + // Output Weight + if (channels.find("W") != string::npos) { + for (unsigned int i = 0; i <= N; i++) + *outfile << "Node" << i << "Wx \t Node" << i << "Wy \t Node" + << i << "Wz \t "; + } + // output Buoyancy + if (channels.find("B") != string::npos) { + for (unsigned int i = 0; i <= N; i++) + *outfile << "Node" << i << "Box \t Node" << i << "Boy \t Node" + << i << "Boz \t "; + } + // output Dynamic Pressure + if (channels.find("X") != string::npos) { + for (unsigned int i = 0; i <= N; i++) + *outfile << "Node" << i << "Dpx \t Node" << i << "Dpy \t Node" + << i << "Dpz \t "; + } + // output Tangential drag + if (channels.find("Y") != string::npos) { + for (unsigned int i = 0; i <= N; i++) + *outfile << "Node" << i << "Dqx \t Node" << i << "Dqy \t Node" + << i << "Dqz \t "; + } + // output transverse inertia force + if (channels.find("A") != string::npos) { + for (unsigned int i = 0; i <= N; i++) + *outfile << "Node" << i << "ApX \t Node" << i << "ApY \t Node" + << i << "ApZ \t "; + } + // output axial fluid inertia force + if (channels.find("a") != string::npos) { + for (unsigned int i = 0; i <= N; i++) + *outfile << "Node" << i << "AqX \t Node" << i << "AqY \t Node" + << i << "AqZ \t "; + } + // output dynamic pressure + if (channels.find("Pd") != string::npos) { + for (unsigned int i = 0; i <= N; i++) + *outfile << "Node" << i << "Pdx \t Node" << i << "Pdy \t Node" + << i << "Pdz \t "; + } + // output bottom contact force + if (channels.find("b") != string::npos) { + for (unsigned int i = 0; i <= N; i++) + *outfile << "Node" << i << "Bx \t Node" << i << "By \t Node" + << i << "Bz \t "; + }; *outfile << "\n"; @@ -292,6 +341,46 @@ Rod::openoutput() for (unsigned int i = 0; i <= 3 * N + 2; i++) *outfile << "(N) \t"; } + // Output Weight + if (channels.find("W") != string::npos) { + for (unsigned int i = 0; i <= 3 * N + 2; i++) + *outfile << "(N) \t"; + } + // output Buoyancy + if (channels.find("B") != string::npos) { + for (unsigned int i = 0; i <= 3 * N + 2; i++) + *outfile << "(N) \t"; + } + // output Dynamic Pressure + if (channels.find("Y") != string::npos) { + for (unsigned int i = 0; i <= 3 * N + 2; i++) + *outfile << "(Pa) \t"; + } + // output Tangential drag + if (channels.find("X") != string::npos) { + for (unsigned int i = 0; i <= 3 * N + 2; i++) + *outfile << "(N) \t"; + } + // output transverse inertia force + if (channels.find("A") != string::npos) { + for (unsigned int i = 0; i <= 3 * N + 2; i++) + *outfile << "(N) \t"; + } + // output axial fluid inertia force + if (channels.find("a") != string::npos) { + for (unsigned int i = 0; i <= 3 * N + 2; i++) + *outfile << "(N) \t"; + } + // output dynamic pressure + if (channels.find("P") != string::npos) { + for (unsigned int i = 0; i <= 3 * N + 2; i++) + *outfile << "(Pa) \t"; + } + // output bottom contact force + if (channels.find("b") != string::npos) { + for (unsigned int i = 0; i <= 3 * N + 2; i++) + *outfile << "(N) \t"; + } *outfile << "\n"; } @@ -422,6 +511,51 @@ Rod::GetRodOutput(OutChanProps outChan) return Fnet[outChan.NodeID][1]; else if (outChan.QType == FZ) return Fnet[outChan.NodeID][2]; + else if (outChan.QType == WZ) + return W[outChan.NodeID][2]; + else if (outChan.QType == BoX) + return Bo[outChan.NodeID][0]; + else if (outChan.QType == BoY) + return Bo[outChan.NodeID][1]; + else if (outChan.QType == BoZ) + return Bo[outChan.NodeID][2]; + else if (outChan.QType == DpX) + return Dp[outChan.NodeID][0]; + else if (outChan.QType == DpY) + return Dp[outChan.NodeID][1]; + else if (outChan.QType == DpZ) + return Dp[outChan.NodeID][2]; + else if (outChan.QType == DqX) + return Dq[outChan.NodeID][0]; + else if (outChan.QType == DqY) + return Dq[outChan.NodeID][1]; + else if (outChan.QType == DqZ) + return Dq[outChan.NodeID][2]; + else if (outChan.QType == ApX) + return Ap[outChan.NodeID][0]; + else if (outChan.QType == ApY) + return Ap[outChan.NodeID][1]; + else if (outChan.QType == ApZ) + return Ap[outChan.NodeID][2]; + else if (outChan.QType == AqX) + return Aq[outChan.NodeID][0]; + else if (outChan.QType == AqY) + return Aq[outChan.NodeID][1]; + else if (outChan.QType == AqZ) + return Aq[outChan.NodeID][2]; + else if (outChan.QType == PdX) + return Pd[outChan.NodeID][0]; + else if (outChan.QType == PdY) + return Pd[outChan.NodeID][1]; + else if (outChan.QType == PdZ) + return Pd[outChan.NodeID][2]; + else if (outChan.QType == BX) + return B[outChan.NodeID][0]; + else if (outChan.QType == BY) + return B[outChan.NodeID][1]; + else if (outChan.QType == BZ) + return B[outChan.NodeID][2]; + } LOGWRN << "Unrecognized output channel " << outChan.QType << endl; return 0.0; @@ -988,12 +1122,12 @@ Rod::doRHS() // get scalar for submerged portion if (h0 < 0.0) { // Upside down case - if (Lsum + dL >= h0) // if fully submerged + if (Lsum >= -h0) // if fully submerged VOF0 = 1.0; - else if (Lsum > h0) // if partially below waterline - VOF0 = (h0 - Lsum) / dL; + else if (Lsum + dL > -h0) // if partially below waterline + VOF0 = (Lsum + dL + h0) / dL; // partially submerged else // must be out of water - VOF0 = 0.0; + VOF0 = 0.0; // fully out of water } else { if (Lsum + dL <= h0) // if fully submerged VOF0 = 1.0; @@ -1432,8 +1566,48 @@ Rod::Output(real time) *outfile << Fnet[i][J] << "\t "; } } + // individual forces + if (channels.find("W") != string::npos) + for (unsigned int i = 0; i <= N; i++) + for (unsigned int J = 0; J < 3; J++) + *outfile << W[i][J] << "\t "; - *outfile << "\n"; + if (channels.find("B") != string::npos) + for (unsigned int i = 0; i <= N; i++) + for (unsigned int J = 0; J < 3; J++) + *outfile << Bo[i][J] << "\t "; + + if (channels.find("Y") != string::npos) + for (unsigned int i = 0; i <= N; i++) + for (unsigned int J = 0; J < 3; J++) + *outfile << Dp[i][J] << "\t "; + + if (channels.find("X") != string::npos) + for (unsigned int i = 0; i <= N; i++) + for (unsigned int J = 0; J < 3; J++) + *outfile << Dq[i][J] << "\t "; + + if (channels.find("A") != string::npos) + for (unsigned int i = 0; i <= N; i++) + for (unsigned int J = 0; J < 3; J++) + *outfile << Ap[i][J] << "\t "; + + if (channels.find("a") != string::npos) + for (unsigned int i = 0; i <= N; i++) + for (unsigned int J = 0; J < 3; J++) + *outfile << Aq[i][J] << "\t "; + + if (channels.find("P") != string::npos) + for (unsigned int i = 0; i <= N; i++) + for (unsigned int J = 0; J < 3; J++) + *outfile << Pd[i][J] << "\t "; + + if (channels.find("b") != string::npos) + for (unsigned int i = 0; i <= N; i++) + for (unsigned int J = 0; J < 3; J++) + *outfile << B[i][J] << "\t "; + + *outfile << "\n"; // end of row } return; } From 36ee755ad4f197fc1f8e3feb1614ace113d41b07 Mon Sep 17 00:00:00 2001 From: kylerf229 Date: Tue, 5 Aug 2025 13:41:28 -0600 Subject: [PATCH 2/5] Added new rod outputs to inputs.rst --- docs/inputs.rst | 10 +++++++++- source/Rod.cpp | 20 ++++++++++---------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/docs/inputs.rst b/docs/inputs.rst index ff6d1b41..f879c06f 100644 --- a/docs/inputs.rst +++ b/docs/inputs.rst @@ -429,7 +429,15 @@ outputs are wanted. Eight output properties are currently possible: - c – internal damping force at each segment - s – strain of each segment - d – rate of strain of each segment - + - f – net node force + - W – weight at each node + - B – buoyancy force at each node + - P – dynamic pressure at each node + - X – transverse drag force at each node + - Y – tangential drag force at each node + - A – transverse inertia force at each node + - a – axial fluid inertia force at each node + - b – bottom contact force For example, outputting node positions and segment tensions could be achieved by writing “pt” for this last column. These outputs will go to a dedicated output file for each rod. For sending values to the global output file, use the Outputs section instead. diff --git a/source/Rod.cpp b/source/Rod.cpp index 35949d3e..85c7c443 100644 --- a/source/Rod.cpp +++ b/source/Rod.cpp @@ -280,13 +280,13 @@ Rod::openoutput() *outfile << "Node" << i << "Box \t Node" << i << "Boy \t Node" << i << "Boz \t "; } - // output Dynamic Pressure + // output transverse drag if (channels.find("X") != string::npos) { for (unsigned int i = 0; i <= N; i++) *outfile << "Node" << i << "Dpx \t Node" << i << "Dpy \t Node" << i << "Dpz \t "; } - // output Tangential drag + // output tangential drag if (channels.find("Y") != string::npos) { for (unsigned int i = 0; i <= N; i++) *outfile << "Node" << i << "Dqx \t Node" << i << "Dqy \t Node" @@ -305,7 +305,7 @@ Rod::openoutput() << i << "AqZ \t "; } // output dynamic pressure - if (channels.find("Pd") != string::npos) { + if (channels.find("P") != string::npos) { for (unsigned int i = 0; i <= N; i++) *outfile << "Node" << i << "Pdx \t Node" << i << "Pdy \t Node" << i << "Pdz \t "; @@ -331,12 +331,12 @@ Rod::openoutput() for (unsigned int i = 0; i <= 3 * N + 2; i++) *outfile << "(m) \t"; } - // output velocities? + // output velocities if (channels.find("v") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) *outfile << "(m/s) \t"; } - // output net node force? + // output net node force if (channels.find("f") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) *outfile << "(N) \t"; @@ -351,13 +351,13 @@ Rod::openoutput() for (unsigned int i = 0; i <= 3 * N + 2; i++) *outfile << "(N) \t"; } - // output Dynamic Pressure - if (channels.find("Y") != string::npos) { + // output transverse drag + if (channels.find("X") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(Pa) \t"; + *outfile << "(N) \t"; } - // output Tangential drag - if (channels.find("X") != string::npos) { + // output tangential drag + if (channels.find("Y") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) *outfile << "(N) \t"; } From 2d7091a960236b958ae9142e0a10ab7883b0f42b Mon Sep 17 00:00:00 2001 From: kylerf229 Date: Thu, 7 Aug 2025 12:15:56 -0600 Subject: [PATCH 3/5] Removed main output file sections and cleaned up code --- docs/inputs.rst | 4 +-- source/Misc.hpp | 22 --------------- source/MoorDyn2.cpp | 10 ------- source/Rod.cpp | 69 ++++++++------------------------------------- 4 files changed, 14 insertions(+), 91 deletions(-) diff --git a/docs/inputs.rst b/docs/inputs.rst index f879c06f..2721d319 100644 --- a/docs/inputs.rst +++ b/docs/inputs.rst @@ -435,8 +435,8 @@ outputs are wanted. Eight output properties are currently possible: - P – dynamic pressure at each node - X – transverse drag force at each node - Y – tangential drag force at each node - - A – transverse inertia force at each node - - a – axial fluid inertia force at each node + - A – transverse fluid inertia force at each node + - a – tangential fluid inertia force at each node - b – bottom contact force For example, outputting node positions and segment tensions could be achieved by writing “pt” for this last column. These outputs will go to a dedicated output file for each rod. For sending diff --git a/source/Misc.hpp b/source/Misc.hpp index 0f669be8..4dfda938 100644 --- a/source/Misc.hpp +++ b/source/Misc.hpp @@ -1241,28 +1241,6 @@ enum QTypeEnum : int Sub = 26, TenA = 27, TenB = 28, - WZ = 31, - DpX = 32, - DpY = 33, - DpZ = 34, - DqX = 35, - DqY = 36, - DqZ = 37, - ApX = 38, - ApY = 39, - ApZ = 40, - AqX = 41, - AqY = 42, - AqZ = 43, - PdX = 44, - PdY = 45, - PdZ = 46, - BX = 47, - BY = 48, - BZ = 49, - BoX = 50, - BoY = 51, - BoZ = 52 }; // The following are some definitions for use with the output options in diff --git a/source/MoorDyn2.cpp b/source/MoorDyn2.cpp index bb3310d5..20199d40 100644 --- a/source/MoorDyn2.cpp +++ b/source/MoorDyn2.cpp @@ -80,16 +80,6 @@ const char* UnitList[] = { "N", "N", "N", // 20: FX 21: FY 22: FZ "N*m", "N*m", "N*m", // 23: MX 24: MY 25: MZ "(frac)", // 26: Sub - "N", "N", // 27: TenA 28: TenB - "N", // 29: WZ - "N", "N", "N", // 30: BoX 31: BoY 32: BoZ - "N", "N", "N", // 33: DpX 34: DpY 35: DpZ - "N*m", "N*m", "N*m", // 36: DqX 37: DqY 38: DqZ - "N", "N", "N", // 39: ApX 40: ApY 41: ApZ - "N", "N", "N", // 42: AqX 43: AqY 44: AqZ - "Pa", "Pa", "Pa", // 45: PdX 46: PdY 47: PdZ - "N", "N", "N", // 48: BX 49: BY 50: BZ - "N", "N", "N" // 51: BoX 52: BoY 53: BoZ }; std::atomic __systems_counter(0); diff --git a/source/Rod.cpp b/source/Rod.cpp index 85c7c443..28bde26f 100644 --- a/source/Rod.cpp +++ b/source/Rod.cpp @@ -298,7 +298,7 @@ Rod::openoutput() *outfile << "Node" << i << "ApX \t Node" << i << "ApY \t Node" << i << "ApZ \t "; } - // output axial fluid inertia force + // output tangential fluid inertia force if (channels.find("a") != string::npos) { for (unsigned int i = 0; i <= N; i++) *outfile << "Node" << i << "AqX \t Node" << i << "AqY \t Node" @@ -361,12 +361,12 @@ Rod::openoutput() for (unsigned int i = 0; i <= 3 * N + 2; i++) *outfile << "(N) \t"; } - // output transverse inertia force + // output transverse fluid inertia force if (channels.find("A") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) *outfile << "(N) \t"; } - // output axial fluid inertia force + // output tangential fluid inertia force if (channels.find("a") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) *outfile << "(N) \t"; @@ -511,51 +511,6 @@ Rod::GetRodOutput(OutChanProps outChan) return Fnet[outChan.NodeID][1]; else if (outChan.QType == FZ) return Fnet[outChan.NodeID][2]; - else if (outChan.QType == WZ) - return W[outChan.NodeID][2]; - else if (outChan.QType == BoX) - return Bo[outChan.NodeID][0]; - else if (outChan.QType == BoY) - return Bo[outChan.NodeID][1]; - else if (outChan.QType == BoZ) - return Bo[outChan.NodeID][2]; - else if (outChan.QType == DpX) - return Dp[outChan.NodeID][0]; - else if (outChan.QType == DpY) - return Dp[outChan.NodeID][1]; - else if (outChan.QType == DpZ) - return Dp[outChan.NodeID][2]; - else if (outChan.QType == DqX) - return Dq[outChan.NodeID][0]; - else if (outChan.QType == DqY) - return Dq[outChan.NodeID][1]; - else if (outChan.QType == DqZ) - return Dq[outChan.NodeID][2]; - else if (outChan.QType == ApX) - return Ap[outChan.NodeID][0]; - else if (outChan.QType == ApY) - return Ap[outChan.NodeID][1]; - else if (outChan.QType == ApZ) - return Ap[outChan.NodeID][2]; - else if (outChan.QType == AqX) - return Aq[outChan.NodeID][0]; - else if (outChan.QType == AqY) - return Aq[outChan.NodeID][1]; - else if (outChan.QType == AqZ) - return Aq[outChan.NodeID][2]; - else if (outChan.QType == PdX) - return Pd[outChan.NodeID][0]; - else if (outChan.QType == PdY) - return Pd[outChan.NodeID][1]; - else if (outChan.QType == PdZ) - return Pd[outChan.NodeID][2]; - else if (outChan.QType == BX) - return B[outChan.NodeID][0]; - else if (outChan.QType == BY) - return B[outChan.NodeID][1]; - else if (outChan.QType == BZ) - return B[outChan.NodeID][2]; - } LOGWRN << "Unrecognized output channel " << outChan.QType << endl; return 0.0; @@ -1571,37 +1526,37 @@ Rod::Output(real time) for (unsigned int i = 0; i <= N; i++) for (unsigned int J = 0; J < 3; J++) *outfile << W[i][J] << "\t "; - + // output buoyancy forces if (channels.find("B") != string::npos) for (unsigned int i = 0; i <= N; i++) for (unsigned int J = 0; J < 3; J++) *outfile << Bo[i][J] << "\t "; - + // output tangential drag forces if (channels.find("Y") != string::npos) for (unsigned int i = 0; i <= N; i++) for (unsigned int J = 0; J < 3; J++) - *outfile << Dp[i][J] << "\t "; - + *outfile << Dq[i][J] << "\t "; + // output transverse drag forces if (channels.find("X") != string::npos) for (unsigned int i = 0; i <= N; i++) for (unsigned int J = 0; J < 3; J++) - *outfile << Dq[i][J] << "\t "; - + *outfile << Dp[i][J] << "\t "; + // output transverse fluid inertia forces if (channels.find("A") != string::npos) for (unsigned int i = 0; i <= N; i++) for (unsigned int J = 0; J < 3; J++) *outfile << Ap[i][J] << "\t "; - + // output tangential fluid inertia forces if (channels.find("a") != string::npos) for (unsigned int i = 0; i <= N; i++) for (unsigned int J = 0; J < 3; J++) *outfile << Aq[i][J] << "\t "; - + // output dynamic pressure forces if (channels.find("P") != string::npos) for (unsigned int i = 0; i <= N; i++) for (unsigned int J = 0; J < 3; J++) *outfile << Pd[i][J] << "\t "; - + // output seabed bottom contact forces if (channels.find("b") != string::npos) for (unsigned int i = 0; i <= N; i++) for (unsigned int J = 0; J < 3; J++) From 4e2596099bcb38eb56d9de03d8a298309078a70a Mon Sep 17 00:00:00 2001 From: kylerf229 Date: Fri, 8 Aug 2025 11:32:07 -0600 Subject: [PATCH 4/5] Added formatting changes for lines and rods when writing to the files to be like fortran outputs --- source/Line.cpp | 158 ++++++++++++++++++-------------- source/MoorDyn2.cpp | 25 +++-- source/Rod.cpp | 218 +++++++++++++++++++++++--------------------- 3 files changed, 220 insertions(+), 181 deletions(-) diff --git a/source/Line.cpp b/source/Line.cpp index 2e738d0f..206dfeca 100644 --- a/source/Line.cpp +++ b/source/Line.cpp @@ -35,6 +35,7 @@ #include "Util/Interp.hpp" #include // #include +#include #ifdef USE_VTK #include "Util/VTK_Util.hpp" @@ -46,6 +47,10 @@ #include #endif +// Formating constants for line files outputs (iomanip) +constexpr int WIDTH = 20; // Width for output +constexpr int PRECISION = 7; // Precision for output + using namespace std; namespace moordyn { @@ -302,80 +307,87 @@ Line::initialize() // 1st line with the fields // output time - *outfile << "Time" - << "\t "; + *outfile << setw(10) << right + << "Time"; // output positions if (channels.find("p") != string::npos) { for (unsigned int i = 0; i <= N; i++) { - *outfile << "Node" << i << "px \t Node" << i << "py \t Node" - << i << "pz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "px") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "py") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "pz"); } } // output curvatures if (channels.find("K") != string::npos) { for (unsigned int i = 0; i <= N; i++) { - *outfile << "Node" << i << "Ku \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Ku"); } } // output velocities if (channels.find("v") != string::npos) { for (unsigned int i = 0; i <= N; i++) { - *outfile << "Node" << i << "vx \t Node" << i << "vy \t Node" - << i << "vz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "vx") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "vy") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "vz"); } } // output wave velocities if (channels.find("U") != string::npos) { for (unsigned int i = 0; i <= N; i++) { - *outfile << "Node" << i << "Ux \t Node" << i << "Uy \t Node" - << i << "Uz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Ux") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Uy") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Uz"); } } // output hydro force if (channels.find("D") != string::npos) { for (unsigned int i = 0; i <= N; i++) { - *outfile << "Node" << i << "Dx \t Node" << i << "Dy \t Node" - << i << "Dz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Dx") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Dy") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Dz"); } } // output VIV lift force if (channels.find("V") != string::npos) { for (unsigned int i = 0; i <= N; i++) { - *outfile << "Node" << i << "Vx \t Node" << i << "Vy \t Node" - << i << "Vz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Vx") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Vy") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Vz"); } } // output segment tensions if (channels.find("t") != string::npos) { for (unsigned int i = 1; i <= N; i++) { - *outfile << "Seg" << i << "Te \t "; + *outfile << setw(WIDTH) << right << ("Seg" + to_string((int)i) + "Te"); } } // output internal damping force if (channels.find("c") != string::npos) { for (unsigned int i = 1; i <= N; i++) { - *outfile << "Seg" << i << "cx \t Seg" << i << "cy \t Seg" << i - << "cz \t "; + *outfile << setw(WIDTH) << right << ("Seg" + to_string((int)i) + "cx") + << setw(WIDTH) << right << ("Seg" + to_string((int)i) + "cy") + << setw(WIDTH) << right << ("Seg" + to_string((int)i) + "cz"); } } // output segment strains if (channels.find("s") != string::npos) { for (unsigned int i = 1; i <= N; i++) { - *outfile << "Seg" << i << "St \t "; + *outfile << setw(WIDTH) << right << ("Seg" + to_string((int)i) + "St"); } } // output segment strain rates if (channels.find("d") != string::npos) { for (unsigned int i = 1; i <= N; i++) { - *outfile << "Seg" << i << "dSt \t "; + *outfile << setw(WIDTH) << right << ("Seg" + to_string((int)i) + "dSt"); } } // output seabed contact forces if (channels.find("b") != string::npos) { for (unsigned int i = 0; i <= N; i++) { - *outfile << "Node" << i << "bx \t Node" << i << "by \t Node" - << i << "bz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "bx") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "by") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "bz"); } } @@ -385,64 +397,75 @@ Line::initialize() // 2nd line with the units // output time - *outfile << "(s)" - << "\t "; + *outfile << setw(10) << right + << "(s)"; // output positions if (channels.find("p") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(m) \t"; + *outfile << setw(WIDTH) << right + << "(m)"; } // output curvatures? if (channels.find("K") != string::npos) { for (unsigned int i = 0; i <= N; i++) { - *outfile << "(1/m) \t "; + *outfile << setw(WIDTH) << right + << "(1/m)"; } } // output velocities? if (channels.find("v") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(m/s) \t"; + *outfile << setw(WIDTH) << right + << "(m/s)"; } // output wave velocities? if (channels.find("U") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(m/s) \t"; + *outfile << setw(WIDTH) << right + << "(m/s)"; } // output hydro force if (channels.find("D") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right + << "(N)"; } // output VIV force if (channels.find("V") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right + << "(N)"; } // output segment tensions? if (channels.find("t") != string::npos) { for (unsigned int i = 0; i < N; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right + << "(N)"; } // output internal damping force? if (channels.find("c") != string::npos) { for (unsigned int i = 0; i < 3 * N; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right + << "(N)"; } // output segment strains? if (channels.find("s") != string::npos) { for (unsigned int i = 0; i < N; i++) - *outfile << "(-) \t"; + *outfile << setw(WIDTH) << right + << "(-)"; } // output segment strain rates? if (channels.find("d") != string::npos) { for (unsigned int i = 0; i < N; i++) - *outfile << "(-/s) \t"; + *outfile << setw(WIDTH) << right + << "(-/s)"; } // output seabed contact force? if (channels.find("b") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right + << "(N)"; } *outfile << "\n"; @@ -1554,66 +1577,73 @@ Line::Output(real time) // Flags changed to just be one character (case sensitive) per output flag. // To match FASTv8 version. +// Helper to format and write a single value +auto write_val = [&](real val) { + *outfile << std::setw(WIDTH) + << std::right + << std::scientific + << std::setprecision(PRECISION) + << val; + }; + if (outfile) // if not a null pointer (indicating no output) { if (!outfile->is_open()) { LOGWRN << "Unable to write to output file " << endl; return; } + // Loops through the nodes + auto write_vec_array = [&](const std::vector& arr) { + for (unsigned int i = 0; i <= N; i++) + for (unsigned int J = 0; J < 3; J++){ + write_val(arr[i][J]);} + + }; + // Loops through the nodes for scalars + auto write_scalar_array = [&](const std::vector& arr) { + for (unsigned int i = 0; i <= N; i++) + write_val(arr[i]); + }; // output time - *outfile << time << "\t "; + *outfile << setw(10) << right << fixed << setprecision(4) + << time; // output positions? // if (find(channels.begin(), channels.end(), "position") != // channels.end()) if (channels.find("p") != string::npos) { - for (unsigned int i = 0; i <= N; i++) // loop through nodes - { - for (unsigned int J = 0; J < 3; J++) - *outfile << r[i][J] << "\t "; - } + write_vec_array(r); // position } + // output curvatures? if (channels.find("K") != string::npos) { - for (unsigned int i = 0; i <= N; i++) { - *outfile << Kurv[i] << "\t "; - } + write_scalar_array(Kurv); } // output velocities? if (channels.find("v") != string::npos) { - for (unsigned int i = 0; i <= N; i++) { - for (int J = 0; J < 3; J++) - *outfile << rd[i][J] << "\t "; - } + write_vec_array(rd); } // output wave velocities? if (channels.find("U") != string::npos) { auto [_z, U, _ud, _pdyn] = waves->getWaveKinLine(lineId); - for (unsigned int i = 0; i <= N; i++) { - for (int J = 0; J < 3; J++) - *outfile << U[i][J] << "\t "; - } + write_vec_array(U); } // output hydro drag force? if (channels.find("D") != string::npos) { for (unsigned int i = 0; i <= N; i++) { for (int J = 0; J < 3; J++) - *outfile << Dp[i][J] + Dq[i][J] + Ap[i][J] + Aq[i][J] - << "\t "; + write_val(Dp[i][J] + Dq[i][J] + Ap[i][J] + Aq[i][J]); } } // output VIV force (only CF for now) if (channels.find("V") != string::npos) { - for (unsigned int i = 0; i <= N; i++) { - for (int J = 0; J < 3; J++) - *outfile << Lf[i][J] << "\t "; - } + write_vec_array(Lf); } // output segment tensions? if (channels.find("t") != string::npos) { for (unsigned int i = 0; i < N; i++) { - *outfile << T[i].norm() << "\t "; + write_val(T[i].norm()); // >>> preparation below for switching to outputs at nodes // <<< note that tension of end nodes will need weight and // buoyancy adjustment @@ -1627,29 +1657,23 @@ Line::Output(real time) } // output internal damping force? if (channels.find("c") != string::npos) { - for (unsigned int i = 0; i < N; i++) { - for (int J = 0; J < 3; J++) - *outfile << Td[i][J] << "\t "; - } + write_vec_array(Td); // internal damping force } // output segment strains? if (channels.find("s") != string::npos) { for (unsigned int i = 0; i < N; i++) { - *outfile << lstr[i] / l[i] - 1.0 << "\t "; + write_val(lstr[i] / l[i] - 1.0); } } // output segment strain rates? if (channels.find("d") != string::npos) { for (unsigned int i = 0; i < N; i++) { - *outfile << ldstr[i] / l[i] << "\t "; + write_val(ldstr[i] / l[i]); } } // output seabed contact forces? if (channels.find("b") != string::npos) { - for (unsigned int i = 0; i <= N; i++) { - for (int J = 0; J < 3; J++) - *outfile << B[i][J] << "\t "; - } + write_vec_array(B); } *outfile << "\n"; diff --git a/source/MoorDyn2.cpp b/source/MoorDyn2.cpp index 20199d40..b5c3e171 100644 --- a/source/MoorDyn2.cpp +++ b/source/MoorDyn2.cpp @@ -35,6 +35,7 @@ #include "MoorDyn2.hpp" #include "Rod.hpp" #include +#include #ifdef LINUX #include @@ -50,6 +51,10 @@ using namespace std; +// Formating constants for rod files outputs (iomanip) +constexpr int WIDTH = 20; // Width for output +constexpr int PRECISION = 7; // Precision for output + /** * @brief A helper function for getting the size of a vector as an unsigned int * @@ -626,18 +631,19 @@ moordyn::MoorDyn::Init(const double* x, const double* xd, bool skip_ic) } // --- channel titles --- - outfileMain << "Time" - << "\t "; + outfileMain << setw(10) << right + << "Time"; for (auto channel : outChans) - outfileMain << channel.Name << "\t "; + outfileMain << setw(WIDTH) << right << channel.Name; outfileMain << endl; if (env->WriteUnits > 0) { // --- units --- - outfileMain << "(s)" - << "\t "; + outfileMain << setw(10) << right + << "(s)"; for (auto channel : outChans) - outfileMain << channel.Units << "\t "; + outfileMain << setw(WIDTH) << right + << channel.Units; outfileMain << "\n"; } @@ -2418,12 +2424,15 @@ moordyn::MoorDyn::WriteOutputs(double t, double dt) LOGERR << "Error: Unable to write to main output file " << endl; return MOORDYN_INVALID_OUTPUT_FILE; } - outfileMain << t << "\t "; // output time + outfileMain << setw(10) << right << fixed << setprecision(4) + << t; // output time for (auto channel : outChans) { moordyn::error_id err = MOORDYN_SUCCESS; string err_msg; try { - outfileMain << GetOutput(channel) << "\t "; + outfileMain << setw(WIDTH) << right << fixed << scientific + << setprecision(PRECISION) + << GetOutput(channel); } MOORDYN_CATCHER(err, err_msg); if (err != MOORDYN_SUCCESS) { diff --git a/source/Rod.cpp b/source/Rod.cpp index 28bde26f..18a4d821 100644 --- a/source/Rod.cpp +++ b/source/Rod.cpp @@ -47,6 +47,10 @@ using namespace std; +// Formating constants for rod files outputs (iomanip) +constexpr int WIDTH = 20; // Width for output +constexpr int PRECISION = 7; // Precision for output + namespace moordyn { // here is the new numbering scheme (N segments per line) @@ -244,78 +248,91 @@ Rod::openoutput() // 1st line with the fields // output time - *outfile << "Time" - << "\t "; + *outfile << setw(10) << right + << "Time"; // output positions if (channels.find("p") != string::npos) { for (unsigned int i = 0; i <= N; i++) { - *outfile << "Node" << i << "px \t Node" << i << "py \t Node" - << i << "pz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "px") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "py") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "pz"); } } // output velocities if (channels.find("v") != string::npos) { for (unsigned int i = 0; i <= N; i++) { - *outfile << "Node" << i << "vx \t Node" << i << "vy \t Node" - << i << "vz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "vx") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "vy") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "vz"); } } // output net node force if (channels.find("f") != string::npos) { for (unsigned int i = 0; i <= N; i++) { - *outfile << "Node" << i << "Fx \t Node" << i << "Fy \t Node" - << i << "Fz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Fx") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Fy") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Fz"); } } // Output Weight if (channels.find("W") != string::npos) { for (unsigned int i = 0; i <= N; i++) - *outfile << "Node" << i << "Wx \t Node" << i << "Wy \t Node" - << i << "Wz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Wx") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Wy") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Wz"); } // output Buoyancy if (channels.find("B") != string::npos) { for (unsigned int i = 0; i <= N; i++) - *outfile << "Node" << i << "Box \t Node" << i << "Boy \t Node" - << i << "Boz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Box") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Boy") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Boz"); } // output transverse drag if (channels.find("X") != string::npos) { for (unsigned int i = 0; i <= N; i++) - *outfile << "Node" << i << "Dpx \t Node" << i << "Dpy \t Node" - << i << "Dpz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Dpx") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Dpy") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Dpz"); } // output tangential drag if (channels.find("Y") != string::npos) { for (unsigned int i = 0; i <= N; i++) - *outfile << "Node" << i << "Dqx \t Node" << i << "Dqy \t Node" - << i << "Dqz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Dqx") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Dqy") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Dqz"); } // output transverse inertia force if (channels.find("A") != string::npos) { for (unsigned int i = 0; i <= N; i++) - *outfile << "Node" << i << "ApX \t Node" << i << "ApY \t Node" - << i << "ApZ \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "ApX") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "ApY") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "ApZ"); + } // output tangential fluid inertia force if (channels.find("a") != string::npos) { for (unsigned int i = 0; i <= N; i++) - *outfile << "Node" << i << "AqX \t Node" << i << "AqY \t Node" - << i << "AqZ \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "AqX") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "AqY") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "AqZ"); } // output dynamic pressure if (channels.find("P") != string::npos) { for (unsigned int i = 0; i <= N; i++) - *outfile << "Node" << i << "Pdx \t Node" << i << "Pdy \t Node" - << i << "Pdz \t "; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Pdx") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Pdy") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Pdz"); + } // output bottom contact force if (channels.find("b") != string::npos) { for (unsigned int i = 0; i <= N; i++) - *outfile << "Node" << i << "Bx \t Node" << i << "By \t Node" - << i << "Bz \t "; - }; + *outfile << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Bx") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "By") + << setw(WIDTH) << right << ("Node" + to_string((int)i) + "Bz"); + } *outfile << "\n"; @@ -323,63 +340,63 @@ Rod::openoutput() // 2nd line with the units // output time - *outfile << "(s)" - << "\t "; + *outfile << setw(10) << right + << "(s)"; // output positions if (channels.find("p") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(m) \t"; + *outfile << setw(WIDTH) << right << "(m)"; } // output velocities if (channels.find("v") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(m/s) \t"; + *outfile << setw(WIDTH) << right << "(m/s)"; } // output net node force if (channels.find("f") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right << "(N)"; } // Output Weight if (channels.find("W") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right << "(N)"; } // output Buoyancy if (channels.find("B") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right << "(N)"; } // output transverse drag if (channels.find("X") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right << "(N)"; } // output tangential drag if (channels.find("Y") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right << "(N)"; } // output transverse fluid inertia force if (channels.find("A") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right << "(N)"; } // output tangential fluid inertia force if (channels.find("a") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right << "(N)"; } // output dynamic pressure if (channels.find("P") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(Pa) \t"; + *outfile << setw(WIDTH) << right << "(Pa)"; } // output bottom contact force if (channels.find("b") != string::npos) { for (unsigned int i = 0; i <= 3 * N + 2; i++) - *outfile << "(N) \t"; + *outfile << setw(WIDTH) << right << "(N)"; } *outfile << "\n"; @@ -1484,6 +1501,15 @@ Rod::Output(real time) // Flags changed to just be one character (case sensitive) per output flag. // To match FASTv8 version. +// Helper to format and write a single value +auto write_val = [&](real val) { + *outfile << std::setw(WIDTH) + << std::right + << std::scientific + << std::setprecision(PRECISION) + << val; + }; + if (outfile) // if not a null pointer (indicating no output) { if (openedoutfile == 0) { @@ -1497,76 +1523,56 @@ Rod::Output(real time) return; } // output time - *outfile << time << "\t "; - - // output positions? - if (channels.find("p") != string::npos) { - for (unsigned int i = 0; i <= N; i++) // loop through nodes - { - for (int J = 0; J < 3; J++) - *outfile << r[i][J] << "\t "; - } - } - // output velocities? - if (channels.find("v") != string::npos) { - for (unsigned int i = 0; i <= N; i++) { - for (int J = 0; J < 3; J++) - *outfile << rd[i][J] << "\t "; - } - } - // output net node forces? - if (channels.find("f") != string::npos) { - for (unsigned int i = 0; i <= N; i++) { - for (unsigned int J = 0; J < 3; J++) - *outfile << Fnet[i][J] << "\t "; - } - } - // individual forces - if (channels.find("W") != string::npos) - for (unsigned int i = 0; i <= N; i++) - for (unsigned int J = 0; J < 3; J++) - *outfile << W[i][J] << "\t "; - // output buoyancy forces - if (channels.find("B") != string::npos) - for (unsigned int i = 0; i <= N; i++) - for (unsigned int J = 0; J < 3; J++) - *outfile << Bo[i][J] << "\t "; - // output tangential drag forces - if (channels.find("Y") != string::npos) - for (unsigned int i = 0; i <= N; i++) - for (unsigned int J = 0; J < 3; J++) - *outfile << Dq[i][J] << "\t "; - // output transverse drag forces - if (channels.find("X") != string::npos) - for (unsigned int i = 0; i <= N; i++) - for (unsigned int J = 0; J < 3; J++) - *outfile << Dp[i][J] << "\t "; - // output transverse fluid inertia forces - if (channels.find("A") != string::npos) - for (unsigned int i = 0; i <= N; i++) - for (unsigned int J = 0; J < 3; J++) - *outfile << Ap[i][J] << "\t "; - // output tangential fluid inertia forces - if (channels.find("a") != string::npos) - for (unsigned int i = 0; i <= N; i++) - for (unsigned int J = 0; J < 3; J++) - *outfile << Aq[i][J] << "\t "; - // output dynamic pressure forces - if (channels.find("P") != string::npos) - for (unsigned int i = 0; i <= N; i++) - for (unsigned int J = 0; J < 3; J++) - *outfile << Pd[i][J] << "\t "; - // output seabed bottom contact forces - if (channels.find("b") != string::npos) - for (unsigned int i = 0; i <= N; i++) - for (unsigned int J = 0; J < 3; J++) - *outfile << B[i][J] << "\t "; - - *outfile << "\n"; // end of row + *outfile << setw(10) << right << fixed << setprecision(4) + << time; + // Loops through the nodes and writes the values + auto write_vec_array = [&](const std::vector& arr) { + for (unsigned int i = 0; i <= N; i++) + for (unsigned int J = 0; J < 3; J++){ + write_val(arr[i][J]);} + }; + + // --------------------- + // Output data per channel + // --------------------- + if (channels.find("p") != string::npos) { + write_vec_array(r); // position + } + if (channels.find("v") != string::npos) { + write_vec_array(rd); // velocity + } + if (channels.find("f") != string::npos) { + write_vec_array(Fnet); // net node forces + } + if (channels.find("W") != string::npos) { + write_vec_array(W); // weight + } + if (channels.find("B") != string::npos) { + write_vec_array(Bo); // buoyancy + } + if (channels.find("Y") != string::npos) { + write_vec_array(Dq); // tangential drag + } + if (channels.find("X") != string::npos) { + write_vec_array(Dp); // transverse drag + } + if (channels.find("A") != string::npos) { + write_vec_array(Ap); // transverse fluid inertia + } + if (channels.find("a") != string::npos) { + write_vec_array(Aq); // tangential fluid inertia + } + if (channels.find("P") != string::npos) { + write_vec_array(Pd); // dynamic pressure + } + if (channels.find("b") != string::npos) { + write_vec_array(B); // seabed contact (bottom contact forces) } - return; -} + *outfile << "\n"; + } + +} std::vector Rod::Serialize(void) { From a3334464465f71cb43db6f3379a95a87611dac95 Mon Sep 17 00:00:00 2001 From: kylerf229 Date: Fri, 8 Aug 2025 11:35:14 -0600 Subject: [PATCH 5/5] removed commas --- source/Misc.hpp | 2 +- source/MoorDyn2.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Misc.hpp b/source/Misc.hpp index 4dfda938..b8178363 100644 --- a/source/Misc.hpp +++ b/source/Misc.hpp @@ -1240,7 +1240,7 @@ enum QTypeEnum : int MZ = 25, Sub = 26, TenA = 27, - TenB = 28, + TenB = 28 }; // The following are some definitions for use with the output options in diff --git a/source/MoorDyn2.cpp b/source/MoorDyn2.cpp index b5c3e171..1ed52a75 100644 --- a/source/MoorDyn2.cpp +++ b/source/MoorDyn2.cpp @@ -84,7 +84,7 @@ const char* UnitList[] = { "N", // 19: Ten "N", "N", "N", // 20: FX 21: FY 22: FZ "N*m", "N*m", "N*m", // 23: MX 24: MY 25: MZ - "(frac)", // 26: Sub + "(frac)" // 26: Sub }; std::atomic __systems_counter(0);