From 63e10688e4ec39df97b5b64412cfde7c0af1a50e Mon Sep 17 00:00:00 2001
From: Cristian C Lalescu <Cristian.Lalescu@ds.mpg.de>
Date: Fri, 6 Nov 2015 14:17:09 +0100
Subject: [PATCH] introduce linear interpolation in time

I think. still checking...
---
 bfps/NavierStokes.py      |  4 ++--
 bfps/cpp/interpolator.cpp | 34 +++++++++++++++++++++-------------
 bfps/cpp/interpolator.hpp |  4 ++--
 bfps/cpp/particles.cpp    | 29 +++++++++++++++++------------
 bfps/cpp/particles.hpp    |  4 +++-
 5 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/bfps/NavierStokes.py b/bfps/NavierStokes.py
index bf49357b..6f345644 100644
--- a/bfps/NavierStokes.py
+++ b/bfps/NavierStokes.py
@@ -256,8 +256,8 @@ class NavierStokes(bfps.fluid_base.fluid_particle_base):
             update_fields += 'fs->low_pass_Fourier(fs->cvelocity, 3, {0});\n'.format(kcut)
         update_fields += ('fs->ift_velocity();\n' +
                           'vel_{0}->read_rFFTW(fs->rvelocity);\n' +
-                          'fs->compute_Lagrangian_acceleration(acc_{0}->f+acc_{0}->buffer_size);\n' +
-                          'acc_{0}->read_rFFTW(acc_{0}->f+acc_{0}->buffer_size);\n').format(name)
+                          'fs->compute_Lagrangian_acceleration(acc_{0}->temp);\n' +
+                          'acc_{0}->read_rFFTW(acc_{0}->temp);\n').format(name)
         self.particle_start += update_fields
         self.particle_loop += update_fields
         return None
diff --git a/bfps/cpp/interpolator.cpp b/bfps/cpp/interpolator.cpp
index a0940038..254213e2 100644
--- a/bfps/cpp/interpolator.cpp
+++ b/bfps/cpp/interpolator.cpp
@@ -43,25 +43,30 @@ interpolator<rnumber, interp_neighbours>::interpolator(
             4, tdims,
             this->unbuffered_descriptor->mpi_dtype,
             this->unbuffered_descriptor->comm);
