From 36f25f99b394bfa0e9afab9e390077646726a3a3 Mon Sep 17 00:00:00 2001
From: Richard Comblen <richard.comblen@uclouvain.be>
Date: Wed, 17 Feb 2010 08:09:35 +0000
Subject: [PATCH] Added many explicit Runge-Kutta

---
 Solver/dgLimiter.cpp    |   2 +-
 Solver/dgLimiter.h      |   2 +-
 Solver/dgRungeKutta.cpp | 153 ++++++++++++++++++++++++++++++++++++++--
 Solver/dgRungeKutta.h   |   7 +-
 4 files changed, 157 insertions(+), 7 deletions(-)

diff --git a/Solver/dgLimiter.cpp b/Solver/dgLimiter.cpp
index 518674751d..45c7b55e99 100644
--- a/Solver/dgLimiter.cpp
+++ b/Solver/dgLimiter.cpp
@@ -132,7 +132,7 @@ void dgLimiter::registerBindings(binding *b) {
   cm->setDescription("apply the limiter on the solution");
 }
 
-void dgSlopeLimiter::registerBindings(binding *b) {
+void dgSlopeLimiterRegisterBindings(binding *b) {
   classBinding *cb = b->addClass<dgSlopeLimiter>("dgSlopeLimiter");
   cb->setDescription("The usual DG slope limiter: keep the mean, reduces uniformly the slope until it does not overshoot the neighbors' mean");
   methodBinding *cm;
diff --git a/Solver/dgLimiter.h b/Solver/dgLimiter.h
index 5e4072beae..d8630beb45 100644
--- a/Solver/dgLimiter.h
+++ b/Solver/dgLimiter.h
@@ -21,7 +21,7 @@ class dgSlopeLimiter : public dgLimiter{
 public :
   dgSlopeLimiter (dgConservationLaw *claw) : dgLimiter (claw) {}
   virtual int apply ( dgDofContainer *solution);
-  static void registerBindings(binding *b);
 };
+void dgSlopeLimiterRegisterBindings(binding *b);
 
 #endif
diff --git a/Solver/dgRungeKutta.cpp b/Solver/dgRungeKutta.cpp
index ba3572a990..3480c5f5cc 100644
--- a/Solver/dgRungeKutta.cpp
+++ b/Solver/dgRungeKutta.cpp
@@ -11,18 +11,87 @@ double dgRungeKutta::iterateEuler(const dgConservationLaw *claw, double dt, dgDo
   return diagonalRK(claw, dt, solution, 1, A, b);
 }
 
+double dgRungeKutta::iterate22(const dgConservationLaw *claw, double dt, dgDofContainer *solution) {
+  double A[] = {0, 1};
+  double b[] = {1./2, 1./2};
+  return diagonalRK(claw, dt, solution, 2, A, b);
+}
+double dgRungeKutta::iterate33(const dgConservationLaw *claw, double dt, dgDofContainer *solution) {
+  double A[] = {0, 1./3, 2./3};
+  double b[] = {1./4,0, 3./4};
+  return diagonalRK(claw, dt, solution, 3, A, b);
+}
 double dgRungeKutta::iterate44(const dgConservationLaw *claw, double dt, dgDofContainer *solution) {
   double A[] = {0, 0.5, 0.5, 1};
   double b[] = {1./6, 1./3, 1./3, 1./6};
   return diagonalRK(claw, dt, solution, 4, A, b);
 }
 
-double dgRungeKutta::iterate22(const dgConservationLaw *claw, double dt, dgDofContainer *solution) {
-  double A[] = {0, 1};
-  double b[] = {1./2, 1./2};
-  return diagonalRK(claw, dt, solution, 2, A, b);
+
+double dgRungeKutta::iterate44ThreeEight(const dgConservationLaw *claw, double dt, dgDofContainer *solution) {
+  // 3/8 RK44
+  double A[4][4]={
+     {0, 0, 0, 0},
+     {1.0/3.0, 0, 0 ,0},
+     {-1.0/3.0, 1.0, 0, 0},
+     {1, -1, 1, 0}
+  };
+  fullMatrix<double> Afm(4,4);
+  for(int i=0;i<4;i++){
+    for(int j=0;j<4;j++){
+      Afm(i,j)=A[i][j];
+    }
+  }
+  double b[4]={1.0/8.0, 3.0/8.0, 3.0/8.0, 1.0/8.0};
+  double c[4]={0, 1.0/3.0, 2.0/3.0, 1};
+  return nonDiagonalRK(claw, dt, solution, 4, Afm, b, c);
 }
 
+double dgRungeKutta::iterateRKFehlberg45(const dgConservationLaw *claw, double dt, dgDofContainer *solution){
+  double A[6][6]={
+    {0,0,0,0,0,0},
+    {1.0/4,0,0,0,0,0},
+    {3.0/32,9.0/32,0,0,0,0},
+    {1932.0/2197,-7200.0/2197,7296.0/2197,0,0,0},
+    {439.0/216,-8,3680.0/513,-845.0/4104,0,0},
+    {8.0/27,2,-3544.0/2565,-1859.0/4104,-11.0/40,0},
+  };
+  double c[6];
+  fullMatrix<double> Afm(6,6);
+  for(int i=0;i<6;i++){
+    c[i]=0;
+    for(int j=0;j<6;j++){
+      Afm(i,j)=A[i][j];
+      c[i]+=A[i][j];
+    }
+  }
+  double b[6]={16.0/235,6656.0/12825,28561.0/56430,-9.0/50,2.0/55};
+  return nonDiagonalRK(claw, dt, solution, 6, Afm, b, c);
+}
+
+
+double dgRungeKutta::iterate43SchlegelJCAM2009(const dgConservationLaw *claw, double dt, dgDofContainer *solution) {
+  // RK43 from Schlegel et al. JCAM 2009
+  double A[4][4]={
+     {0, 0, 0, 0},
+     {1.0/2.0, 0, 0 ,0},
+     {-1.0/6.0, 2.0/3.0, 0, 0},
+     {1.0/3.0, -1.0/3.0, 1, 0}
+  };
+  fullMatrix<double> Afm(4,4);
+  for(int i=0;i<4;i++){
+    for(int j=0;j<4;j++){
+      Afm(i,j)=A[i][j];
+    }
+  }
+  double b[4]={1.0/6.0, 1.0/3.0, 1.0/3.0, 1.0/6.0};
+  double c[4]={0, 1.0/2.0, 1.0/2.0, 1};
+  return nonDiagonalRK(claw, dt, solution, 4, Afm, b, c);
+}
+
+
+
+
 double dgRungeKutta::diagonalRK (const dgConservationLaw *claw,
 			      double dt,				         // time-step
 			      dgDofContainer *sol,
@@ -70,6 +139,70 @@ double dgRungeKutta::diagonalRK (const dgConservationLaw *claw,
   return sol->norm();
 }
 
+
+
+double dgRungeKutta::nonDiagonalRK(const dgConservationLaw *claw,
+  double dt, 
+  dgDofContainer *solution, 
+  int nStages, 
+  fullMatrix<double>&A, //                                     c | A
+  double *b, // Standard Butcher tableau notation :___|__
+  double *c  //                                       |b^T  
+  )
+{
+  dgGroupCollection *groups=solution->getGroups();
+  fullMatrix<double> residuEl, KEl;
+  fullMatrix<double> iMassEl;
+
+  int nbFields = claw->getNbFields();
+
+  dgDofContainer **K;
+  K=new dgDofContainer*[nStages];
+  for(int i=0;i<nStages;i++){
+    K[i]=new dgDofContainer(groups,nbFields);
+    K[i]->scale(0.);
+  }
+  dgDofContainer Unp (groups,nbFields);
+  dgDofContainer tmp (groups,nbFields);
+  dgDofContainer resd(groups,nbFields);
+
+  Unp.scale(0.0);
+  Unp.axpy(*solution);
+  for(int i=0; i<nStages;i++){
+    tmp.scale(0.0);
+    tmp.axpy(*solution);
+    for(int j=0;j<i;j++){
+      if(fabs(A(i,j))>1e-12){
+        tmp.axpy(*K[j],dt*A(i,j));
+      }
+    }
+    if (_limiter) _limiter->apply(&tmp);
+    dgAlgorithm::residual(*claw,*groups,tmp,resd);
+
+    // Multiply the spatial residual by the inverse of the mass matrix
+    for(int k=0; k < groups->getNbElementGroups(); k++) {
+      dgGroupOfElements *group = groups->getElementGroup(k);
+      int nbNodes = group->getNbNodes();
+      for(int j=0;j<group->getNbElements();j++) {
+        residuEl.setAsProxy(resd.getGroupProxy(k),j*nbFields,nbFields);
+        KEl.setAsProxy(K[i]->getGroupProxy(k),j*nbFields,nbFields);
+        iMassEl.setAsProxy(group->getInverseMassMatrix(),j*nbNodes,nbNodes);
+        iMassEl.mult(residuEl,KEl);
+      }
+    }
+    Unp.axpy(*K[i],dt*b[i]);
+  }
+  if (_limiter) _limiter->apply(&Unp);
+  solution->scale(0.);
+  solution->axpy(Unp);
+
+  for(int i=0;i<nStages;i++){
+    delete K[i];
+  }
+  delete []K;
+  return solution->norm();
+}
+
 dgRungeKutta::dgRungeKutta():_limiter(NULL) {}
 
 
@@ -87,9 +220,21 @@ void dgRungeKutta::registerBindings(binding *b) {
   cm = cb->addMethod("iterate22",&dgRungeKutta::iterate22);
   cm->setArgNames("law","dt","solution",NULL);
   cm->setDescription("update solution by doing Heun second order runge-kutta step of time step dt for the conservation law");
+  cm = cb->addMethod("iterate33",&dgRungeKutta::iterate33);
+  cm->setArgNames("law","dt","solution",NULL);
+  cm->setDescription("update solution by doing classical third order runge-kutta step of time step dt for the conservation law");
   cm = cb->addMethod("iterate44",&dgRungeKutta::iterate44);
   cm->setArgNames("law","dt","solution",NULL);
   cm->setDescription("update solution by doing classical fourth order runge-kutta step of time step dt for the conservation law");
+  cm = cb->addMethod("iterate44ThreeEight",&dgRungeKutta::iterate44ThreeEight);
+  cm->setArgNames("law","dt","solution",NULL);
+  cm->setDescription("update solution by doing a fourth order runge-kutta (3/8 rule, not the classical one, see Hairer & Wanner book) step of time step dt for the conservation law");
+  cm = cb->addMethod("iterate43SchlegelJCAM2009",&dgRungeKutta::iterate43SchlegelJCAM2009);
+  cm->setArgNames("law","dt","solution",NULL);
+  cm->setDescription("update solution by doing a four stage third order runge-kutta (from Schlegel et al. Journal of Computational and Applied Mathematics, 2009) step of time step dt for the conservation law");
+  cm = cb->addMethod("iterateRKFehlberg45",&dgRungeKutta::iterateRKFehlberg45);
+  cm->setArgNames("law","dt","solution",NULL);
+  cm->setDescription("update solution by doing a six stage fifth order Runge-Kutta-Fehlberg step of time step dt for the conservation law");
   cm = cb->addMethod("setLimiter",&dgRungeKutta::setLimiter);
   cm->setArgNames("limiter",NULL);
   cm->setDescription("if a limiter is set, it is applied after each RK stage");
diff --git a/Solver/dgRungeKutta.h b/Solver/dgRungeKutta.h
index c4a2495dc9..09a19cd2a9 100644
--- a/Solver/dgRungeKutta.h
+++ b/Solver/dgRungeKutta.h
@@ -4,15 +4,20 @@ class dgConservationLaw;
 class dgDofContainer;
 class dgLimiter;
 class binding;
+#include "fullMatrix.h"
 class dgRungeKutta {
   double diagonalRK(const dgConservationLaw *claw, double dt, dgDofContainer *solution, int nStages, double *A, double *b); // c == A
-  //static double nonDiagonalRK();
+  double nonDiagonalRK(const dgConservationLaw *claw, double dt, dgDofContainer *solution, int nStages, fullMatrix<double>&A, double *b, double *c);
   dgLimiter *_limiter;
   public:
   void setLimiter(dgLimiter *limiter) { _limiter = limiter; }
   double iterateEuler(const dgConservationLaw *claw, double dt, dgDofContainer *solution);
   double iterate22(const dgConservationLaw *claw, double dt, dgDofContainer *solution);
+  double iterate33(const dgConservationLaw *claw, double dt, dgDofContainer *solution);
   double iterate44(const dgConservationLaw *claw, double dt, dgDofContainer *solution);
+  double iterate44ThreeEight(const dgConservationLaw *claw, double dt, dgDofContainer *solution);
+  double iterate43SchlegelJCAM2009(const dgConservationLaw *claw, double dt, dgDofContainer *solution);
+  double iterateRKFehlberg45(const dgConservationLaw *claw, double dt, dgDofContainer *solution);
   static void registerBindings (binding *b);
   dgRungeKutta();
 };
-- 
GitLab