#include "interpolate.h" #include "math.h" #define MAXLINE 256 #define MIN(a,b) ((a)>(b)?(b):(a)) #define MAX(a,b) ((a)>(b)?(a):(b)) /* ---------------------------------------------------------------------------- * Constructor used to get info from caller, and prepare other necessary data * ---------------------------------------------------------------------------- */ Interpolate::Interpolate(int nx, int ny, int nz, int ndm, doublecomplex **DM) { Nx = nx; Ny = ny; Nz = nz; Npt = Nx*Ny*Nz; ndim = ndm; memory = new Memory; which = UseGamma = 0; data = DM; Dfdx = Dfdy = Dfdz = D2fdxdy = D2fdxdz = D2fdydz = D3fdxdydz = NULL; flag_reset_gamma = flag_allocated_dfs = 0; return; } /* ---------------------------------------------------------------------------- * Private method to initialize tricubic interpolations * ---------------------------------------------------------------------------- */ void Interpolate::tricubic_init() { // prepare necessary data for tricubic if (flag_allocated_dfs == 0){ Dfdx = memory->create(Dfdx, Npt, ndim, "Interpolate_Interpolate:Dfdx"); Dfdy = memory->create(Dfdy, Npt, ndim, "Interpolate_Interpolate:Dfdy"); Dfdz = memory->create(Dfdz, Npt, ndim, "Interpolate_Interpolate:Dfdz"); D2fdxdy = memory->create(D2fdxdy, Npt, ndim, "Interpolate_Interpolate:D2fdxdy"); D2fdxdz = memory->create(D2fdxdz, Npt, ndim, "Interpolate_Interpolate:D2fdxdz"); D2fdydz = memory->create(D2fdydz, Npt, ndim, "Interpolate_Interpolate:D2fdydz"); D3fdxdydz = memory->create(D3fdxdydz, Npt, ndim, "Interpolate_Interpolate:D2fdxdydz"); flag_allocated_dfs = 1; } // get the derivatives int n=0; const double half = 0.5, one4 = 0.25, one8 = 0.125; for (int ii=0; iidestroy(Dfdx); memory->destroy(Dfdy); memory->destroy(Dfdz); memory->destroy(D2fdxdy); memory->destroy(D2fdxdz); memory->destroy(D2fdydz); memory->destroy(D3fdxdydz); delete memory; } /* ---------------------------------------------------------------------------- * Tricubic interpolation, by calling the tricubic library * ---------------------------------------------------------------------------- */ void Interpolate::tricubic(double *qin, doublecomplex *DMq) { // qin should be in unit of 2*pi/L double q[3]; for (int i=0; i<3; i++) q[i] = qin[i]; for (int i=0; i<3; i++){ while (q[i] < 0.) q[i] += 1.; while (q[i] >= 1.) q[i] -= 1.; } int ix = int(q[0]*double(Nx)); int iy = int(q[1]*double(Ny)); int iz = int(q[2]*double(Nz)); double x = q[0]*double(Nx)-double(ix); double y = q[1]*double(Ny)-double(iy); double z = q[2]*double(Nz)-double(iz); int ixp = (ix+1)%Nx, iyp = (iy+1)%Ny, izp = (iz+1)%Nz; vidx[0] = (ix*Ny+iy)*Nz+iz; vidx[1] = (ixp*Ny+iy)*Nz+iz; vidx[2] = (ix*Ny+iyp)*Nz+iz; vidx[3] = (ixp*Ny+iyp)*Nz+iz; vidx[4] = (ix*Ny+iy)*Nz+izp; vidx[5] = (ixp*Ny+iy)*Nz+izp; vidx[6] = (ix*Ny+iyp)*Nz+izp; vidx[7] = (ixp*Ny+iyp)*Nz+izp; for (int i=0; i<8; i++) if (vidx[i] == 0) UseGamma = 1; for (int idim=0; idim= 1.) q[i] -= 1.; } // find the index of the eight vertice int ix, iy, iz, ixp, iyp, izp; double x, y, z; q[0] *= double(Nx); q[1] *= double(Ny); q[2] *= double(Nz); ix = int(q[0])%Nx; iy = int(q[1])%Ny; iz = int(q[2])%Nz; ixp = (ix+1)%Nx; iyp = (iy+1)%Ny; izp = (iz+1)%Nz; x = q[0] - double(ix); y = q[1] - double(iy); z = q[2] - double(iz); //-------------------------------------- vidx[0] = ((ix*Ny)+iy)*Nz + iz; vidx[1] = ((ixp*Ny)+iy)*Nz + iz; vidx[2] = ((ix*Ny)+iyp)*Nz + iz; vidx[3] = ((ix*Ny)+iy)*Nz + izp; vidx[4] = ((ixp*Ny)+iy)*Nz + izp; vidx[5] = ((ix*Ny)+iyp)*Nz + izp; vidx[6] = ((ixp*Ny)+iyp)*Nz + iz; vidx[7] = ((ixp*Ny)+iyp)*Nz + izp; for (int i=0; i<8; i++) if (vidx[i] == 0) UseGamma = 1; double fac[8]; fac[0] = (1.-x)*(1.-y)*(1.-z); fac[1] = x*(1.-y)*(1.-z); fac[2] = (1.-x)*y*(1.-z); fac[3] = (1.-x)*(1.-y)*z; fac[4] = x*(1.-y)*z; fac[5] = (1.-x)*y*z; fac[6] = x*y*(1.-z); fac[7] = x*y*z; // now to do the interpolation for (int idim=0; idim