-    this->f = new rnumber[this->descriptor->local_size];
-    //if (sizeof(rnumber) == 4)
-    //    this->f = fftwf_alloc_real(this->descriptor->local_size);
-    //else if (sizeof(rnumber) == 8)
-    //    this->f = fftw_alloc_real(this->descriptor->local_size);
+    this->f0 = new rnumber[this->descriptor->local_size];
+    this->f1 = new rnumber[this->descriptor->local_size];
+    this->temp = this->f1 + this->buffer_size;
 }
 
 template <class rnumber, int interp_neighbours>
 interpolator<rnumber, interp_neighbours>::~interpolator()
 {
-    delete[] this->f;
+    delete[] this->f0;
+    delete[] this->f1;
     delete this->descriptor;
 }
 
 template <class rnumber, int interp_neighbours>
 int interpolator<rnumber, interp_neighbours>::read_rFFTW(void *void_src)
 {
+    /* first, roll fields */
+    rnumber *tmp = this->f0;
+    this->f0 = this->f1;
+    this->f1 = tmp;
+    this->temp = this->f0 + this->buffer_size;
+    /* now do regular things */
     rnumber *src = (rnumber*)void_src;
-    rnumber *dst = this->f;
+    rnumber *dst = this->f1;
     /* do big copy of middle stuff */
     clip_zero_padding<rnumber>(this->unbuffered_descriptor, src, 3);
     std::copy(src,
@@ -121,6 +126,7 @@ int interpolator<rnumber, interp_neighbours>::read_rFFTW(void *void_src)
 
 template <class rnumber, int interp_neighbours>
 void interpolator<rnumber, interp_neighbours>::operator()(
+        double t,
         int *xg,
         double *xx,
         double *dest,
@@ -140,16 +146,18 @@ void interpolator<rnumber, interp_neighbours>::operator()(
         this->compute_beta(deriv[2], xx[2], bz);
     }
     std::fill_n(dest, 3, 0);
-    rnumber *field = this->f + this->buffer_size;
+    rnumber *ff0 = this->f0 + this->buffer_size;
+    rnumber *ff1 = this->f1 + this->buffer_size;
     for (int iz = -interp_neighbours; iz <= interp_neighbours+1; iz++)
     for (int iy = -interp_neighbours; iy <= interp_neighbours+1; iy++)
     for (int ix = -interp_neighbours; ix <= interp_neighbours+1; ix++)
         for (int c=0; c<3; c++)
-            dest[c] += field[((ptrdiff_t(    xg[2]+iz                             ) *this->descriptor->sizes[1] +
-                               ptrdiff_t(MOD(xg[1]+iy, this->descriptor->sizes[1])))*this->descriptor->sizes[2] +
-                               ptrdiff_t(MOD(xg[0]+ix, this->descriptor->sizes[2])))*3+c]*(bz[iz+interp_neighbours]*
-                                                                                           by[iy+interp_neighbours]*
-                                                                                           bx[ix+interp_neighbours]);
+        {
+            ptrdiff_t tindex = ((ptrdiff_t(    xg[2]+iz                             ) *this->descriptor->sizes[1] +
+                                 ptrdiff_t(MOD(xg[1]+iy, this->descriptor->sizes[1])))*this->descriptor->sizes[2] +
+                                 ptrdiff_t(MOD(xg[0]+ix, this->descriptor->sizes[2])))*3+c;
+            dest[c] += (ff0[tindex]*(1-t) + t*ff1[tindex])*(bz[iz+interp_neighbours]*by[iy+interp_neighbours]*bx[ix+interp_neighbours]);
+        }
 }
 
 template class interpolator<float, 1>;
diff --git a/bfps/cpp/interpolator.hpp b/bfps/cpp/interpolator.hpp
index 3e996f4a..4f2716a2 100644
--- a/bfps/cpp/interpolator.hpp
+++ b/bfps/cpp/interpolator.hpp
@@ -52,14 +52,14 @@ class interpolator
         base_polynomial_values compute_beta;
         field_descriptor<rnumber> *descriptor;
         field_descriptor<rnumber> *unbuffered_descriptor;
-        rnumber *f;
+        rnumber *f0, *f1, *temp;
 
         interpolator(
                 fluid_solver_base<rnumber> *FSOLVER,
                 base_polynomial_values BETA_POLYS);
         ~interpolator();
 
-        void operator()(int *xg, double *xx, double *dest, int *deriv = NULL);
+        void operator()(double t, int *xg, double *xx, double *dest, int *deriv = NULL);
         /* destroys input */
         int read_rFFTW(void *src);
 };
diff --git a/bfps/cpp/particles.cpp b/bfps/cpp/particles.cpp
index 2afc73c9..7109f409 100644
--- a/bfps/cpp/particles.cpp
+++ b/bfps/cpp/particles.cpp
@@ -135,6 +135,7 @@ particles<particle_type, rnumber, multistep, interp_neighbours>::~particles()
 template <int particle_type, class rnumber, bool multistep, int interp_neighbours>
 void particles<particle_type, rnumber, multistep, interp_neighbours>::sample_vec_field(
         interpolator<rnumber, interp_neighbours> *vec,
+        double t,
         double *x,
         double *y,
         const bool synch,
@@ -151,7 +152,7 @@ void particles<particle_type, rnumber, multistep, interp_neighbours>::sample_vec
         for (int p=0; p<this->nparticles; p++)
         {
             if (this->myrank == this->computing[p])
-               (*vec)(xg + p*3, xx + p*3, y + p*3, deriv);
+               (*vec)(t, xg + p*3, xx + p*3, y + p*3, deriv);
         }
     }
     else
@@ -162,7 +163,7 @@ void particles<particle_type, rnumber, multistep, interp_neighbours>::sample_vec
             {
                 int crank = this->get_rank(x[p*3 + 2]);
                 if (this->myrank == crank)
-                    (*vec)(xg + p*3, xx + p*3, y + p*3, deriv);
+                    (*vec)(t, xg + p*3, xx + p*3, y + p*3, deriv);
                 if (crank != this->computing[p])
                     this->synchronize_single_particle_state(p, y, crank);
             }
@@ -191,12 +192,12 @@ void particles<particle_type, rnumber, multistep, interp_neighbours>::sample_vec
 }
 
 template <int particle_type, class rnumber, bool multistep, int interp_neighbours>
-void particles<particle_type, rnumber, multistep, interp_neighbours>::get_rhs(double *x, double *y)
+void particles<particle_type, rnumber, multistep, interp_neighbours>::get_rhs(double t, double *x, double *y)
 {
     switch(particle_type)
     {
         case VELOCITY_TRACER:
-            this->sample_vec_field(this->vel, x, y, false);
+            this->sample_vec_field(this->vel, t, x, y, false);
             break;
     }
 }
