Repository: FloatingArrayDesign/MoorDyn (language: python)

Issue:
Clang++ compile issue with Waves
I was getting my branch up to date today (from before the waves object was created) and merged all the recent updates in. I have been compiling the library from the makefile in compile/DYLIB/makefile. v2 no longer compiles, and clang throws an error: linker command failed with exit code 1. It says this is caused by undefined symbols for architecture x86_64, all of which are related to the waves object. @sanguinariojoe, any ideas?


<img width="1440" alt="Screenshot 2023-05-25 at 1 54 13 PM" src="https://github.com/FloatingArrayDesign/MoorDyn/assets/101124339/d2fdebdf-9d48-425a-99f2-122cfd3f12bd">

Error introduced in bodies_and_rods test
In v2: Our team has observed that d0b09d27 causes `bodies_and_rods` to no longer converge during the IC stage. Furthermore, when MOORDYN_SSE is set to AVX2, the system actually diverges completely at `t=0.0003`s. This divergence is first caught in Line1, which connects Body1 and a fixed point. The two rods in the model appear to be linked to Body1 as well. This bug also persists in the latest commit ebcac61d.

We haven't determined the root cause of this, but it appears to be due to the changes to the mathematics in Misc.cpp, Misc.hpp, or Rod.cpp, as the input file was not changed in this commit. The issue persists even when the time-step is reduced to be quite low (0.000001), so it does not appear to be a minor stability thing.


Discussion / hints:

To expand on this, it seems like the culprit for the early divergence (introduction of NaNs) was this code starting at line 912 of Rod.cpp
```c++
vec r_top, r_bottom;
real zeta_i;
if (r[N][2] > r[0][2]) {
	r_top = r[N];
	r_bottom = r[0];
	real zeta_i = zeta[N];
} else {
	r_top = r[0];
	r_bottom = r[N];
	real zeta_i = zeta[0];
}

if ((r_bottom[2] < zeta_i) && (r_top[2] > zeta_i)) {
	// the water plane is crossing the rod
	// (should also add some limits to avoid near-horizontals at some point)
	h0 = (zeta_i - r_bottom[2]) / fabs(q[2]);
} else if (r[0][2] < zeta_i) {
	// fully submerged case
	h0 = UnstrLen;
} else {
	// fully unsubmerged case (ever applicable?)
	h0 = 0.0;
}
```
The variable `zeta_i` is not actually ever being initialized, causing it to be read from random uninitialized memory.  Fixing this problem does appear to solve the issue of the simulation quickly running into NaNs, but does not solve the problem of failing to converge during initial conditions solving.
Uhm, interesting! The tests were working just fine on my computer and [GitHub actions](https://github.com/FloatingArrayDesign/MoorDyn/actions/runs/4765512137/jobs/8471332141)

I will give it a look ASAP
With standard settings the tests will pass, but what won't happen is reaching a steady state during the dynamic relaxation/initial conditions solving process. In the github actions log it looks like bodies_and_rods ran for 65 seconds, which at least in local testing generally means that it did not reach it's 1.5% tolerance during the dynamic relaxation and hit the ICmax. In previous commits the test normally finds a steady state rather quickly and would run for a much shorter amount of time.
Hm, the PR in question has changes in the rotation order and rotation matrices (without any explanation that I can see). I know the rotation order also was changed in the initial refactor from my original v2 code. My original code had been verified. Maybe we could just ensure things match the original code’s approach. Or if there’s a reason to handle rotations differently, it would be good to have that stated. @RyanDavies19 any input on this?
I'm not sure if I can say which approach is better, but in dev2 the rotation order was YXZ to deal with the FAST coordinate system convention (line 904 of Misc.cpp). In v2 the rotation order is XYZ (line 1046 of Misc.hpp). It might be worth trying to change the rotation matrix in v2 to YXZ and see if that resolves the issue. 
Hey guys!

Today I will be visiting this issue and letting you know. Anyway, as a matter of fact, bodies_and_rods had some stability issues from the very beginning. In fact, @mattEhall rolled it out to me because it was not working in a previous version.

I hope I can come with news later today
Hm.  The commit has changes in both the rotations and the moments of inertia.

In Rod::doRHS there are various changes to the moment of inertia calculations - both the magnitudes and which axis is which. I really think some explanation should be given in the commit message when the physics are being changed. Ryan, if you’re willing, maybe you could cross reference with the Fortran code. I don’t remember the calculations offhand, so I’m not sure if the commit in question is inserting deviations from the original physics, or if things had already deviated in earlier commits.

Fix patch:
diff --git a/compile/DLL/makefile b/compile/DLL/makefile
index 90b19eec..44cc6b3e 100644
--- a/compile/DLL/makefile
+++ b/compile/DLL/makefile
@@ -22,7 +22,7 @@
 
 
 LFLAGS = -shared -static-libgcc -static-libstdc++ -DMoorDyn_EXPORTS -fPIC
-CFLAGS = -c -O3 -g -Wall -Wextra -DMoorDyn_EXPORTS -fPIC
+CFLAGS = -c -O3 -g -Wall -Wextra -DMoorDyn_EXPORTS -fPIC -I../../source/
 
 ifdef USEGL
 CFLAGS += -DUSEGL
@@ -32,98 +32,46 @@ endif
 CFLAGS += $(COPTS)
 LFLAGS += $(LOPTS)
 
-CPPFLAGS = $(CFLAGS) -std=c++14
-EXEFLAGS = -O3 -g -Wall -Wextra -std=c++14 $(EXEOPTS)
-HEADERS = ../../source/Body.h \
-          ../../source/Connection.h \
-          ../../source/_kiss_fft_guts.h \
-          ../../source/kiss_fft.h \
-          ../../source/kiss_fftr.h \
-          ../../source/Line.h \
-          ../../source/MoorDyn2.h \
-          ../../source/MoorDynAPI.h \
-          ../../source/MoorDyn.h \
-          ../../source/Rod.h \
-          ../../source/Waves.h \
-		  ../../source/Seafloor.h \
-          ../../source/Body.hpp \
-          ../../source/Connection.hpp \
-          ../../source/IO.hpp \
-          ../../source/Line.hpp \
-          ../../source/Log.hpp \
-          ../../source/Misc.hpp \
-          ../../source/MoorDyn2.hpp \
-          ../../source/QSlines.hpp \
-          ../../source/Rod.hpp \
-          ../../source/State.hpp \
-          ../../source/Time.hpp \
-          ../../source/Waves.hpp \
-		  ../../source/Seafloor.hpp
+CPPFLAGS = $(CFLAGS) -std=c++17
+EXEFLAGS = -O3 -g -Wall -Wextra -std=c++17 $(EXEOPTS)
+HEADERS = $(wildcard ../../source/*.hpp) \
+          $(wildcard ../../source/Util/*.hpp) \
+          $(wildcard ../../source/Waves/*.hpp) \
+          $(wildcard ../../source/*.h)
+SOURCES = $(wildcard ../../source/*.cpp) \
+          $(wildcard ../../source/Util/*.cpp) \
+          $(wildcard ../../source/Waves/*.cpp)
+OBJECTS = $(patsubst ../../source/%,%,$(patsubst %.cpp,%.o,$(SOURCES)))
+DIRGUARD = @mkdir -p $(@D)
 
 all: libmoordyn2.dll
 
-libmoordyn2.dll: MoorDyn.o MoorDyn2.o Line.o Connection.o Rod.o Body.o Log.o IO.o Misc.o State.o Time.o Waves.o Seafloor.o kiss_fftr.o kiss_fft.o
-	$(CXX) $(LFLAGS) -o libmoordyn2.dll MoorDyn.o MoorDyn2.o Line.o Rod.o Body.o Connection.o Log.o IO.o Misc.o State.o Time.o Waves.o Seafloor.o kiss_fftr.o kiss_fft.o
+libmoordyn2.dll: $(OBJECTS)
+	$(CXX) $(LFLAGS) -o libmoordyn2.dll $(OBJECTS)
 
-MoorDyn.o: ../../source/MoorDyn.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/MoorDyn.cpp
-
-MoorDyn2.o: ../../source/MoorDyn2.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/MoorDyn2.cpp
-
-kiss_fft.o: ../../source/kiss_fft.cpp ../../source/kiss_fft.h ../../source/_kiss_fft_guts.h
-	$(CC) $(CFLAGS) ../../source/kiss_fft.cpp
-
-kiss_fftr.o: ../../source/kiss_fftr.cpp ../../source/kiss_fftr.h ../../source/_kiss_fft_guts.h
-	$(CC) $(CFLAGS) ../../source/kiss_fftr.cpp
-
-Line.o: ../../source/Line.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Line.cpp
-
-Connection.o: ../../source/Connection.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Connection.cpp
-
-Body.o: ../../source/Body.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Body.cpp
-
-Rod.o: ../../source/Rod.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Rod.cpp
-
-State.o: ../../source/State.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/State.cpp
-
-Time.o: ../../source/Time.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Time.cpp
-
-Waves.o: ../../source/Waves.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Waves.cpp
-
-Seafloor.o: ../../source/Seafloor.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Seafloor.cpp
-
-Log.o: ../../source/Log.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Log.cpp
-
-IO.o: ../../source/IO.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/IO.cpp
-
-Misc.o: ../../source/Misc.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Misc.cpp
+%.o: ../../source/%.cpp $(HEADERS)
+	${CXX} $(CPPFLAGS) -o $@ $<
+Util/%.o: ../../source/Util/%.cpp $(HEADERS)
+	$(DIRGUARD)
+	${CXX} $(CPPFLAGS) -o $@ $<
+Waves/%.o: ../../source/Waves/%.cpp $(HEADERS)
+	$(DIRGUARD)
+	${CXX} $(CPPFLAGS) -o $@ $<
 
 clean:
 	$(RM) *.exe.manifest *.exe *.obj *.o *.dll
 
-test_minimal.exe: ../../test/minimal.cpp libmoordyn2.dll
-	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_minimal.exe ../../test/minimal.cpp
+test_minimal.exe: ../../tests/minimal.cpp libmoordyn2.dll
+	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_minimal.exe ../../tests/minimal.cpp
 
-test_bodies_and_rods.exe: ../../test/bodies_and_rods.cpp libmoordyn2.dll
-	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_bodies_and_rods.exe ../../test/bodies_and_rods.cpp
+test_bodies_and_rods.exe: ../../tests/bodies_and_rods.cpp libmoordyn2.dll
+	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_bodies_and_rods.exe ../../tests/bodies_and_rods.cpp
 
-test_wavekin.exe: ../../test/wavekin.cpp libmoordyn2.dll
-	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_wavekin.exe ../../test/wavekin.cpp
+test_wavekin.exe: ../../tests/wavekin.cpp libmoordyn2.dll
+	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_wavekin.exe ../../tests/wavekin.cpp
 
-test_quasi_static_chain.exe: ../../test/quasi_static_chain.cpp libmoordyn2.dll
-	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_quasi_static_chain.exe ../../test/quasi_static_chain.cpp
+test_quasi_static_chain.exe: ../../tests/quasi_static_chain.cpp libmoordyn2.dll
+	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_quasi_static_chain.exe ../../tests/quasi_static_chain.cpp
 
 test: test_minimal.exe test_bodies_and_rods.exe test_quasi_static_chain.exe
 	./test_minimal.exe
diff --git a/compile/DYLIB/makefile b/compile/DYLIB/makefile
index 432f91c9..2aac5186 100644
--- a/compile/DYLIB/makefile
+++ b/compile/DYLIB/makefile
@@ -27,7 +27,7 @@
 
 # Flags for compiling with clang (OSX default)
 LFLAGS = -shared -DOSX -DMoorDyn_EXPORTS -fPIC
-CFLAGS = -c -O3 -static -g -Wall -Wextra -DOSX -DMoorDyn_EXPORTS -fPIC
+CFLAGS = -c -O3 -static -g -Wall -Wextra -DOSX -DMoorDyn_EXPORTS -fPIC -I../../source/
 
 ifdef USEGL
 CFLAGS += -DUSEGL
@@ -37,103 +37,51 @@ endif
 CFLAGS += $(COPTS)
 LFLAGS += $(LOPTS)
 
-CPPFLAGS = $(CFLAGS) -std=c++14
+CPPFLAGS = $(CFLAGS) -std=c++17
 EXEFLAGS = -O3 -g -Wall -Wextra -DOSX $(EXEOPTS)
 
 CC = clang++
 CXX = clang++
 
-HEADERS = ../../source/Body.h \
-          ../../source/Connection.h \
-          ../../source/_kiss_fft_guts.h \
-          ../../source/kiss_fft.h \
-          ../../source/kiss_fftr.h \
-          ../../source/Line.h \
-          ../../source/MoorDyn2.h \
-          ../../source/MoorDynAPI.h \
-          ../../source/MoorDyn.h \
-          ../../source/Rod.h \
-          ../../source/Waves.h \
-		  ../../source/Seafloor.h \
-          ../../source/Body.hpp \
-          ../../source/Connection.hpp \
-          ../../source/IO.hpp \
-          ../../source/Line.hpp \
-          ../../source/Log.hpp \
-          ../../source/Misc.hpp \
-          ../../source/MoorDyn2.hpp \
-          ../../source/QSlines.hpp \
-          ../../source/Rod.hpp \
-          ../../source/State.hpp \
-          ../../source/Time.hpp \
-          ../../source/Waves.hpp \
-		  ../../source/Seafloor.hpp
+HEADERS = $(wildcard ../../source/*.hpp) \
+          $(wildcard ../../source/Util/*.hpp) \
+          $(wildcard ../../source/Waves/*.hpp) \
+          $(wildcard ../../source/*.h)
+SOURCES = $(wildcard ../../source/*.cpp) \
+          $(wildcard ../../source/Util/*.cpp) \
+          $(wildcard ../../source/Waves/*.cpp)
+OBJECTS = $(patsubst ../../source/%,%,$(patsubst %.cpp,%.o,$(SOURCES)))
+DIRGUARD = @mkdir -p $(@D)
 
 all: libmoordyn2.dylib
 
-libmoordyn2.dylib: MoorDyn.o MoorDyn2.o Line.o Connection.o Body.o Rod.o State.o Time.o Waves.o Seafloor.o Log.o IO.o Misc.o kiss_fft.o kiss_fftr.o
-	$(CXX) $(LFLAGS) -o libmoordyn2.dylib MoorDyn.o MoorDyn2.o Line.o Connection.o Body.o Rod.o State.o Time.o Waves.o Seafloor.o Log.o IO.o Misc.o kiss_fft.o kiss_fftr.o
+libmoordyn2.dylib: $(OBJECTS)
+	$(CXX) $(LFLAGS) -o libmoordyn2.dylib $(OBJECTS)
 
-MoorDyn.o: ../../source/MoorDyn.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/MoorDyn.cpp
-
-MoorDyn2.o: ../../source/MoorDyn2.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/MoorDyn2.cpp
-
-kiss_fft.o: ../../source/kiss_fft.cpp ../../source/kiss_fft.h ../../source/_kiss_fft_guts.h
-	$(CC) $(CFLAGS) ../../source/kiss_fft.cpp
-
-kiss_fftr.o: ../../source/kiss_fftr.cpp ../../source/kiss_fftr.h ../../source/_kiss_fft_guts.h
-	$(CC) $(CFLAGS) ../../source/kiss_fftr.cpp
-
-Line.o: ../../source/Line.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Line.cpp
-
-Connection.o: ../../source/Connection.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Connection.cpp
-
-Body.o: ../../source/Body.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Body.cpp
-
-Rod.o: ../../source/Rod.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Rod.cpp
-
-State.o: ../../source/State.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/State.cpp
-
-Time.o: ../../source/Time.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Time.cpp
-
-Waves.o: ../../source/Waves.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Waves.cpp
-
-Seafloor.o: ../../source/Seafloor.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Seafloor.cpp
-
-Log.o: ../../source/Log.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Log.cpp
-
-IO.o: ../../source/IO.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/IO.cpp
-
-Misc.o: ../../source/Misc.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Misc.cpp
+%.o: ../../source/%.cpp $(HEADERS)
+	${CXX} $(CPPFLAGS) -o $@ $<
+Util/%.o: ../../source/Util/%.cpp $(HEADERS)
+	$(DIRGUARD)
+	${CXX} $(CPPFLAGS) -o $@ $<
+Waves/%.o: ../../source/Waves/%.cpp $(HEADERS)
+	$(DIRGUARD)
+	${CXX} $(CPPFLAGS) -o $@ $<
 
 clean:
 	rm -f *.o *.dylib *.dylib.*
 	rm -f test_*
 
-test_minimal: ../../test/minimal.cpp libmoordyn2.dylib
-	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_minimal ../../test/minimal.cpp
+test_minimal: ../../tests/minimal.cpp libmoordyn2.dylib
+	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_minimal ../../tests/minimal.cpp
 
-test_bodies_and_rods: ../../test/bodies_and_rods.cpp libmoordyn2.dylib
-	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_bodies_and_rods ../../test/bodies_and_rods.cpp
+test_bodies_and_rods: ../../tests/bodies_and_rods.cpp libmoordyn2.dylib
+	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_bodies_and_rods ../../tests/bodies_and_rods.cpp
 
-test_wavekin: ../../test/wavekin.cpp libmoordyn2.dylib
-	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_wavekin ../../test/wavekin.cpp
+test_wavekin: ../../tests/wavekin.cpp libmoordyn2.dylib
+	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_wavekin ../../tests/wavekin.cpp
 
-test_quasi_static_chain: ../../test/quasi_static_chain.cpp libmoordyn2.dylib
-	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_quasi_static_chain ../../test/quasi_static_chain.cpp
+test_quasi_static_chain: ../../tests/quasi_static_chain.cpp libmoordyn2.dylib
+	$(CXX) $(EXEFLAGS) -L./ -lmoordyn2 -I../../source/ -o test_quasi_static_chain ../../tests/quasi_static_chain.cpp
 
 test: test_minimal test_bodies_and_rods test_quasi_static_chain
 	LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`/ ./test_minimal
diff --git a/compile/SO/makefile b/compile/SO/makefile
index 31908670..67390058 100644
--- a/compile/SO/makefile
+++ b/compile/SO/makefile
@@ -23,7 +23,7 @@
 
 
 LFLAGS = -shared -static-libgcc -static-libstdc++ -DLINUX -DMoorDyn_EXPORTS -fPIC
-CFLAGS = -c -O3 -g -Wall -Wextra -DLINUX -DMoorDyn_EXPORTS -fPIC
+CFLAGS = -c -O3 -g -Wall -Wextra -DLINUX -DMoorDyn_EXPORTS -fPIC -I../../source/
 
 ifdef USEGL
 CFLAGS += -DUSEGL
@@ -33,33 +33,17 @@ endif
 CFLAGS += $(COPTS)
 LFLAGS += $(LOPTS)
 
-CPPFLAGS = $(CFLAGS) -std=c++14
+CPPFLAGS = $(CFLAGS) -std=c++17
 EXEFLAGS = -O3 -g -Wall -Wextra -DLINUX $(EXEOPTS)
-HEADERS = ../../source/Body.h \
-          ../../source/Connection.h \
-          ../../source/_kiss_fft_guts.h \
-          ../../source/kiss_fft.h \
-          ../../source/kiss_fftr.h \
-          ../../source/Line.h \
-          ../../source/MoorDyn2.h \
-          ../../source/MoorDynAPI.h \
-          ../../source/MoorDyn.h \
-          ../../source/Rod.h \
-          ../../source/Waves.h \
-		  ../../source/Seafloor.h \
-          ../../source/Body.hpp \
-          ../../source/Connection.hpp \
-          ../../source/IO.hpp \
-          ../../source/Line.hpp \
-          ../../source/Log.hpp \
-          ../../source/Misc.hpp \
-          ../../source/MoorDyn2.hpp \
-          ../../source/QSlines.hpp \
-          ../../source/Rod.hpp \
-          ../../source/State.hpp \
-          ../../source/Time.hpp \
-          ../../source/Waves.hpp \
-		  ../../source/Seafloor.hpp
+HEADERS = $(wildcard ../../source/*.hpp) \
+          $(wildcard ../../source/Util/*.hpp) \
+          $(wildcard ../../source/Waves/*.hpp) \
+          $(wildcard ../../source/*.h)
+SOURCES = $(wildcard ../../source/*.cpp) \
+          $(wildcard ../../source/Util/*.cpp) \
+          $(wildcard ../../source/Waves/*.cpp)
+OBJECTS = $(patsubst ../../source/%,%,$(patsubst %.cpp,%.o,$(SOURCES)))
+DIRGUARD = @mkdir -p $(@D)
 
 all: libmoordyn.so
 
@@ -67,78 +51,42 @@ libmoordyn.so: libmoordyn.so.2.0.0
 	rm -f libmoordyn.so
 	ln -s libmoordyn.so.2.0.0 libmoordyn.so
 
-libmoordyn.so.2.0.0: MoorDyn.o MoorDyn2.o Line.o Connection.o Body.o Rod.o State.o Time.o Waves.o Seafloor.o Log.o IO.o Misc.o kiss_fft.o kiss_fftr.o
-	$(CXX) $(LFLAGS) -o libmoordyn.so.2.0.0 MoorDyn.o MoorDyn2.o Line.o Connection.o Body.o Rod.o State.o Time.o Waves.o Seafloor.o Log.o IO.o Misc.o kiss_fft.o kiss_fftr.o
+libmoordyn.so.2.0.0: $(OBJECTS)
+	$(CXX) $(LFLAGS) -o libmoordyn.so.2.0.0 $(OBJECTS)
 
-MoorDyn.o: ../../source/MoorDyn.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/MoorDyn.cpp
-
-MoorDyn2.o: ../../source/MoorDyn2.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/MoorDyn2.cpp
-
-kiss_fft.o: ../../source/kiss_fft.cpp ../../source/kiss_fft.h ../../source/_kiss_fft_guts.h
-	$(CC) $(CFLAGS) ../../source/kiss_fft.cpp
-
-kiss_fftr.o: ../../source/kiss_fftr.cpp ../../source/kiss_fftr.h ../../source/_kiss_fft_guts.h
-	$(CC) $(CFLAGS) ../../source/kiss_fftr.cpp
-
-Line.o: ../../source/Line.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Line.cpp
-
-Connection.o: ../../source/Connection.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Connection.cpp
-
-Body.o: ../../source/Body.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Body.cpp
-
-Rod.o: ../../source/Rod.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Rod.cpp
-
-State.o: ../../source/State.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/State.cpp
-
-Time.o: ../../source/Time.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Time.cpp
-
-Waves.o: ../../source/Waves.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Waves.cpp
-
-Seafloor.o: ../../source/Seafloor.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Seafloor.cpp
-
-Log.o: ../../source/Log.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Log.cpp
-
-IO.o: ../../source/IO.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/IO.cpp
-
-Misc.o: ../../source/Misc.cpp $(HEADERS)
-	$(CXX) $(CPPFLAGS) ../../source/Misc.cpp
+%.o: ../../source/%.cpp $(HEADERS)
+	${CXX} $(CPPFLAGS) -o $@ $<
+Util/%.o: ../../source/Util/%.cpp $(HEADERS)
+	$(DIRGUARD)
+	${CXX} $(CPPFLAGS) -o $@ $<
+Waves/%.o: ../../source/Waves/%.cpp $(HEADERS)
+	$(DIRGUARD)
+	${CXX} $(CPPFLAGS) -o $@ $<
 
 clean:
 	rm -f *.o *.so *.so.*
 	rm -f test_*
 
-test_minimal: ../../test/minimal.cpp libmoordyn.so
-	$(CXX) $(EXEFLAGS) -L./ -lmoordyn -I../../source/ -o test_minimal ../../test/minimal.cpp
+test_minimal: ../../tests/minimal.cpp libmoordyn.so
+	$(CXX) $(EXEFLAGS) -L./ -lmoordyn -I../../source/ -o test_minimal ../../tests/minimal.cpp
 
-test_bodies_and_rods: ../../test/bodies_and_rods.cpp libmoordyn.so
-	$(CXX) $(EXEFLAGS) -L./ -lmoordyn -I../../source/ -o test_bodies_and_rods ../../test/bodies_and_rods.cpp
+test_bodies_and_rods: ../../tests/bodies_and_rods.cpp libmoordyn.so
+	$(CXX) $(EXEFLAGS) -L./ -lmoordyn -I../../source/ -o test_bodies_and_rods ../../tests/bodies_and_rods.cpp
 
-test_wavekin: ../../test/wavekin.cpp libmoordyn.so
-	$(CXX) $(EXEFLAGS) -L./ -lmoordyn -I../../source/ -o test_wavekin ../../test/wavekin.cpp
+test_wavekin: ../../tests/wavekin.cpp libmoordyn.so
+	$(CXX) $(EXEFLAGS) -L./ -lmoordyn -I../../source/ -o test_wavekin ../../tests/wavekin.cpp
 
-test_quasi_static_chain: ../../test/quasi_static_chain.cpp libmoordyn.so
-	$(CXX) $(EXEFLAGS) -L./ -lmoordyn -I../../source/ -o test_quasi_static_chain ../../test/quasi_static_chain.cpp
+test_quasi_static_chain: ../../tests/quasi_static_chain.cpp libmoordyn.so
+	$(CXX) $(EXEFLAGS) -L./ -lmoordyn -I../../source/ -o test_quasi_static_chain ../../tests/quasi_static_chain.cpp
 
 test: test_minimal test_bodies_and_rods test_wavekin test_quasi_static_chain
-	cd ../../test/; \
+	cd ../../tests/; \
 	LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`/../compile/SO/ ../compile/SO/test_minimal
-	cd ../../test/; \
+	cd ../../tests/; \
 	LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`/../compile/SO/ ../compile/SO/test_bodies_and_rods
-	cd ../../test/; \
+	cd ../../tests/; \
 	LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`/../compile/SO/ ../compile/SO/test_wavekin
-	cd ../../test/; \
+	cd ../../tests/; \
 	LD_LIBRARY_PATH=$LD_LIBRARY_PATH:`pwd`/../compile/SO/ ../compile/SO/test_wavekin
 
 debug: CFLAGS += -O0 -g -DDEBUG=1
diff --git a/source/Body.cpp b/source/Body.cpp
index f665d43a..2148da7b 100644
--- a/source/Body.cpp
+++ b/source/Body.cpp
@@ -107,7 +107,7 @@ Body::setup(int number_in,
 	v6 = vec6::Zero();
 
 	// calculate orientation matrix based on latest angles
-	OrMat = RotXYZ(r6(Eigen::seqN(3, 3)));
+	OrMat = RotZYX(r6(Eigen::seqN(3, 3)).reverse());
 
 	LOGDBG << "Set up Body " << number << ", type " << TypeName(type) << ". "
 	       << endl;
@@ -360,7 +360,7 @@ Body::updateFairlead(real time)
 		v6 = rd_ves;
 
 		// calculate orientation matrix based on latest angles
-		OrMat = RotXYZ(r6(Eigen::seqN(3, 3)));
+		OrMat = RotZYX(r6(Eigen::seqN(3, 3)).reverse());
 
 		// set positions of any dependent connections and rods
 		setDependentStates();
@@ -379,7 +379,7 @@ Body::setState(vec6 pos, vec6 vel)
 	v6 = vel;
 
 	// calculate orientation matrix based on latest angles
-	OrMat = RotXYZ(r6[3], r6[4], r6[5]);
+	OrMat = RotZYX(r6[5], r6[4], r6[3]);
 
 	// set positions of any dependent connections and rods
 	setDependentStates();
diff --git a/source/Misc.hpp b/source/Misc.hpp
index cad2ca00..57afa4b1 100644
--- a/source/Misc.hpp
+++ b/source/Misc.hpp
@@ -623,8 +623,10 @@ inline mat
 getH(vec r)
 {
 	mat H;
-	H << 0, r[2], r[1], r[2], 0, r[0], r[1], r[0], 0;
-	return -H;
+	H <<     0,  r[2],  r[1],
+	     -r[2],     0,  r[0],
+	     -r[1], -r[0],     0;
+	return H;
 }
 
 /** @brief Compute the mass matrix on an offset point
@@ -725,27 +727,29 @@ RotZ(real rads)
 	return R;
 }
 
-/** @brief Rotation matrix around z axis
- * @param x The angle around x axis in radians
- * @param y The angle around y axis in radians
- * @param z The angle around z axis in radians
- * @return The rotation matrix
- */
-inline mat
-RotXYZ(real x, real y, real z)
-{
-	return RotZ(z) * RotY(y) * RotX(x);
+// Create the Euler rotations of the type RotXYZ, RotXZX, RotZYX...
+#define MAKE_EULER_ROT(a,b,c)                                                  \
+inline mat Rot ## a ## b ## c(real a1, real a2, real a3)                       \
+{                                                                              \
+	return Rot ## a (a1) * Rot ## b (a2) * Rot ## c (a3);                      \
+}                                                                              \
+inline mat Rot ## a ## b ## c(vec rads)                                        \
+{                                                                              \
+	return Rot ## a ## b ## c (rads[0], rads[1], rads[2]);                     \
 }
 
-/** @brief Euler XYZ rotation matrix
- * @param rads The angles in radians
- * @return The rotation matrix
- */
-inline mat
-RotXYZ(vec rads)
-{
-	return RotXYZ(rads[0], rads[1], rads[2]);
-}
+MAKE_EULER_ROT(X, Y, X)
+MAKE_EULER_ROT(X, Y, Z)
+MAKE_EULER_ROT(X, Z, X)
+MAKE_EULER_ROT(X, Z, Y)
+MAKE_EULER_ROT(Y, X, Y)
+MAKE_EULER_ROT(Y, X, Z)
+MAKE_EULER_ROT(Y, Z, X)
+MAKE_EULER_ROT(Y, Z, Y)
+MAKE_EULER_ROT(Z, X, Y)
+MAKE_EULER_ROT(Z, X, Z)
+MAKE_EULER_ROT(Z, Y, X)
+MAKE_EULER_ROT(Z, Y, Z)
 
 /** @brief Get the spherical angles for a vector
  * @param q The vector
diff --git a/source/MoorDyn2.cpp b/source/MoorDyn2.cpp
index 65b8b191..7fc7d743 100644
--- a/source/MoorDyn2.cpp
+++ b/source/MoorDyn2.cpp
@@ -279,6 +279,10 @@ moordyn::MoorDyn::Init(const double* x, const double* xd, bool skip_ic)
 	real t = 0;
 	bool converged = true;
 	real max_error = 0.0;
+	unsigned int max_error_line = 0;
+	real best_score = std::numeric_limits<real>::max();
+	real best_score_t = 0.0;
+	unsigned int best_score_line = 0;
 	while ((t < ICTmax) && (!skip_ic)) {
 		// Integrate one ICD timestep (ICdt)
 		real t_target = ICdt;
@@ -324,25 +328,22 @@ moordyn::MoorDyn::Init(const double* x, const double* xd, bool skip_ic)
 				for (unsigned int pt = 0; pt < convergence_iters; pt++) {
 					const real error =
 					    abs(FairTens[lf] / FairTensLast[lf][pt] - 1.0);
-					if (error > max_error)
+					if (error > max_error) {
 						max_error = error;
-					if (max_error > ICthresh) {
-						converged = false;
-						if ((_log->GetVerbosity() > MOORDYN_DBG_LEVEL) ||
-						    (_log->GetLogLevel() > MOORDYN_DBG_LEVEL)) {
-							// We are not reporting the error, so it is enough
-							// to know that the criteria convergence has not
-							// been met
-							break;
-						}
+						max_error_line = LineList[lf]->number;
 					}
 				}
-				if (!converged) {
-					LOGDBG << "Dynamic relaxation t = " << t << "s (time step "
-					       << iic << "), error = " << 100.0 * max_error
-					       << "%     \r";
-					break;
-				}
+			}
+			if (max_error < best_score) {
+				best_score = max_error;
+				best_score_t = t;
+				best_score_line = max_error_line;
+			}
+			if (max_error > ICthresh) {
+				converged = false;
+				LOGDBG << "Dynamic relaxation t = " << t << "s (time step "
+						<< iic << "), error = " << 100.0 * max_error
+						<< "% on line " << max_error_line << "     \r";
 			}
 
 			if (converged)
@@ -358,7 +359,12 @@ moordyn::MoorDyn::Init(const double* x, const double* xd, bool skip_ic)
 		LOGWRN << "Fairlead tensions did not converged" << endl;
 	}
 	LOGMSG << "Remaining error after " << t << " s = " << 100.0 * max_error
-	       << "%" << endl;
+	       << "% on line " << max_error_line << endl;
+	if (!converged) {
+		LOGMSG << "Best score at " << best_score_t << " s = "
+		       << 100.0 * best_score << "% on line " << best_score_line
+		       << endl;
+	}
 
 	// restore drag coefficients to normal values and restart time counter of
 	// each object
@@ -1797,6 +1803,12 @@ moordyn::MoorDyn::readOptionsLine(vector<string>& in_txt, int i)
 	// DT is old way, should phase out
 	if ((name == "dtM") || (name == "DT"))
 		dtM0 = atof(entries[0].c_str());
+	else if (name == "writeLog") {
+		// This was actually already did, so we do not need to do that again
+		// But we really want to have this if to avoid showing a warning for
+		// Unrecognized option writeLog
+		// env->writeLog = atoi(entries[0].c_str());
+	}
 	else if (name == "tScheme") {
 		moordyn::error_id err = MOORDYN_SUCCESS;
 		string err_msg;
diff --git a/source/Util/VTK_Util.cpp b/source/Util/VTK_Util.cpp
index 00666d97..4bb0ff8f 100644
--- a/source/Util/VTK_Util.cpp
+++ b/source/Util/VTK_Util.cpp
@@ -1,5 +1,7 @@
 #include "VTK_Util.hpp"
 
+#ifdef USE_VTK
+
 vtkSmartPointer<vtkFloatArray>
 vector_to_vtk_array(const char* name, const std::vector<double>& data)
 {
@@ -14,3 +16,5 @@ vector_to_vtk_array(const char* name, const std::vector<double>& data)
 	}
 	return a;
 }
+
+#endif
diff --git a/source/Waves/WaveGrid.hpp b/source/Waves/WaveGrid.hpp
index d9c879b4..47b45d21 100644
--- a/source/Waves/WaveGrid.hpp
+++ b/source/Waves/WaveGrid.hpp
@@ -1,7 +1,9 @@
 #pragma once
 
 #include "Log.hpp"
+#include "Misc.hpp"
 #include "WaveOptions.hpp"
+#include <memory>
 
 namespace moordyn {
 class WaveGrid;


Test patch:
diff --git a/tests/Mooring/RodPinnedFloating.txt b/tests/Mooring/RodPinnedFloating.txt
index e3f8d382..ceb23a5f 100644
--- a/tests/Mooring/RodPinnedFloating.txt
+++ b/tests/Mooring/RodPinnedFloating.txt
@@ -14,7 +14,7 @@ ID   RodType   Attachment  Xa    Ya    Za    Xb    Yb    Zb   NumSegs  RodOutput
 ---------------------- OPTIONS -------------------------------------------------
 2             writeLog             Write a log file
 1e-5          dtM                  time step to use in mooring integration (s)
-1000          WtrDnsity            water density (kg/m^3)
+1000          WtrDnsty             water density (kg/m^3)
 10            WtrDpth              water depth (m)
 0.25          dtIC                 time interval for analyzing convergence during IC gen (s)
 0.0           TmaxIC               max time for ic gen (s)
diff --git a/tests/rods.cpp b/tests/rods.cpp
index c8003615..a171d19d 100644
--- a/tests/rods.cpp
+++ b/tests/rods.cpp
@@ -208,8 +208,8 @@ hanging()
 int
 main(int, char**)
 {
-	// if (!pinned_floating())
-	// 	return 1;
+	if (!pinned_floating())
+		return 1;
 	if (!hanging())
 		return 2;
 	return 0;
diff --git a/tests/wavekin.cpp b/tests/wavekin.cpp
index 4a270455..b493d2a5 100644
--- a/tests/wavekin.cpp
+++ b/tests/wavekin.cpp
@@ -32,7 +32,6 @@
  * A simple driver program that will run MoorDyn VERSION 2 testing several
  * wave kinematics
  */
-#include "Config.h"
 #include "MoorDyn2.h"
 #include "MoorDyn2.hpp"
 #include "Waves.hpp"