25 #ifndef MIRTK_FreeFormTransformationRungeKutta_H    26 #define MIRTK_FreeFormTransformationRungeKutta_H    28 #include "mirtk/Math.h"    29 #include "mirtk/Matrix.h"    30 #include "mirtk/Vector3D.h"    31 #include "mirtk/TransformationJacobian.h"    53     dk(0, 0) = (Dv(0, 0) * dx(0, 0) + Dv(0, 1) * dx(1, 0) + Dv(0, 2) * dx(2, 0)) * h;
    54     dk(0, 1) = (Dv(0, 0) * dx(0, 1) + Dv(0, 1) * dx(1, 1) + Dv(0, 2) * dx(2, 1)) * h;
    55     dk(0, 2) = (Dv(0, 0) * dx(0, 2) + Dv(0, 1) * dx(1, 2) + Dv(0, 2) * dx(2, 2)) * h;
    56     dk(1, 0) = (Dv(1, 0) * dx(0, 0) + Dv(1, 1) * dx(1, 0) + Dv(1, 2) * dx(2, 0)) * h;
    57     dk(1, 1) = (Dv(1, 0) * dx(0, 1) + Dv(1, 1) * dx(1, 1) + Dv(1, 2) * dx(2, 1)) * h;
    58     dk(1, 2) = (Dv(1, 0) * dx(0, 2) + Dv(1, 1) * dx(1, 2) + Dv(1, 2) * dx(2, 2)) * h;
    59     dk(2, 0) = (Dv(2, 0) * dx(0, 0) + Dv(2, 1) * dx(1, 0) + Dv(2, 2) * dx(2, 0)) * h;
    60     dk(2, 1) = (Dv(2, 0) * dx(0, 1) + Dv(2, 1) * dx(1, 1) + Dv(2, 2) * dx(2, 1)) * h;
    61     dk(2, 2) = (Dv(2, 0) * dx(0, 2) + Dv(2, 1) * dx(1, 2) + Dv(2, 2) * dx(2, 2)) * h;
    68     dk(0, 0) = (Dv(0, 0) * dx(0, 0) + Dv(0, 1) * dx(1, 0) + Dv(0, 2) * dx(2, 0) + dv[0]) * h;
    69     dk(0, 1) = (Dv(0, 0) * dx(0, 1) + Dv(0, 1) * dx(1, 1) + Dv(0, 2) * dx(2, 1)        ) * h;
    70     dk(0, 2) = (Dv(0, 0) * dx(0, 2) + Dv(0, 1) * dx(1, 2) + Dv(0, 2) * dx(2, 2)        ) * h;
    71     dk(1, 0) = (Dv(1, 0) * dx(0, 0) + Dv(1, 1) * dx(1, 0) + Dv(1, 2) * dx(2, 0)        ) * h;
    72     dk(1, 1) = (Dv(1, 0) * dx(0, 1) + Dv(1, 1) * dx(1, 1) + Dv(1, 2) * dx(2, 1) + dv[1]) * h;
    73     dk(1, 2) = (Dv(1, 0) * dx(0, 2) + Dv(1, 1) * dx(1, 2) + Dv(1, 2) * dx(2, 2)        ) * h;
    74     dk(2, 0) = (Dv(2, 0) * dx(0, 0) + Dv(2, 1) * dx(1, 0) + Dv(2, 2) * dx(2, 0)        ) * h;
    75     dk(2, 1) = (Dv(2, 0) * dx(0, 1) + Dv(2, 1) * dx(1, 1) + Dv(2, 2) * dx(2, 1)        ) * h;
    76     dk(2, 2) = (Dv(2, 0) * dx(0, 2) + Dv(2, 1) * dx(1, 2) + Dv(2, 2) * dx(2, 2) + dv[2]) * h;
   101 template <
class TFreeFormTransformation, 
class TButcherTableau>
   108   typedef TButcherTableau 