@@ -209,7 +210,7 @@ void particles<particle_type, rnumber, multistep, interp_neighbours>::jump_estim
     {
         case VELOCITY_TRACER:
             double *y = new double[3*this->nparticles];
-            this->sample_vec_field(this->vel, this->state, y, false);
+            this->sample_vec_field(this->vel, 1.0, this->state, y, false);
             for (int p=0; p<this->nparticles; p++) if (this->myrank == this->computing[p])
             {
                 jump[p] = fabs(2*this->dt * y[3*p+2]);
@@ -358,7 +359,7 @@ template <int particle_type, class rnumber, bool multistep, int interp_neighbour
 void particles<particle_type, rnumber, multistep, interp_neighbours>::AdamsBashforth(int nsteps)
 {
     ptrdiff_t ii;
-    this->get_rhs(this->state, this->rhs[0]);
+    this->get_rhs(0, this->state, this->rhs[0]);
     switch(nsteps)
     {
         case 1:
@@ -450,8 +451,11 @@ void particles<particle_type, rnumber, multistep, interp_neighbours>::Heun()
     if (!multistep)
     {
         double *y = new double[this->array_size];
-        double dtfactor[] = {0.0, this->dt};
-        this->get_rhs(this->state, this->rhs[0]);
+        double dtfactor[2];
+        double factor[] = {0.0, 1.0};
+        dtfactor[0] = factor[0]*this->dt;
+        dtfactor[1] = factor[1]*this->dt;
+        this->get_rhs(0, this->state, this->rhs[0]);
         for (int p=0; p<this->nparticles; p++)
             this->synchronize_single_particle_state(p, this->rhs[0]);
         for (int kindex = 1; kindex < 2; kindex++)
@@ -467,7 +471,7 @@ void particles<particle_type, rnumber, multistep, interp_neighbours>::Heun()
             }
             for (int p=0; p<this->nparticles; p++)
                 this->synchronize_single_particle_state(p, y);
-            this->get_rhs(y, this->rhs[kindex]);
+            this->get_rhs(factor[kindex], y, this->rhs[kindex]);
             for (int p=0; p<this->nparticles; p++)
                 this->synchronize_single_particle_state(p, this->rhs[kindex]);
         }
@@ -492,9 +496,10 @@ void particles<particle_type, rnumber, multistep, interp_neighbours>::cRK4()
 {
     if (!multistep)
     {
+        static double   factor[] = {0.0, 0.5, 0.5, 1.0};
+        static double dtfactor[] = {0.0, this->dt/2, this->dt/2, this->dt};
         double *y = new double[this->array_size];
-        double dtfactor[] = {0.0, this->dt/2, this->dt/2, this->dt};
-        this->get_rhs(this->state, this->rhs[0]);
+        this->get_rhs(0, this->state, this->rhs[0]);
         for (int p=0; p<this->nparticles; p++)
             this->synchronize_single_particle_state(p, this->rhs[0]);
         for (int kindex = 1; kindex < 4; kindex++)
@@ -510,7 +515,7 @@ void particles<particle_type, rnumber, multistep, interp_neighbours>::cRK4()
             }
             for (int p=0; p<this->nparticles; p++)
                 this->synchronize_single_particle_state(p, y);
-            this->get_rhs(y, this->rhs[kindex]);
+            this->get_rhs(factor[kindex], y, this->rhs[kindex]);
             for (int p=0; p<this->nparticles; p++)
                 this->synchronize_single_particle_state(p, this->rhs[kindex]);
         }
diff --git a/bfps/cpp/particles.hpp b/bfps/cpp/particles.hpp
index b42a4f16..49537de1 100644
--- a/bfps/cpp/particles.hpp
+++ b/bfps/cpp/particles.hpp
@@ -109,6 +109,7 @@ class particles
          * */
         void jump_estimate(double *jump_length);
         void get_rhs(double *x, double *rhs);
+        void get_rhs(double t, double *x, double *rhs);
 
         int get_rank(double z); // get rank for given value of z
         void synchronize();
@@ -116,13 +117,14 @@ class particles
         void get_grid_coordinates(double *x, int *xg, double *xx);
         void sample_vec_field(
             interpolator<rnumber, interp_neighbours> *vec,
+            double t,
             double *x,
             double *y,
             const bool synch = false,
             int *deriv = NULL);
         inline void sample_vec_field(interpolator<rnumber, interp_neighbours> *field, double *vec_values)
         {
-            this->sample_vec_field(field, this->state, vec_values, true, NULL);
+            this->sample_vec_field(field, 1.0, this->state, vec_values, true, NULL);
         }
 
         /* input/output */
-- 
GitLab