FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
CableSegmentDragJacobian.h
1#ifndef CABLE_SEGMENT_DRAG_JACOBIAN_H
2#define CABLE_SEGMENT_DRAG_JACOBIAN_H
3
4#include <cmath>
5
23inline void AddCableSegmentDragJacobian(const double* pk, const double* pl, const double* vk, const double* current,
24 double factor, double crossCoef, double alongCoef, double* dF_dpk, double* dF_dpl, double* dF_dvk)
25{
26 const double d[3] = {pl[0] - pk[0], pl[1] - pk[1], pl[2] - pk[2]};
27 const double w[3] = {vk[0] - current[0], vk[1] - current[1], vk[2] - current[2]};
28 const double L = std::sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
29 const double W = std::sqrt(w[0] * w[0] + w[1] * w[1] + w[2] * w[2]);
30 if (L < 1e-10 || W <= 0.0)
31 return; // degenerate segment, or no relative flow: the derivatives vanish
32
33 const double Q[3] = {d[0] / L, d[1] / L, d[2] / L};
34 const double q = w[0] * Q[0] + w[1] * Q[1] + w[2] * Q[2];
35 const double extraAlong = alongCoef - crossCoef;
36
37 // F = -factor * W * inner, inner = crossCoef * L * w + extraAlong * q * L * Q
38 for (int j = 0; j < 3; ++j) {
39 const double inner = crossCoef * L * w[j] + extraAlong * q * L * Q[j];
40 for (int k = 0; k < 3; ++k) {
41 const double delta = (j == k) ? 1.0 : 0.0;
42 // dW/dw = w / W; d(inner)/dw = L * (crossCoef * I + extraAlong * Q Q^T)
43 const double dInner_dw = L * (crossCoef * delta + extraAlong * Q[j] * Q[k]);
44 const double dF_dw = -factor * (inner * w[k] / W + W * dInner_dw);
45 // d(L w)/dd = w Q^T; d(q L Q)/dd = d((w.d) d / L)/dd = Q w^T + q (I - Q Q^T)
46 const double dInner_dd = crossCoef * w[j] * Q[k] + extraAlong * (Q[j] * w[k] + q * (delta - Q[j] * Q[k]));
47 const double dF_dd = -factor * W * dInner_dd;
48
49 dF_dvk[j * 3 + k] += dF_dw;
50 dF_dpl[j * 3 + k] += dF_dd;
51 dF_dpk[j * 3 + k] -= dF_dd;
52 }
53 }
54}
55
56#endif