BT; 
   111   static void Transform(
const TFreeFormTransformation *v,
   112                         double &x, 
double &y, 
double &z,
   113                         double t1, 
double t2, 
double dt)
   115     if (t1 == t2) 
return;
   118     const double     d = copysign(1.0, t2 - t1); 
   119     double           h = d * abs(dt);            
   125     while (d * t < d * t2) {
   127       if (d * (t + h) > d * t2) h = t2 - t;
   129       if (BT::fsal && t != t1) k[0] = k[BT::s - 1], i = 1;
   131       for (; i < BT::s; i++) {
   133         k[i].
_x = x, k[i].
_y = y, k[i].
_z = z;
   134         for (j = 0; j < i; j++) k[i] += k[j] * BT::a[i][j];
   135         v->WorldToLattice(k[i]._x, k[i]._y, k[i]._z);
   136         l = v->TimeToLattice(t + BT::c[i] * h);
   138         v->Evaluate(k[i]._x, k[i]._y, k[i]._z, l);
   142       for (i = 0; i < BT::s; i++) {
   143         x += k[i].
_x * BT::b[i];
   144         y += k[i].
_y * BT::b[i];
   145         z += k[i].
_z * BT::b[i];
   152   static void Jacobian(
const TFreeFormTransformation *v,
   154                        double &x, 
double &y, 
double &z,
   155                        double t1, 
double t2, 
double dt)
   157     if (t1 == t2) 
return;
   163     const double     d = copysign(1.0, t2 - t1); 
   164     double           h = d * abs(dt);            
   168     for (i = 0; i < BT::s; ++i) dk[i].Initialize(3, 3);
   172     while (d * t < d * t2) {
   174       if (d * (t + h) > d * t2) h = t2 - t;
   176       if (BT::fsal && t != t1) {
   183       for (; i < BT::s; i++) {
   185         k[i].
_x = x, k[i].
_y = y, k[i].
_z = z;
   186         for (j = 0; j < i; j++) k[i] += k[j] * BT::a[i][j];
   187         v->WorldToLattice(k[i]._x, k[i]._y, k[i]._z);
   188         l = v->TimeToLattice(t + BT::c[i] * h);
   190         v->EvaluateJacobianWorld(Dv, k[i]._x, k[i]._y, k[i]._z, l);
   192         v->Evaluate(k[i]._x, k[i]._y, k[i]._z, l);
   196         for (j = 0; j < i; j++) dx += dk[j] * BT::a[i][j];
   197         dkdx(dk[i], Dv, dx, h); 
   201       for (i = 0; i < BT::s; i++) {
   202         x  +=  k[i].
_x * BT::b[i];
   203         y  +=  k[i].
_y * BT::b[i];
   204         z  +=  k[i].
_z * BT::b[i];
   205         dx += dk[i]    * BT::b[i];
   213   static void JacobianDOFs(
const TFreeFormTransformation *v,
   214                            Matrix &jac, 
int ci, 
int cj, 
int ck, 
int cl,
   215                            double &x, 
double &y, 
double &z,
   216                            double t1, 
double t2, 
double dt)
   218     if (t1 == t2) 
return;
   225     const double     d = copysign(1.0, t2 - t1); 
   226     double           h = d * abs(dt);            
   230     for (i = 0; i < BT::s; i++) dk[i].Initialize(3, 3);
   234     while (d * t < d * t2) {
   236       if (d * (t + h) > d * t2) h = t2 - t;
   238       if (BT::fsal && t != t1) {
   245       for (; i < BT::s; i++) {
   247         k[i].
_x = x, k[i].
_y = y, k[i].
_z = z;
   248         for (j = 0; j < i; j++) k[i] += k[j] * BT::a[i][j];
   249         v->WorldToLattice(k[i]._x, k[i]._y, k[i]._z);
   250         l = v->TimeToLattice(t + BT::c[i] * h);
   252         v->EvaluateJacobianWorld(Dv,                 k[i]._x, k[i]._y, k[i]._z, l);
   253         v->EvaluateJacobianDOFs (dv, ci, cj, ck, cl, k[i]._x, k[i]._y, k[i]._z, l);
   255         v->Evaluate(k[i]._x, k[i]._y, k[i]._z, l);
   259         for (j = 0; j < i; j++) dx += dk[j] * BT::a[i][j];
   261         dkdp(dk[i], Dv, dx, dv, h); 
   264       for (i = 0; i < BT::s; i++) {
   265         x   +=  k[i].
_x * BT::b[i];
   266         y   +=  k[i].
_y * BT::b[i];
   267         z   +=  k[i].
_z * BT::b[i];
   268         jac += dk[i]    * BT::b[i];
   275   static void JacobianDOFs(
const TFreeFormTransformation *v,
   277                            double &x, 
double &y, 
double &z,
   278                            double t1, 
double t2, 
double dt)
   280     if (t1 == t2) 
return;
   288     const double           d = copysign(1.0, t2 - t1); 
   289     double                 h = d * abs(dt);            
   295     while (d * t < d * t2) {
   297       if (d * (t + h) > d * t2) h = t2 - t;
   299       if (BT::fsal && t != t1) {
   300         k [0] = k [BT::s - 1];
   301         dk[0] = dk[BT::s - 1];
   306       for (; i < BT::s; i++) {
   308         k[i].
_x = x, k[i].
_y = y, k[i].
_z = z;
   309         for (j = 0; j < i; j++) k[i] += k[j] * BT::a[i][j];
   310         v->WorldToLattice(k[i]._x, k[i]._y, k[i]._z);
   311         l = v->TimeToLattice(t + BT::c[i] * h);
   313         v->EvaluateJacobianWorld(Dv,           k[i]._x, k[i]._y, k[i]._z, l);
   314         v->EvaluateJacobianDOFs (dk[i], k[i]._x, k[i]._y, k[i]._z, l);
   316         v->Evaluate(k[i]._x, k[i]._y, k[i]._z, l);
   320         for (j = 0; j < i; j++) dx.
add(dk[j], BT::a[i][j]);
   327       for (i = 0; i < BT::s; i++) {
   328         x += k[i].
_x * BT::b[i];
   329         y += k[i].
_y * BT::b[i];
   330         z += k[i].
_z * BT::b[i];
   331         jac.
add(dk[i], BT::b[i]);
   359 template <
class TFreeFormTransformation, 
class TButcherTableau>
   366   typedef TButcherTableau 
BT; 
   369   static void Transform(
const TFreeFormTransformation *v,
   370                         double &x, 
double &y, 
double &z,
   371                         double t1, 
double t2, 
double mindt, 
double maxdt, 
double tol)
   373     if (t1 == t2) 
return;
   381     const double     d = copysign(1.0, h);            
   382     const double     e = 1.0 / 
static_cast<double>(BT::p); 
   387     if (abs(h) > maxdt) h = copysign(maxdt, d);
   391     while (d * t < d * t2) {
   393       if (d * (t + h) > d * t2) h = t2 - t;
   395       if (BT::fsal && t != t1) k[0] = k[BT::s - 1], i = 1;
   397       for (; i < BT::s; i++) {
   398         k[i].
_x = x, k[i].
_y = y, k[i].
_z = z;
   399         for (j = 0; j < i; j++) k[i] += k[j] * BT::a[i][j];
   400         v->WorldToLattice(k[i]._x, k[i]._y, k[i]._z);
   401         l = v->TimeToLattice(t + BT::c[i] * h);
   402         v->Evaluate(k[i]._x, k[i]._y, k[i]._z, l);
   406       next.
_x = x, next.
_y = y, next.
_z = z;
   407       for (i = 0; i < BT::s; i++) next += k[i] * BT::b[1][i];
   411         tmp.
_x = x, tmp.
_y = y, tmp.
_z = z;
   412         for (i = 0; i < BT::s; i++) tmp += k[i] * BT::b[0][i];
   414         error = max(max(abs(next.
_x - tmp.
_x),
   415                                   abs(next.
_y - tmp.
_y)),
   416                                   abs(next.
_z - tmp.
_z));
   418         if (abs(h) > mindt && error > tol) {
   420           h *= 0.8 * pow(tol / error, e);
   421           if (abs(h) < mindt) h = copysign(mindt, d);
   426           hnext = 0.8 * pow(tol / error, e) * h;
   427           if      (abs(hnext) < mindt) hnext = copysign(mindt, d);
   428           else if (abs(hnext) > maxdt) hnext = copysign(maxdt, d);
   444   static void Jacobian(
const TFreeFormTransformation *v,
   445                        Matrix &jac, 
double &x, 
double &y, 
double &z,
   446                        double t1, 
double t2, 
double mindt, 
double maxdt, 
double tol)
   448     if (t1 == t2) 
return;
   456     const double     d = copysign(1.0, h);            
   460     const double     e = 1.0 / 
static_cast<double>(BT::p); 
   464     for (i = 0; i < BT::s; i++) dk[i].Initialize(3, 3);
   467     if (abs(h) > maxdt) h = copysign(maxdt, d);
   471     while (d * t < d * t2) {
   473       if (d * (t + h) > d * t2) h = t2 - t;
   475       if (BT::fsal && t != t1) {
   482       for (; i < BT::s; i++) {
   484         k[i].
_x = x, k[i].
_y = y, k[i].
_z = z;
   485         for (j = 0; j < i; j++) k[i] += k[j] * BT::a[i][j];
   486         v->WorldToLattice(k[i]._x, k[i]._y, k[i]._z);
   487         l = v->TimeToLattice(t + BT::c[i] * h);
   489         v->EvaluateJacobianWorld(Dv, k[i]._x, k[i]._y, k[i]._z, l);
   491         v->Evaluate(k[i]._x, k[i]._y, k[i]._z, l);
   495         for (j = 0; j < i; j++) dx += dk[j] * BT::a[i][j];
   497         dkdx(dk[i], Dv, dx, h); 
   500       next.
_x = x, next.
_y = y, next.
_z = z;
   501       for (i = 0; i < BT::s; i++) next += k[i] * BT::b[1][i];
   505         tmp.
_x = x, tmp.
_y = y, tmp.
_z = z;
   506         for (i = 0; i < BT::s; i++) tmp += k[i] * BT::b[0][i];
   508         error = max(max(abs(next.
_x - tmp.
_x),
   509                                   abs(next.
_y - tmp.
_y)),
   510                                   abs(next.
_z - tmp.
_z));
   512         if (abs(h) > mindt && error > tol) {
   514           h *= 0.8 * pow(tol / error, e);
   515           if (abs(h) < mindt) h = copysign(mindt, d);
   520           hnext = 0.8 * pow(tol / error, e) * h;
   521           if      (abs(hnext) < mindt) hnext = copysign(mindt, d);
   522           else if (abs(hnext) > maxdt) hnext = copysign(maxdt, d);
   529       for (i = 0; i < BT::s; i++) dx += dk[i] * BT::b[1][i];
   542   static void JacobianDOFs(
const TFreeFormTransformation *v,
   543                            Matrix &jac, 
int ci, 
int cj, 
int ck, 
int cl,
   544                            double &x, 
double &y, 
double &z, 
double t1, 
double t2,
   545                            double mindt, 
double maxdt, 
double tol)
   547     if (t1 == t2) 
return;
   556     const double     d = copysign(1.0, h);            
   560     const double     e = 1.0 / 
static_cast<double>(BT::p); 
   564     for (i = 0; i < BT::s; i++) dk[i].Initialize(3, 3);
   567     if (abs(h) > maxdt) h = copysign(maxdt, d);
   571     while (d * t < d * t2) {
   573       if (d * (t + h) > d * t2) h = t2 - t;
   575       if (BT::fsal && t != t1) {
   582       for (; i < BT::s; i++) {
   584         k[i].
_x = x, k[i].
_y = y, k[i].
_z = z;
   585         for (j = 0; j < i; j++) k[i] += k[j] * BT::a[i][j];
   586         v->WorldToLattice(k[i]._x, k[i]._y, k[i]._z);
   587         l = v->TimeToLattice(t + BT::c[i] * h);
   589         v->EvaluateJacobianWorld(Dv,                 k[i]._x, k[i]._y, k[i]._z, l);
   590         v->EvaluateJacobianDOFs (dv, ci, cj, ck, cl, k[i]._x, k[i]._y, k[i]._z, l);
   592         v->Evaluate(k[i]._x, k[i]._y, k[i]._z, l);
   596         for (j = 0; j < i; j++) dx += dk[j] * BT::a[i][j];
   598         dkdp(dk[i], Dv, dx, dv, h); 
   601       next.
_x = x, next.
_y = y, next.
_z = z;
   602       for (i = 0; i < BT::s; i++) next += k[i] * BT::b[1][i];
   606         tmp.
_x = x, tmp.
_y = y, tmp.
_z = z;
   607         for (i = 0; i < BT::s; i++) tmp += k[i] * BT::b[0][i];
   609         error = max(max(abs(next.
_x - tmp.
_x),
   610                                   abs(next.
_y - tmp.
_y)),
   611                                   abs(next.
_z - tmp.
_z));
   613         if (abs(h) > mindt && error > tol) {
   615           h *= 0.8 * pow(tol / error, e);
   616           if (abs(h) < mindt) h = copysign(mindt, d);
   621           hnext = 0.8 * pow(tol / error, e) * h;
   622           if      (abs(hnext) < mindt) hnext = copysign(mindt, d);
   623           else if (abs(hnext) > maxdt) hnext = copysign(maxdt, d);
   629       for (i = 0; i < BT::s; i++) jac += dk[i] * BT::b[1][i];
   641   static void JacobianDOFs(
const TFreeFormTransformation *v,
   643                            double &x, 
double &y, 
double &z,
   644                            double t1, 
double t2, 
double mindt, 
double maxdt, 
double tol)
   646     if (t1 == t2) 
return;
   655     const double           d = copysign(1.0, h);       
   660     const double           e = 1.0 / double(BT::p);    
   665     if (abs(h) > maxdt) h = copysign(maxdt, d);
   669     while (d * t < d * t2) {
   671       if (d * (t + h) > d * t2) h = t2 - t;
   673       if (BT::fsal && t != t1) {
   680       for (; i < BT::s; i++) {
   682         k[i].
_x = x, k[i].
_y = y, k[i].
_z = z;
   683         for (j = 0; j < i; j++) k[i] += k[j] * BT::a[i][j];
   684         v->WorldToLattice(k[i]._x, k[i]._y, k[i]._z);
   685         l = v->TimeToLattice(t + BT::c[i] * h);
   687         v->EvaluateJacobianWorld(Dv,           k[i]._x, k[i]._y, k[i]._z, l);
   688         v->EvaluateJacobianDOFs (dk[i], k[i]._x, k[i]._y, k[i]._z, l);
   690         v->Evaluate(k[i]._x, k[i]._y, k[i]._z, l);
   694         for (j = 0; j < i; j++) dx.
add(dk[j], BT::a[i][j]);
   701       next.
_x = x, next.
_y = y, next.
_z = z;
   702       for (i = 0; i < BT::s; i++) next += k[i] * BT::b[1][i];
   706         tmp.
_x = x, tmp.
_y = y, tmp.
_z = z;
   707         for (i = 0; i < BT::s; i++) tmp += k[i] * BT::b[0][i];
   709         error = max(max(abs(next.
_x - tmp.
_x),
   710                                   abs(next.
_y - tmp.
_y)),
   711                                   abs(next.
_z - tmp.
_z));
   713         if (abs(h) > mindt && error > tol) {
   715           h *= 0.8 * pow(tol / error, e);
   716           if (abs(h) < mindt) h = copysign(mindt, d);
   721           hnext = 0.8 * pow(tol / error, e) * h;
   722           if      (abs(hnext) < mindt) hnext = copysign(mindt, d);
   723           else if (abs(hnext) > maxdt) hnext = copysign(maxdt, d);
   729       for (i = 0; i < BT::s; i++) jac.
add(dk[i], BT::b[1][i]);
   748 #define MIRTK_DECLARE_FFDRK_EXPLICIT(NAME, S)                                  \   749   struct FreeFormTransformationButcherTableau##NAME                            \   751     static const int    s = S;                                                 \   752     static const int    p;                                                     \   753     static const bool   fsal;                                                  \   754     static const double a[S][S];                                               \   755     static const double b[S];                                                  \   756     static const double c[S];                                                  \   759   template <class TFreeFormTransformation>                                     \   760   class FreeFormTransformationIntegration##NAME                                \   761     : public mirtk::FreeFormTransformationExplicitRungeKutta                   \   762              <TFreeFormTransformation, FreeFormTransformationButcherTableau##NAME> \   767 #define MIRTK_DECLARE_FFDRK_EMBEDDED(NAME, S)                                  \   768   struct FreeFormTransformationButcherTableau##NAME                            \   770     static const int    s = S;                                                 \   771     static const int    p;                                                     \   772     static const bool   fsal;                                                  \   773     static const double a[S][S];                                               \   774     static const double b[2][S];                                               \   775     static const double c[S];                                                  \   778   template <class TFreeFormTransformation>                                     \   779   class FreeFormTransformationIntegration##NAME                                \   780     : public mirtk::FreeFormTransformationEmbeddedRungeKutta                   \   781              <TFreeFormTransformation, FreeFormTransformationButcherTableau##NAME> \   786 #define MIRTK_DEFINE_FFDRK_EXPLICIT(NAME, S, P, FSAL, C, A, B)                 \   788   const int    FreeFormTransformationButcherTableau##NAME::p       = P;        \   789   const bool   FreeFormTransformationButcherTableau##NAME::fsal    = FSAL;     \   790   const double FreeFormTransformationButcherTableau##NAME::a[S][S] = A;        \   791   const double FreeFormTransformationButcherTableau##NAME::b[S]    = B;        \   792   const double FreeFormTransformationButcherTableau##NAME::c[S]    = C   796 #define MIRTK_DEFINE_FFDRK_EMBEDDED(NAME, S, P, FSAL, C, A, BY, BZ)            \   798   const int    FreeFormTransformationButcherTableau##NAME::p       = P;        \   799   const bool   FreeFormTransformationButcherTableau##NAME::fsal    = FSAL;     \   800   const double FreeFormTransformationButcherTableau##NAME::a[S][S] = A;        \   801   const double FreeFormTransformationButcherTableau##NAME::b[2][S] = {BY, BZ}; \   802   const double FreeFormTransformationButcherTableau##NAME::c[S]    = C   810 MIRTK_DECLARE_FFDRK_EXPLICIT(RKE1,   1); 
   811 MIRTK_DECLARE_FFDRK_EMBEDDED(RKEH12, 2); 
   812 MIRTK_DECLARE_FFDRK_EXPLICIT(RKE2,   2); 
   813 MIRTK_DECLARE_FFDRK_EXPLICIT(RKH2,   2); 
   814 MIRTK_DECLARE_FFDRK_EMBEDDED(RKBS23, 4); 
   815 MIRTK_DECLARE_FFDRK_EXPLICIT(RK4,    4); 
   816 MIRTK_DECLARE_FFDRK_EMBEDDED(RKF45,  6); 
   817 MIRTK_DECLARE_FFDRK_EMBEDDED(RKCK45, 6); 
   818 MIRTK_DECLARE_FFDRK_EMBEDDED(RKDP45, 7); 
   823 #endif // MIRTK_FreeFormTransformationRungeKutta_H 
Matrix & Ident()
Set to identity matrix. 
void Transform(Array< T > &values, UnaryOperation op)
Apply unary operation for each array element in-place.