MoorDyn
Misc.hpp
1 /*
2  * Copyright (c) 2022, Matt Hall
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 #pragma once
32 
33 // Visual studio still uses this
34 #define _USE_MATH_DEFINES
35 
36 #include "MoorDynAPI.h"
37 #include "Eigen/Dense"
38 
39 #include "Waves/WaveOptions.hpp"
40 
41 #include <vector>
42 #include <string>
43 #include <cmath>
44 #include <complex>
45 #include <utility>
46 #include <initializer_list>
47 #include <filesystem>
48 
49 #include <memory>
50 #include <limits>
51 
52 #ifdef OSX
53 #include <sys/uio.h>
54 #elif defined WIN32
55 #include <windows.h> // these are for guicon function RedirectIOToConsole
56 #include <io.h>
57 #endif
58 
59 // note: this file contains the struct definitions for environmental and
60 // line/point properties
61 
62 // from IƱaki Zabala
63 #ifdef _MSC_VER
64 template<typename T>
65 static inline T
66 round(T val)
67 {
68  return floor(val + 0.5);
69 }
70 #endif
71 
72 using namespace std;
73 
74 namespace Eigen {
75 // Eigen does not provide 6 or 7 components objects out of the box
76 typedef Matrix<float, 6, 1> Vector6f;
77 typedef Matrix<float, 6, 6> Matrix6f;
78 typedef Matrix<double, 6, 1> Vector6d;
79 typedef Matrix<double, 6, 6> Matrix6d;
80 typedef Matrix<int, 6, 1> Vector6i;
81 typedef Matrix<int, 6, 6> Matrix6i;
82 typedef Matrix<float, 7, 1> Vector7f;
83 typedef Matrix<float, 7, 7> Matrix7f;
84 typedef Matrix<double, 7, 1> Vector7d;
85 typedef Matrix<double, 7, 7> Matrix7d;
86 typedef Matrix<int, 7, 1> Vector7i;
87 typedef Matrix<int, 7, 7> Matrix7i;
88 // It is also convenient for us to define a generic Eigen dynamic matrix class
89 #ifdef MOORDYN_SINGLEPRECISSION
90 typedef MatrixXf MatrixXr;
91 #else
92 typedef MatrixXd MatrixXr;
93 #endif
94 }
95 
98 namespace moordyn {
99 
100 #ifdef MOORDYN_SINGLEPRECISSION
101 typedef float real;
102 typedef Eigen::Vector2f vec2;
103 typedef Eigen::Vector3f vec3;
104 typedef Eigen::Vector4f vec4;
105 typedef Eigen::Vector6f vec6;
106 typedef Eigen::Vector7f vec7;
107 typedef vec3 vec;
108 typedef Eigen::Matrix2f mat2;
109 typedef Eigen::Matrix3f mat3;
110 typedef Eigen::Matrix4f mat4;
111 typedef Eigen::Matrix6f mat6;
112 typedef Eigen::Matrix7f mat7;
113 typedef mat3 mat;
114 typedef Eigen::Quaternionf quaternion;
115 typedef Eigen::Matrix<real, Eigen::Dynamic, 1> list;
116 #else
118 typedef double real;
120 typedef Eigen::Vector2d vec2;
122 typedef Eigen::Vector3d vec3;
124 typedef Eigen::Vector4d vec4;
126 typedef Eigen::Vector6d vec6;
128 typedef Eigen::Vector7d vec7;
130 typedef vec3 vec;
132 typedef Eigen::Matrix2d mat2;
134 typedef Eigen::Matrix3d mat3;
136 typedef Eigen::Matrix4d mat4;
138 typedef Eigen::Matrix6d mat6;
140 typedef Eigen::Matrix7d mat7;
142 typedef mat3 mat;
144 typedef Eigen::Quaterniond quaternion;
146 typedef Eigen::Matrix<real, Eigen::Dynamic, 1> list;
147 #endif
149 typedef Eigen::Vector2i ivec2;
151 typedef Eigen::Vector3i ivec3;
153 typedef Eigen::Vector4i ivec4;
155 typedef Eigen::Vector6i ivec6;
157 typedef Eigen::Vector7i ivec7;
159 typedef ivec3 ivec;
160 
162 typedef std::complex<real> complex;
163 
165 typedef Eigen::Matrix<real, Eigen::Dynamic, Eigen::Dynamic> InstanceStateVar;
167 typedef Eigen::Block<InstanceStateVar, Eigen::Dynamic> InstanceStateVarView;
169 typedef Eigen::Matrix<InstanceStateVar, Eigen::Dynamic, 1> StateVar;
171 typedef Eigen::VectorBlock<StateVar, Eigen::Dynamic> StateVarView;
172 
187 inline bool
188 EqualRealNos(const real a1, const real a2)
189 {
190  constexpr real eps = std::numeric_limits<moordyn::real>::epsilon();
191  constexpr real tol = ((real)100.0) * eps / ((real)2.0);
192 
193  const real fraction = (std::max)(std::abs(a1 + a2), ((real)1.0));
194  return std::abs(a1 - a2) <= fraction * tol;
195 }
196 
197 inline vec3
198 canonicalEulerAngles(const quaternion& quat, int a0, int a1, int a2)
199 {
200  // From issue #163:
201  // https://github.com/FloatingArrayDesign/MoorDyn/issues/163
202  mat3 coeff = quat.normalized().toRotationMatrix();
203  vec3 res{};
204  using Index = int;
205  using Scalar = real;
206  const Index odd = ((a0 + 1) % 3 == a1) ? 0 : 1;
207  const Index i = a0;
208  const Index j = (a0 + 1 + odd) % 3;
209  const Index k = (a0 + 2 - odd) % 3;
210  if (a0 == a2) {
211  // Proper Euler angles (same first and last axis).
212  // The i, j, k indices enable addressing the input matrix as the XYX
213  // archetype matrix (see Graphics Gems IV), where e.g. coeff(k, i) means
214  // third column, first row in the XYX archetype matrix:
215  // c2 s2s1 s2c1
216  // s2s3 -c2s1s3 + c1c3 -c2c1s3 - s1c3
217  // -s2c3 c2s1c3 + c1s3 c2c1c3 - s1s3
218  // Note: s2 is always positive.
219  Scalar s2 = Eigen::numext::hypot(coeff(j, i), coeff(k, i));
220  if (odd) {
221  res[0] = atan2(coeff(j, i), coeff(k, i));
222  // s2 is always positive, so res[1] will be within the canonical [0,
223  // pi] range
224  res[1] = atan2(s2, coeff(i, i));
225  } else {
226  // In the !odd case, signs of all three angles are flipped at the
227  // very end. To keep the solution within the canonical range, we
228  // flip the solution and make res[1] always negative here (since s2
229  // is always positive, -atan2(s2, c2) will always be negative). The
230  // final flip at the end due to !odd will thus make res[1] positive
231  // and canonical. NB: in the general case, there are two correct
232  // solutions, but only one is canonical. For proper Euler angles,
233  // flipping from one solution to the other involves flipping the
234  // sign of the second angle res[1] and adding/subtracting pi to the
235  // first and third angles. The addition/subtraction of pi to the
236  // first angle res[0] is handled here by flipping the signs of
237  // arguments to atan2, while the calculation of the third angle does
238  // not need special adjustment since it uses the adjusted res[0] as
239  // the input and produces a correct result.
240  res[0] = atan2(-coeff(j, i), -coeff(k, i));
241  res[1] = -atan2(s2, coeff(i, i));
242  }
243  // With a=(0,1,0), we have i=0; j=1; k=2, and after computing the first
244  // two angles, we can compute their respective rotation, and apply its
245  // inverse to M. Since the result must be a rotation around x, we have:
246  //
247  // c2 s1.s2 c1.s2 1 0 0
248  // 0 c1 -s1 * M = 0 c3 s3
249  // -s2 s1.c2 c1.c2 0 -s3 c3
250  //
251  // Thus: m11.c1 - m21.s1 = c3 & m12.c1 - m22.s1 = s3
252  Scalar s1 = sin(res[0]);
253  Scalar c1 = cos(res[0]);
254  res[2] = atan2(c1 * coeff(j, k) - s1 * coeff(k, k),
255  c1 * coeff(j, j) - s1 * coeff(k, j));
256  } else {
257  // Tait-Bryan angles (all three axes are different; typically used for
258  // yaw-pitch-roll calculations). The i, j, k indices enable addressing
259  // the input matrix as the XYZ archetype matrix (see Graphics Gems IV),
260  // where e.g. coeff(k, i) means third column, first row in the XYZ
261  // archetype matrix:
262  // c2c3 s2s1c3 - c1s3 s2c1c3 + s1s3
263  // c2s3 s2s1s3 + c1c3 s2c1s3 - s1c3
264  // -s2 c2s1 c2c1
265  res[0] = atan2(coeff(j, k), coeff(k, k));
266  Scalar c2 = Eigen::numext::hypot(coeff(i, i), coeff(i, j));
267  // c2 is always positive, so the following atan2 will always return a
268  // result in the correct canonical middle angle range [-pi/2, pi/2]
269  res[1] = atan2(-coeff(i, k), c2);
270  Scalar s1 = sin(res[0]);
271  Scalar c1 = cos(res[0]);
272  res[2] = atan2(s1 * coeff(k, i) - c1 * coeff(j, i),
273  c1 * coeff(j, j) - s1 * coeff(k, j));
274  }
275  if (!odd) {
276  res = -res;
277  }
278  return res;
279 }
280 
281 inline vec3
282 Quat2Euler(const quaternion& q)
283 {
284  // 0, 1, 2 correspond to axes leading to XYZ rotation
285  return canonicalEulerAngles(q, 0, 1, 2);
286 }
287 
288 inline quaternion
289 Euler2Quat(const vec3& angles)
290 {
291  using AngleAxis = Eigen::AngleAxis<real>;
292  quaternion q = AngleAxis(angles.x(), vec3::UnitX()) *
293  AngleAxis(angles.y(), vec3::UnitY()) *
294  AngleAxis(angles.z(), vec3::UnitZ());
295  return q;
296 }
297 
303 struct XYZQuat
304 {
305  vec3 pos;
306  quaternion quat;
307 
308  XYZQuat() {}
309 
310  XYZQuat(vec3 pos, quaternion quat)
311  : pos(pos)
312  , quat(quat)
313  {
314  }
315 
316  static XYZQuat Zero()
317  {
318  return XYZQuat{ vec3::Zero(), quaternion::Identity() };
319  }
320  static XYZQuat fromVec6(const vec6& vec)
321  {
322  return XYZQuat{ vec.head<3>(), Euler2Quat(vec.tail<3>()) };
323  }
324  vec6 toVec6() const
325  {
326  vec6 out;
327  out.head<3>() = this->pos;
328  out.tail<3>() = Quat2Euler(this->quat);
329  return out;
330  }
331  static XYZQuat fromVec7(const vec7& vec)
332  {
333  return XYZQuat{ vec.head<3>(), quaternion(vec.tail<4>()) };
334  }
335  vec7 toVec7() const
336  {
337  vec7 out;
338  out.head<3>() = pos;
339  out.tail<4>() = quat.coeffs();
340  return out;
341  }
342 
343  XYZQuat operator+(const XYZQuat& visitor) const;
344  XYZQuat operator-(const XYZQuat& visitor) const;
345  XYZQuat& operator*=(const real& visitor);
346  XYZQuat operator*(const real& visitor) const;
347 };
348 
350 const complex i1(0., 1.);
351 
356 template<typename T>
357 inline void
358 vec2array(const vec& v, T* a)
359 {
360  a[0] = (T)v[0];
361  a[1] = (T)v[1];
362  a[2] = (T)v[2];
363 }
364 
369 template<typename T>
370 inline void
371 array2vec(const T* a, vec& v)
372 {
373  v[0] = (moordyn::real)a[0];
374  v[1] = (moordyn::real)a[1];
375  v[2] = (moordyn::real)a[2];
376 }
377 
382 template<typename T>
383 inline void
384 vec62array(const vec6& v, T* a)
385 {
386  a[0] = (T)v[0];
387  a[1] = (T)v[1];
388  a[2] = (T)v[2];
389  a[3] = (T)v[3];
390  a[4] = (T)v[4];
391  a[5] = (T)v[5];
392 }
393 
398 template<typename T>
399 inline void
400 array2vec6(const T* a, vec6& v)
401 {
402  v[0] = (moordyn::real)a[0];
403  v[1] = (moordyn::real)a[1];
404  v[2] = (moordyn::real)a[2];
405  v[3] = (moordyn::real)a[3];
406  v[4] = (moordyn::real)a[4];
407  v[5] = (moordyn::real)a[5];
408 }
409 
414 template<typename T>
415 inline void
416 mat2array(const mat& v, T a[3][3])
417 {
418  a[0][0] = (T)v(0, 0);
419  a[0][1] = (T)v(0, 1);
420  a[0][2] = (T)v(0, 2);
421  a[1][0] = (T)v(1, 0);
422  a[1][1] = (T)v(1, 1);
423  a[1][2] = (T)v(1, 2);
424  a[2][0] = (T)v(2, 0);
425  a[2][1] = (T)v(2, 1);
426  a[2][2] = (T)v(2, 2);
427 }
428 
433 template<typename T>
434 inline void
435 array2mat(const T a[3][3], mat& v)
436 {
437  v(0, 0) = (moordyn::real)a[0][0];
438  v(0, 1) = (moordyn::real)a[0][1];
439  v(0, 2) = (moordyn::real)a[0][2];
440  v(1, 0) = (moordyn::real)a[1][0];
441  v(1, 1) = (moordyn::real)a[1][1];
442  v(1, 2) = (moordyn::real)a[1][2];
443  v(2, 0) = (moordyn::real)a[2][0];
444  v(2, 1) = (moordyn::real)a[2][1];
445  v(2, 2) = (moordyn::real)a[2][2];
446 }
447 
452 template<typename T>
453 inline void
454 mat62array(const mat6& v, T a[6][6])
455 {
456  a[0][0] = (T)v(0, 0);
457  a[0][1] = (T)v(0, 1);
458  a[0][2] = (T)v(0, 2);
459  a[0][3] = (T)v(0, 3);
460  a[0][4] = (T)v(0, 4);
461  a[0][5] = (T)v(0, 5);
462  a[1][0] = (T)v(1, 0);
463  a[1][1] = (T)v(1, 1);
464  a[1][2] = (T)v(1, 2);
465  a[1][3] = (T)v(1, 3);
466  a[1][4] = (T)v(1, 4);
467  a[1][5] = (T)v(1, 5);
468  a[2][0] = (T)v(2, 0);
469  a[2][1] = (T)v(2, 1);
470  a[2][2] = (T)v(2, 2);
471  a[2][3] = (T)v(2, 3);
472  a[2][4] = (T)v(2, 4);
473  a[2][5] = (T)v(2, 5);
474 }
475 
480 template<typename T>
481 inline void
482 array2mat6(const T a[6][6], mat6& v)
483 {
484  v(0, 0) = (moordyn::real)a[0][0];
485  v(0, 1) = (moordyn::real)a[0][1];
486  v(0, 2) = (moordyn::real)a[0][2];
487  v(0, 3) = (moordyn::real)a[0][3];
488  v(0, 4) = (moordyn::real)a[0][4];
489  v(0, 5) = (moordyn::real)a[0][5];
490  v(1, 0) = (moordyn::real)a[1][0];
491  v(1, 1) = (moordyn::real)a[1][1];
492  v(1, 2) = (moordyn::real)a[1][2];
493  v(1, 3) = (moordyn::real)a[1][3];
494  v(1, 4) = (moordyn::real)a[1][4];
495  v(1, 5) = (moordyn::real)a[1][5];
496  v(2, 0) = (moordyn::real)a[2][0];
497  v(2, 1) = (moordyn::real)a[2][1];
498  v(2, 2) = (moordyn::real)a[2][2];
499  v(2, 3) = (moordyn::real)a[2][3];
500  v(2, 4) = (moordyn::real)a[2][4];
501  v(2, 5) = (moordyn::real)a[2][5];
502 }
503 
510 template<typename T>
511 std::vector<T>
512 vector_slice(std::vector<T> const& v, unsigned int m, unsigned int n)
513 {
514  auto first = v.begin() + m;
515  auto last = first + n;
516  std::vector<T> v2(first, last);
517  return v2;
518 }
519 
525 template<typename T>
526 std::vector<T>
527 vector_slice(std::vector<T> const& v, unsigned int n)
528 {
529  return vector_slice(v, 0, n);
530 }
531 
536 template<typename T>
537 void
538 vector_extend(std::vector<T>& v, std::vector<T> const& v_prime)
539 {
540  v.reserve(v.size() + distance(v_prime.begin(), v_prime.end()));
541  v.insert(v.end(), v_prime.begin(), v_prime.end());
542 }
543 
550 template<typename T, int NROWS, int NCOLS>
551 std::vector<T> flatten(std::vector<Eigen::Matrix<T, NROWS, NCOLS>> const& v)
552 {
553  const int stride = NROWS * NCOLS;
554  std::vector<T> out(v.size() * stride);
555  for (unsigned int i = 0; i < v.size(); i++) {
556  for (unsigned int j = 0; j < NROWS; j++) {
557  for (unsigned int k = 0; k < NCOLS; k++) {
558  out[i * stride + j * NCOLS + k] = v[i](j, k);
559  }
560  }
561  }
562  return out;
563 }
564 
569 typedef enum
570 {
575  // Some aliases
576  ENDPOINT_BOTTOM = ENDPOINT_A,
577  ENDPOINT_TOP = ENDPOINT_B,
578 } EndPoints;
579 
583 inline char
585 {
586  return char('A' + (int)p);
587 }
588 
594 typedef int error_id;
595 
597 #define MAKE_EXCEPTION(name) \
598  class name : public std::runtime_error \
599  { \
600  public: \
601  name(const char* msg) \
602  : std::runtime_error(msg) \
603  { \
604  } \
605  };
606 
608 MAKE_EXCEPTION(input_file_error)
610 MAKE_EXCEPTION(output_file_error)
612 MAKE_EXCEPTION(input_error)
614 MAKE_EXCEPTION(nan_error)
616 MAKE_EXCEPTION(mem_error)
618 MAKE_EXCEPTION(invalid_value_error)
620 MAKE_EXCEPTION(non_implemented_error)
622 MAKE_EXCEPTION(invalid_type_error)
624 MAKE_EXCEPTION(unhandled_error)
625 
626 #define MOORDYN_THROW(err, msg) \
629  switch (err) { \
630  case MOORDYN_SUCCESS: \
631  break; \
632  case MOORDYN_INVALID_INPUT_FILE: \
633  throw moordyn::input_file_error(msg); \
634  break; \
635  case MOORDYN_INVALID_OUTPUT_FILE: \
636  throw moordyn::output_file_error(msg); \
637  break; \
638  case MOORDYN_INVALID_INPUT: \
639  throw moordyn::input_error(msg); \
640  break; \
641  case MOORDYN_NAN_ERROR: \
642  throw moordyn::nan_error(msg); \
643  break; \
644  case MOORDYN_MEM_ERROR: \
645  throw moordyn::mem_error(msg); \
646  break; \
647  case MOORDYN_INVALID_VALUE: \
648  throw moordyn::invalid_value_error(msg); \
649  break; \
650  case MOORDYN_NON_IMPLEMENTED: \
651  throw moordyn::non_implemented_error(msg); \
652  break; \
653  default: \
654  throw moordyn::unhandled_error(msg); \
655  break; \
656  }
657 
662 #define MOORDYN_CATCHER(err, msg) \
663  catch (moordyn::input_file_error const& e) \
664  { \
665  err = MOORDYN_INVALID_INPUT_FILE; \
666  msg = e.what(); \
667  } \
668  catch (moordyn::output_file_error const& e) \
669  { \
670  err = MOORDYN_INVALID_OUTPUT_FILE; \
671  msg = e.what(); \
672  } \
673  catch (moordyn::input_error const& e) \
674  { \
675  err = MOORDYN_INVALID_INPUT; \
676  msg = e.what(); \
677  } \
678  catch (moordyn::nan_error const& e) \
679  { \
680  err = MOORDYN_NAN_ERROR; \
681  msg = e.what(); \
682  } \
683  catch (moordyn::mem_error const& e) \
684  { \
685  err = MOORDYN_MEM_ERROR; \
686  msg = e.what(); \
687  } \
688  catch (moordyn::invalid_value_error const& e) \
689  { \
690  err = MOORDYN_INVALID_VALUE; \
691  msg = e.what(); \
692  } \
693  catch (moordyn::unhandled_error const& e) \
694  { \
695  err = MOORDYN_UNHANDLED_ERROR; \
696  msg = e.what(); \
697  }
698 
707 namespace str {
708 
713 string
714 lower(const string& str);
715 
720 string
721 upper(const string& str);
722 
728 bool
729 startswith(const string& str, const string& prefix);
730 
737 bool
738 has(const string& str, const vector<string> terms);
739 
745 vector<string>
746 split(const string& str, const char sep);
747 
754 inline vector<string>
755 split(const string& s)
756 {
757  vector<string> sout = split(s, ' ');
758  if (sout.size() == 1)
759  return split(sout[0],
760  ' '); // if space didnt split it, try again with tab
761  else
762  return sout;
763 }
764 
770 void
771 rtrim(string& s);
772 
775 int DECLDIR
776 decomposeString(const std::string& outWord,
777  std::string& let1,
778  std::string& num1,
779  std::string& let2,
780  std::string& num2,
781  std::string& let3);
782 
783 bool
784 isOneOf(const std::string& str,
785  const std::initializer_list<const std::string> values);
786 
787 } // ::moordyn::str
788 
789 namespace fileIO {
790 
795 std::vector<std::string>
796 fileToLines(const std::filesystem::path& path);
797 
798 }
799 
810 typedef enum
811 {
817 
833 vec6 DECLDIR
834 solveMat6(const mat6& mat, const vec6& vec);
835 
846 inline moordyn::real
847 unitvector(vec& u, const vec& r1, const vec& r2)
848 {
849  u = r2 - r1;
850  const double l = u.norm();
851  if (!EqualRealNos(l, 0.0))
852  u /= l;
853  return l;
854 }
855 
863 template<typename T>
864 inline void
865 scalevector(const vec& u, T newlength, vec& y)
866 {
867  const moordyn::real l2 = u.squaredNorm();
868  if (EqualRealNos(l2, 0.0)) {
869  y = u;
870  return;
871  }
872  const moordyn::real scaler = (moordyn::real)newlength / sqrt(l2);
873  y = scaler * u;
874 }
875 
885 inline mat
887 {
888  mat H;
889  // clang-format off
890  H << 0, r[2], -r[1],
891  -r[2], 0, r[0],
892  r[1], -r[0], 0;
893  // clang-format on
894  return H;
895 }
896 
902 mat6 DECLDIR
903 translateMass(vec r, mat M);
904 
910 mat6 DECLDIR
911 translateMass6(vec r, mat6 M);
912 
920 inline mat
922 {
923  return R * M * R.transpose();
924 }
925 
933 mat6 DECLDIR
934 rotateMass6(mat R, mat6 M);
935 
945 void
946 transformKinematics(const vec& rRelBody,
947  const mat& M,
948  const vec& r,
949  const vec6& rd,
950  vec& rOut,
951  vec& rdOut);
952 
957 inline mat
958 RotX(real rads)
959 {
960  const real s = sin(rads);
961  const real c = cos(rads);
962  mat R;
963  R << 1., 0., 0., 0., c, -s, 0., s, c;
964  return R;
965 }
966 
971 inline mat
972 RotY(real rads)
973 {
974  const real s = sin(rads);
975  const real c = cos(rads);
976  mat R;
977  R << c, 0., s, 0., 1., 0., -s, 0., c;
978  return R;
979 }
980 
985 inline mat
986 RotZ(real rads)
987 {
988  const real s = sin(rads);
989  const real c = cos(rads);
990  mat R;
991  R << c, -s, 0., s, c, 0., 0., 0., 1.;
992  return R;
993 }
994 
995 // clang-format off
997 #define MAKE_EULER_ROT(a,b,c) \
998 inline mat Rot ## a ## b ## c(real a1, real a2, real a3) \
999 { \
1000  return Rot ## a (a1) * Rot ## b (a2) * Rot ## c (a3); \
1001 } \
1002 inline mat Rot ## a ## b ## c(vec rads) \
1003 { \
1004  return Rot ## a ## b ## c (rads[0], rads[1], rads[2]); \
1005 }
1006 
1007 // clang-format on
1008 
1009 MAKE_EULER_ROT(X, Y, X)
1010 MAKE_EULER_ROT(X, Y, Z)
1011 MAKE_EULER_ROT(X, Z, X)
1012 MAKE_EULER_ROT(X, Z, Y)
1013 MAKE_EULER_ROT(Y, X, Y)
1014 MAKE_EULER_ROT(Y, X, Z)
1015 MAKE_EULER_ROT(Y, Z, X)
1016 MAKE_EULER_ROT(Y, Z, Y)
1017 MAKE_EULER_ROT(Z, X, Y)
1018 MAKE_EULER_ROT(Z, X, Z)
1019 MAKE_EULER_ROT(Z, Y, X)
1020 MAKE_EULER_ROT(Z, Y, Z)
1021 
1022 
1028 std::pair<real, real>
1029 orientationAngles(vec q);
1030 
1039 GetCurvature(moordyn::real length, const vec& q1, const vec& q2);
1040 
1045 #if !defined(MOORDYN_SINGLEPRECISSION) && defined(M_PIl)
1047 const real pi = M_PIl;
1048 #else
1050 // const real pi = M_PI;
1051 const real pi = 3.141592653589793238462643383279502884197169399375105820974944;
1052 #endif
1054 const real rad2deg = 180.0 / pi;
1055 
1057 const real deg2rad = pi / 180.0;
1058 
1064 class Rod;
1065 class Point;
1066 class Line;
1067 
1070 typedef struct _FailProps
1071 {
1079  std::vector<Line*> lines;
1082  std::vector<EndPoints> line_end_points;
1088  bool status;
1090 
1095 } // ::moordyn
1096 
1098 operator*(const moordyn::real& k, const moordyn::quaternion& v);
1099 
1100 const int nCoef = 30; // maximum number of entries to allow in nonlinear
1101  // coefficient lookup tables
1102 
1107 struct EnvCond
1108 {
1110  double g;
1112  double WtrDpth;
1114  double rho_w;
1115 
1117  double kb;
1119  double cb;
1122 
1124  moordyn::waves::WaterKinOptions waterKinOptions;
1125 
1129  double FricDamp;
1132 
1139 };
1140 
1141 typedef std::shared_ptr<EnvCond> EnvCondRef;
1142 
1144 
1145 typedef struct _LineProps // (matching Line Dictionary inputs)
1146 {
1147  string type;
1148  double d;
1149  double w; // linear weight in air
1150  int ElasticMod;
1151  double EA;
1152  double EA_D;
1153  double alphaMBL;
1154  double vbeta;
1155  double EI;
1156  double BA; // internal damping
1157  double BA_D;
1158  double cI;
1159  double Can;
1160  double Cat;
1161  double Cdn;
1162  double Cdt;
1163  double Cl; // VIV lift coefficient. If 0, VIV turned off.
1164  double dF; // +- range around cF for VIV synchronization model
1165  double cF; // center non-dim frequency for VIV synch model
1166  int nEApoints; // number of values in stress-strain lookup table (0 means
1167  // using constant E)
1168  double
1169  stiffXs[nCoef]; // x array for stress-strain lookup table (up to nCoef)
1170  double stiffYs[nCoef]; // y array for stress-strain lookup table
1171  int nBApoints; // number of values in stress-strainrate lookup table (0
1172  // means using constant c)
1173  double dampXs[nCoef]; // x array for stress-strainrate lookup table (up to
1174  // nCoef)
1175  double dampYs[nCoef]; // y array for stress-strainrate lookup table
1176  int nEIpoints = 0; // number of values in bending stress-strain lookup table
1177  // (0 means using constant E)
1178  double
1179  bstiffXs[nCoef]; // x array for stress-strain lookup table (up to nCoef)
1180  double bstiffYs[nCoef]; // y array for stress-strain lookup table
1181  int SyropeWCForm; // Syrope working curve formula (1=linear, 2=quadratic,
1182  // 3=exponential)
1183  double k1; // first coefficient for the Syrope working curve formula
1184  double k2; // second coefficient for the Syrope working curve formula
1185 } LineProps;
1186 
1187 typedef struct _RodProps // (matching Rod Dictionary inputs)
1188 {
1189  string type;
1190  double d;
1191  double w; // linear weight in air
1192  double Can;
1193  double Cat;
1194  double Cdn;
1195  double Cdt;
1196  double CaEnd;
1197  double CdEnd;
1198 } RodProps;
1199 
1200 typedef struct _PointProps // matching node input stuff
1201 {
1202  int number;
1203  string type;
1204  double X;
1205  double Y;
1206  double Z;
1207  double M;
1208  double V;
1209  double FX;
1210  double FY;
1211  double FZ;
1212  double
1213  CdA; // added 2015/1/15 - product of drag coefficient and frontal area
1214  double Ca; // added 2015/1/15 - added mass coefficient
1215 } PointProps;
1216 
1217 typedef struct _BodyProps // matching body input stuff
1218 {
1219  int number;
1220  string type;
1221  double X0; // constants set at startup from input file
1222  double Y0;
1223  double Z0;
1224  double Xcg;
1225  double Ycg;
1226  double Zcg;
1227  double M;
1228  double V;
1229  double IX;
1230  double IY;
1231  double IZ;
1232  double CdA;
1233  double Ca;
1234 } BodyProps;
1235 
1236 // ------------ Output definitions -------------
1237 enum QTypeEnum : int
1238 {
1239 
1240  Time = 0,
1241  PosX = 1,
1242  PosY = 2,
1243  PosZ = 3,
1244  RX = 4,
1245  RY = 5,
1246  RZ = 6,
1247  VelX = 7,
1248  VelY = 8,
1249  VelZ = 9,
1250  RVelX = 10,
1251  RVelY = 11,
1252  RVelZ = 12,
1253  AccX = 13,
1254  AccY = 14,
1255  AccZ = 15,
1256  RAccX = 16,
1257  RAccY = 17,
1258  RAccZ = 18,
1259  Ten = 19,
1260  FX = 20,
1261  FY = 21,
1262  FZ = 22,
1263  MX = 23,
1264  MY = 24,
1265  MZ = 25,
1266  Sub = 26,
1267  TenA = 27,
1268  TenB = 28
1269 };
1270 
1271 // The following are some definitions for use with the output options in
1272 // MoorDyn. These are for the global output quantities specified by OutList, not
1273 // line-specific outputs. Output definitions follow the structure described by
1274 // the MD_OutParmType . Each output channel is described by the following
1275 // fields:
1276 // Name - (string) what appears at the top of the output column
1277 // Units - (string) selected from UnitList (see below) based on index QType
1278 // OType - (int) the type of object the output is from. 1=line, 2=point
1279 // (0=invalid) ObjID - (int) the ID number of the line or point QType -
1280 // (int) the type of quantity to output. 0=tension, 1=x pos, etc. see the
1281 // parameters below NodeID - (int) the ID number of the node of the output
1282 // quantity
1283 //
1284 // These are the "OTypes": 0=Point object, 1=Line Object
1285 // (will just use 0 and 1 rather than parameter names)
1286 //
1287 // Indices for computing output channels: - customized for the MD_OutParmType
1288 // approach these are the "QTypes"
1289 //
1290 // UnitList is in MoorDyn.cpp
1291 typedef struct _OutChanProps
1292 { // this is C version of MDOutParmType - a less literal alternative of the NWTC
1293  // OutParmType for MoorDyn (to avoid huge lists of possible output channel
1294  // permutations)
1295  string Name; // "name of output channel"
1296  string Units; // "units string"
1297  QTypeEnum QType; // "type of quantity - 0=tension, 1=x, 2=y, 3=z..."
1298  int OType; // "type of object - 1=line, 2=point, 3=rod, 4=body"
1299  int NodeID; // "node number if OType = 1 or 3. -1 indicated whole rod or
1300  // fairlead for line"
1301  int ObjID; // "number of Point or Line object", subtract 1 to get the
1302  // index in the LineList or PointList
1303 } OutChanProps;
#define DECLDIR
Prefix to export C functions on the compiled library.
Definition: MoorDynAPI.h:68
A mooring line.
Definition: Line.hpp:71
A point for a line endpoint.
Definition: Point.hpp:69
A cylindrical rod.
Definition: Rod.hpp:65
struct moordyn::_FailProps FailProps
Failure conditions.
seafloor_settings
Definition: Misc.hpp:811
@ SEAFLOOR_3D
3D seafloor
Definition: Misc.hpp:815
@ SEAFLOOR_FLAT
Flat seafloor:
Definition: Misc.hpp:813
#define MAKE_EXCEPTION(name)
Simple macro to define custom exceptions.
Definition: Misc.hpp:597
int error_id
Error identifier.
Definition: Misc.hpp:594
mat6 rotateMass6(mat R, mat6 M)
rotation to a 6x6 mass/inertia tensor
Definition: Misc.cpp:270
mat6 translateMass(vec r, mat M)
Compute the mass matrix on an offset point.
Definition: Misc.cpp:222
mat getH(vec r)
Produce alternator matrix.
Definition: Misc.hpp:886
moordyn::real unitvector(vec &u, const vec &r1, const vec &r2)
Normalized direction vector.
Definition: Misc.hpp:847
std::pair< real, real > orientationAngles(vec v)
Get the spherical angles for a vector.
Definition: Misc.cpp:325
mat RotX(real rads)
Rotation matrix around x axis.
Definition: Misc.hpp:958
mat RotY(real rads)
Rotation matrix around y axis.
Definition: Misc.hpp:972
mat6 translateMass6(vec r, mat6 M)
Compute the mass matrix on an offset point.
Definition: Misc.cpp:243
mat rotateMass(mat R, mat M)
rotation to a 3x3 mass matrix or any other second order tensor
Definition: Misc.hpp:921
moordyn::real GetCurvature(moordyn::real length, const vec &q1, const vec &q2)
Convenience function to calculate curvature based on adjacent segments' direction vectors and their c...
Definition: Misc.cpp:342
mat RotZ(real rads)
Rotation matrix around z axis.
Definition: Misc.hpp:986
void scalevector(const vec &u, T newlength, vec &y)
Compute a vector with the same direction but different length.
Definition: Misc.hpp:865
void transformKinematics(const vec &rRelBody, const mat &M, const vec &r, const vec6 &rd, vec &rOut, vec &rdOut)
calculate position and velocity of point based on its position relative to moving 6DOF body
Definition: Misc.cpp:299
#define MAKE_EULER_ROT(a, b, c)
Create the Euler rotations, like RotXYZ, RotXZX, RotZYX...
Definition: Misc.hpp:997
MoorDyn2 C++ API namespace.
Definition: Body.cpp:27
vec3 vec
vec3 renaming
Definition: Misc.hpp:130
bool EqualRealNos(const real a1, const real a2)
This function compares two real numbers and determines if they are "almost" equal.
Definition: Misc.hpp:188
void array2vec6(const T *a, vec6 &v)
Convert a C-ish array to a vector.
Definition: Misc.hpp:400
std::vector< T > vector_slice(std::vector< T > const &v, unsigned int m, unsigned int n)
Definition: Misc.hpp:512
Eigen::Quaterniond quaternion
Quaternion of real numbers.
Definition: Misc.hpp:144
Eigen::Vector7d vec7
7-D vector of real numbers
Definition: Misc.hpp:128
Eigen::Block< InstanceStateVar, Eigen::Dynamic > InstanceStateVarView
View of the State variables for a particular instance.
Definition: Misc.hpp:167
Eigen::Matrix< real, Eigen::Dynamic, Eigen::Dynamic > InstanceStateVar
State variables for a particular instance.
Definition: Misc.hpp:165
void mat2array(const mat &v, T a[3][3])
Convert a matrix to a C-ish array.
Definition: Misc.hpp:416
void array2mat6(const T a[6][6], mat6 &v)
Convert a C-ish array to a matrix.
Definition: Misc.hpp:482
void mat62array(const mat6 &v, T a[6][6])
Convert a matrix to a C-ish array.
Definition: Misc.hpp:454
Eigen::Vector6d vec6
6-D vector of real numbers
Definition: Misc.hpp:126
Eigen::Vector7i ivec7
7-D vector of integers
Definition: Misc.hpp:157
void vector_extend(std::vector< T > &v, std::vector< T > const &v_prime)
Definition: Misc.hpp:538
Eigen::Matrix7d mat7
7x7 matrix of real numbers
Definition: Misc.hpp:140
Eigen::Vector4i ivec4
4-D vector of integers
Definition: Misc.hpp:153
Eigen::VectorBlock< StateVar, Eigen::Dynamic > StateVarView
View of the State variable.
Definition: Misc.hpp:171
Eigen::Matrix6d mat6
6x6 matrix of real numbers
Definition: Misc.hpp:138
Eigen::Matrix3d mat3
3x3 matrix of real numbers
Definition: Misc.hpp:134
const real deg2rad
Constant to convert degrees into radians.
Definition: Misc.hpp:1057
EndPoints
End point qualifiers.
Definition: Misc.hpp:570
@ ENDPOINT_A
Bottom of the line.
Definition: Misc.hpp:572
@ ENDPOINT_B
Top of the line.
Definition: Misc.hpp:574
Eigen::Vector2i ivec2
2-D vector of integers
Definition: Misc.hpp:149
const complex i1(0., 1.)
The imaginary unit.
std::vector< T > flatten(std::vector< Eigen::Matrix< T, NROWS, NCOLS >> const &v)
Flatten a list of vectors or matrices.
Definition: Misc.hpp:551
Eigen::Vector3i ivec3
3-D vector of integers
Definition: Misc.hpp:151
Eigen::Matrix< InstanceStateVar, Eigen::Dynamic, 1 > StateVar
State variable.
Definition: Misc.hpp:169
Eigen::Vector2d vec2
2-D vector of real numbers
Definition: Misc.hpp:120
double real
Real numbers wrapper. It is either double or float.
Definition: Misc.hpp:118
ivec3 ivec
Renaming of ivec3.
Definition: Misc.hpp:159
Eigen::Matrix2d mat2
2x2 matrix of real numbers
Definition: Misc.hpp:132
const real rad2deg
Constant to convert radians into degrees.
Definition: Misc.hpp:1054
Eigen::Vector6i ivec6
6-D vector of integers
Definition: Misc.hpp:155
Eigen::Matrix< real, Eigen::Dynamic, 1 > list
A resizable list of reals.
Definition: Misc.hpp:146
void vec62array(const vec6 &v, T *a)
Convert a vector to a C-ish array.
Definition: Misc.hpp:384
void array2mat(const T a[3][3], mat &v)
Convert a C-ish array to a matrix.
Definition: Misc.hpp:435
char end_point_name(EndPoints p)
Gives an character representation of the end point.
Definition: Misc.hpp:584
std::complex< real > complex
Complex numbers.
Definition: Misc.hpp:162
Eigen::Vector4d vec4
4-D vector of real numbers
Definition: Misc.hpp:124
Eigen::Vector3d vec3
3-D vector of real numbers
Definition: Misc.hpp:122
Eigen::Matrix4d mat4
4x4 matrix of real numbers
Definition: Misc.hpp:136
void array2vec(const T *a, vec &v)
Convert a C-ish array to a vector.
Definition: Misc.hpp:371
mat3 mat
mat3 renaming
Definition: Misc.hpp:142
void vec2array(const vec &v, T *a)
Convert a vector to a C-ish array.
Definition: Misc.hpp:358
const real pi
Pi constant.
Definition: Misc.hpp:1051
Definition: Misc.hpp:1218
Definition: Misc.hpp:1146
Definition: Misc.hpp:1292
Definition: Misc.hpp:1201
Definition: Misc.hpp:1188
Definition: Misc.hpp:1108
double rho_w
Water density (kg/m^3)
Definition: Misc.hpp:1114
double FrictionCoefficient
general bottom friction coefficient, as a start
Definition: Misc.hpp:1127
double g
Gavity acceleration (m/s^2)
Definition: Misc.hpp:1110
double WtrDpth
Water depth (m)
Definition: Misc.hpp:1112
moordyn::waves::WaterKinOptions waterKinOptions
Water Kinematics Options.
Definition: Misc.hpp:1124
double cb
bottom damping (Pa/m/s)
Definition: Misc.hpp:1119
double FricDamp
a damping coefficient used to model the friction at speeds near zero
Definition: Misc.hpp:1129
int WriteUnits
Definition: Misc.hpp:1135
double StatDynFricScale
a ratio of static to dynamic friction ( = mu_static/mu_dynamic)
Definition: Misc.hpp:1131
moordyn::seafloor_settings SeafloorMode
Bottom modeling mode (0=flat, 1=3d...)<<<.
Definition: Misc.hpp:1121
int writeLog
Definition: Misc.hpp:1138
double kb
bottom stiffness (Pa/m)
Definition: Misc.hpp:1117
Failure conditions.
Definition: Misc.hpp:1071
std::vector< Line * > lines
The attached lines.
Definition: Misc.hpp:1079
std::vector< EndPoints > line_end_points
Definition: Misc.hpp:1082
Rod * rod
The rod the lines are attached to, if any. Otherwise it is NULL.
Definition: Misc.hpp:1073
bool status
false until the line fails
Definition: Misc.hpp:1088
EndPoints rod_end_point
The rod attachment end point, useless if rod is NULL.
Definition: Misc.hpp:1075
Point * point
The point the lines are attached to, if any. Otherwise it is NULL.
Definition: Misc.hpp:1077
real ten
Failure criteria based on tension (N)
Definition: Misc.hpp:1086
real time
Failure criteria based on simulation time (s)
Definition: Misc.hpp:1084
Joint of a point and a quaternion.
Definition: Misc.hpp:304