From 258ae09276f7737e50c5d40449679aa62f4e50aa Mon Sep 17 00:00:00 2001 From: lanfer Date: Tue, 26 Sep 2000 10:55:23 +0000 Subject: SOR solvers for flat and conformal metric git-svn-id: http://svn.cactuscode.org/arrangements/CactusElliptic/EllSOR/trunk@59 fa3da13c-9f13-4301-a575-cf5b8c5e1907 --- src/sor_confmetric.c | 413 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/sor_flat.c | 219 +++++++++++++++++++++++++++ 2 files changed, 632 insertions(+) create mode 100644 src/sor_confmetric.c create mode 100644 src/sor_flat.c diff --git a/src/sor_confmetric.c b/src/sor_confmetric.c new file mode 100644 index 0000000..b0df762 --- /dev/null +++ b/src/sor_confmetric.c @@ -0,0 +1,413 @@ + /*@@ + @file sor_confmetric.c + @date Tue Sep 26 11:29:18 2000 + @author Gerd Lanfermann + @desc + Provides sor solver engine routines + @enddesc + @@*/ + + +#include +#include +#include + +#include "cctk.h" +#include "cctk_Arguments.h" +#include "cctk_Parameters.h" + +#include "CactusBase/Boundary/src/Boundary.h" +#include "CactusBase/CartGrid3D/src/Symmetry.h" +#include "CactusElliptic/EllBase/src/Ell_DBstructure.h" + + +#define SQR(a) ((a)*(a)) + + /*@@ + @routine sor_confmetric + @date Tue Sep 26 11:28:08 2000 + @author Joan Masso, Paul Walker, Gerd Lanfermann + @desc + This is a standalone sor solver engine, + called by the wrapper functions + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + + + +void sor_confmetric_3d(cGH *GH, int *MetricPsiI, int conformal, + int FieldIndex, int MIndex, int NIndex, + CCTK_REAL *AbsTol, CCTK_REAL *RelTol) +{ + DECLARE_CCTK_PARAMETERS + + /* The pointer to the metric fields */ + CCTK_REAL *gxx =NULL, *gxy =NULL; + CCTK_REAL *gxz =NULL, *gyy =NULL; + CCTK_REAL *gyz =NULL, *gzz =NULL; + CCTK_REAL *psi =NULL; + CCTK_REAL *Mlin=NULL, *Nlin=NULL; + CCTK_REAL *var =NULL; + + /* The inverse metric, allocated here */ + CCTK_REAL *uxx=NULL, *uyy=NULL, + *uzz=NULL, *uxz=NULL, + *uxy=NULL, *uyz=NULL; + + /* shortcuts for metric, psi, deltas, etc. */ + CCTK_REAL pm4, p12, det; + + CCTK_REAL dx,dy,dz; + CCTK_REAL dxdx, dydy, dzdz, + dxdy, dxdz, dydz; + + /* Some physical variables */ + int accel_cheb=0, accel_const=0; + int chebit; + CCTK_REAL omega, resnorm=0.0, residual=0.0; + CCTK_REAL glob_residual=0.0, rjacobian=0.0; + CCTK_REAL finf; + int npow; + CCTK_REAL tol; + + + /* Iteration / stepping variables */ + int sorit; + int i,is,ie; + int j,js,je; + int k,ks,ke,kstep; + int nxyz; + + /* 19 point stencil index */ + int ijk; + int ipjk, ijpk, ijkp, imjk, ijmk, ijkm; + int ipjpk, ipjmk, imjpk, imjmk; + int ipjkp, ipjkm, imjkp, imjkm; + int ijpkp, ijpkm, ijmkp, ijmkm; + + /* 19 point stencil coefficients */ + CCTK_REAL ac; + CCTK_REAL ae,aw,an,as,at,ab; + CCTK_REAL ane, anw, ase, asw, ate, atw, abe, abw; + CCTK_REAL atn, ats, abn, abs; + + /* Miscellaneous */ + int sum_handle=-1; + int sw[3], ierr; + int Mstorage=0, Nstorage=0; + size_t varsize; + static int firstcall = 1; + CCTK_REAL detrec_pm4, sqrtdet; + + + /* Get the reduction handle */ + sum_handle = CCTK_ReductionArrayHandle("sum"); + if (sum_handle<0) + CCTK_WARN(1,"Cannot get reduction handle for operation >sum<"); + + /* IF Robin BCs are set, prepare for a boundary call: + setup stencil width and get Robin constants (set by the routine + which is calling the solver interface) */ + if (CCTK_EQUALS(sor_bound,"robin")) { + sw[0]=1; + sw[1]=1; + sw[2]=1; + + ierr = Ell_GetRealKey(&finf, "EllLinConfMetric::Bnd::Robin::inf"); + ierr = Ell_GetIntKey (&npow, "EllLinConfMetric::Bnd::Robin::falloff"); + } + + /* Only supports absolute tolerance */ + tol = AbsTol[0]; + if (CCTK_EQUALS(sor_accel,"const")) + accel_const = 1; + else if (CCTK_EQUALS(sor_accel,"cheb")) + accel_cheb = 1; + + /* Things to do only once! */ + if (firstcall==1) { + if (CCTK_Equals(elliptic_verbose, "yes")) + { + if (accel_cheb) + printf("SOR with Chebyshev acceleration with radius of 1\n"); + else if (accel_const) + printf("SOR with hardcoded omega = 1.8\n"); + else + printf("SOR with unaccelearted relaxation (omega = 1)\n"); + } + firstcall = 0; + } + + + /* Get the data ptr of these GFs, They all have to be + on the same timelevel; derive the metric data pointer from + the index array. Note the ordering in the metric */ + var = (CCTK_REAL*) CCTK_VarDataPtrI(GH, 0, FieldIndex); + gxx = (CCTK_REAL*) CCTK_VarDataPtrI(GH, 0, MetricPsiI[0]); + gxy = (CCTK_REAL*) CCTK_VarDataPtrI(GH, 0, MetricPsiI[1]); + gxz = (CCTK_REAL*) CCTK_VarDataPtrI(GH, 0, MetricPsiI[2]); + gyy = (CCTK_REAL*) CCTK_VarDataPtrI(GH, 0, MetricPsiI[3]); + gyz = (CCTK_REAL*) CCTK_VarDataPtrI(GH, 0, MetricPsiI[4]); + gzz = (CCTK_REAL*) CCTK_VarDataPtrI(GH, 0, MetricPsiI[5]); + + + if (conformal) + psi = (CCTK_REAL*) CCTK_VarDataPtrI(GH, 0, MetricPsiI[6]); + + /* if we have a negative index for M/N, this GF is not needed, + there for don't even look for it. when index positive, + set flag Mstorage=1, dito for N */ + if (MIndex>=0) { + Mlin = (CCTK_REAL*) CCTK_VarDataPtrI(GH,0,MIndex); + Mstorage = 1; + } + if (NIndex>=0) { + Nlin = (CCTK_REAL*) CCTK_VarDataPtrI(GH,0,NIndex); + Nstorage = 1; + } + + /* Shortcuts */ + dx = GH->cctk_delta_space[0]; + dy = GH->cctk_delta_space[1]; + dz = GH->cctk_delta_space[2]; + nxyz = GH->cctk_lsh[0]*GH->cctk_lsh[1]*GH->cctk_lsh[2]; + + + /* Allocate the inverse metric */ + varsize = (size_t)CCTK_VarTypeSize(CCTK_VarTypeI(FieldIndex))*nxyz; + if (!(uxx = (CCTK_REAL*) malloc(varsize))) CCTK_WARN(0,"Allocation failed"); + if (!(uyy = (CCTK_REAL*) malloc(varsize))) CCTK_WARN(0,"Allocation failed"); + if (!(uzz = (CCTK_REAL*) malloc(varsize))) CCTK_WARN(0,"Allocation failed"); + if (!(uxy = (CCTK_REAL*) malloc(varsize))) CCTK_WARN(0,"Allocation failed"); + if (!(uxz = (CCTK_REAL*) malloc(varsize))) CCTK_WARN(0,"Allocation failed"); + if (!(uyz = (CCTK_REAL*) malloc(varsize))) CCTK_WARN(0,"Allocation failed"); + + /* PreCalc the differential coeff. */ + dxdx = 1.0/(2.0*dx*dx); + dydy = 1.0/(2.0*dy*dy); + dzdz = 1.0/(2.0*dz*dz); + dxdy = 1.0/(4.0*dx*dy); + dxdz = 1.0/(4.0*dx*dz); + dydz = 1.0/(4.0*dy*dz); + + /* Calculate the inverse metric */ + + for (ijk=0;ijkcctk_lsh[2]-1;k++) { + for (j=1;jcctk_lsh[1]-1;j++) { + for (i=1;icctk_lsh[0]-1;i++) { + ijk = CCTK_GFINDEX3D(GH,i,j,k); + printf("U G : %d %d %d %7.8g %7.8g %7.8g \n", + i,j,k,uxx[ijk],uyy[ijk],gxx[ijk]); + } + } + }$*/ + + + /* iteration boundaries (ks set inside loop)*/ + is = 1; + js = 1; + ie = GH->cctk_lsh[0]-1; + je = GH->cctk_lsh[1]-1; + ke = GH->cctk_lsh[2]-1; + kstep = 2; + + /* start at 1 for historic (Fortran) reasons */ + for (sorit=1; sorit<=maxit; sorit++) { + + omega = 1.0; + rjacobian = 1.0; + + if (accel_cheb) + for (chebit=2;chebitcctk_lsh[2]==3) + ks = 1; + + for (k=ks;kcctk_gsh[0]*GH->cctk_gsh[1]*GH->cctk_gsh[2]); + + /* apply symmetry boundary conditions within loop */ + if (CartSymVI(GH,FieldIndex)<0) + CCTK_WARN(1,"CartSymVI failed in EllSOR loop"); + + /* apply boundary conditions within loop */ + if (CCTK_EQUALS(sor_bound,"robin")) + ierr = BndRobinVI(GH, sw, finf, npow, FieldIndex); + + /* synchronization of grid variable */ + CCTK_SyncGroupWithVarI(GH, FieldIndex); + + /* Leave iteration loop if tolerance criterium is met */ + if (glob_residualtol) + CCTK_VWarn(1,__LINE__,__FILE__,CCTK_THORNSTRING, + "SOR SOLVER DID NOT CONVERGE within given " + "tolerance/max.number of iterations.\n " + "max. iteration %d residual (tolerance): %g (%g)\n", + maxit, glob_residual, tol ); + + if (uxx) free(uxx); + if (uyy) free(uyy); + if (uzz) free(uzz); + if (uxy) free(uxy); + if (uxz) free(uxz); + if (uyz) free(uyz); + + return; +} + + diff --git a/src/sor_flat.c b/src/sor_flat.c new file mode 100644 index 0000000..0117894 --- /dev/null +++ b/src/sor_flat.c @@ -0,0 +1,219 @@ +#include +#include +#include + +#include "cctk.h" +#include "cctk_Arguments.h" +#include "cctk_Parameters.h" + +#include "CactusBase/Boundary/src/Boundary.h" +#include "CactusBase/CartGrid3D/src/Symmetry.h" +#include "CactusElliptic/EllBase/src/Ell_DBstructure.h" + + +void sor_flat_3d(cGH *GH, int FieldIndex, int MIndex, int NIndex, + CCTK_REAL *AbsTol, CCTK_REAL *RelTol) +{ + + DECLARE_CCTK_PARAMETERS + + /* The pointer to the data fields */ + CCTK_REAL *Mlin=NULL, *Nlin=NULL; + CCTK_REAL *var =NULL; + + /* shortcuts for deltas,etc. */ + CCTK_REAL dx,dy,dz; + + /* Some physical variables */ + int accel_cheb=0, accel_const=0; + int chebit; + CCTK_REAL omega, resnorm, residual, glob_residual, rjacobian; + CCTK_REAL finf; + int npow; + CCTK_REAL tol; + + /* Iteration / stepping variables */ + int sorit; + int i,is,ie; + int j,js,je; + int k,ks,ke,kstep; + int nxyz; + + /* stencil index */ + int ijk; + int ipjk, ijpk, ijkp, imjk, ijmk, ijkm; + + /* Coeeficients for the stencil... */ + CCTK_REAL ac,ac_orig,aw,ae,an,as,at,ab; + + /* Miscellaneous */ + int sum_handle=-1; + int sw[3], ierr; + int Mstorage=0, Nstorage=0; + static int firstcall = 1; + CCTK_REAL dx2rec, dy2rec, dz2rec; + + + /* Get the reduction handle */ + sum_handle = CCTK_ReductionArrayHandle("sum"); + if (sum_handle<0) + CCTK_WARN(1,"Cannot get reduction handle for operation >sum<"); + + /* IF Robin BCs are set, prepare for a boundary call: + setup stencil width and get Robin constants (set by the routine + which is calling the solver interface) */ + if (CCTK_EQUALS(sor_bound,"robin")) { + sw[0]=1; + sw[1]=1; + sw[2]=1; + + ierr = Ell_GetRealKey(&finf, "EllLinConfMetric::Bnd::Robin::inf"); + ierr = Ell_GetIntKey (&npow, "EllLinConfMetric::Bnd::Robin::falloff"); + } + + /* Only supports absolute tolerance */ + tol = AbsTol[0]; + if (CCTK_EQUALS(sor_accel,"const")) + accel_const = 1; + else if (CCTK_EQUALS(sor_accel,"cheb")) + accel_cheb = 1; + + /* Things to do only once! */ + if (firstcall==1) { + if (CCTK_Equals(elliptic_verbose, "yes")) + { + if (accel_cheb) + printf("SOR with Chebyshev acceleration with radius of 1\n"); + else if (accel_const) + printf("SOR with hardcoded omega = 1.8\n"); + else + printf("SOR with unaccelearted relaxation (omega = 1)\n"); + } + firstcall = 0; + } + + /* Get the data ptr of these GFs, They all have to be + on the same timelevel; if we have a negative index for M/N, + this GF is not set, there for don't even look for it and flag it */ + var = (CCTK_REAL*) CCTK_VarDataPtrI(GH, 0, FieldIndex); + if (MIndex>=0) { + Mlin = (CCTK_REAL*) CCTK_VarDataPtrI(GH,0,MIndex); + Mstorage = 1; + } + if (NIndex>=0) { + Nlin = (CCTK_REAL*) CCTK_VarDataPtrI(GH,0,NIndex); + Nstorage = 1; + } + + /* Shortcuts */ + dx = GH->cctk_delta_space[0]; + dy = GH->cctk_delta_space[1]; + dz = GH->cctk_delta_space[2]; + nxyz = GH->cctk_lsh[0]*GH->cctk_lsh[1]*GH->cctk_lsh[2]; + + dx2rec = 1.0/(dx*dx); + dy2rec = 1.0/(dy*dy); + dz2rec = 1.0/(dz*dz); + + ae = dx2rec; + aw = dx2rec; + an = dy2rec; + as = dy2rec; + at = dz2rec; + ab = dz2rec; + + ac_orig = -2.0*dx2rec - 2.0*dy2rec - 2.0*dz2rec; + + is = 1; + js = 1; + ie = GH->cctk_lsh[0]-1; + je = GH->cctk_lsh[1]-1; + ke = GH->cctk_lsh[2]-1; + kstep = 2; + + /* start at 1 for historic (Fortran) reasons */ + for (sorit=1; sorit<=maxit; sorit++) { + + omega = 1.0; + rjacobian = 1.0; + + if (accel_cheb) + for (chebit=2;chebitcctk_lsh[2]==3) + ks = 2; + + for (k=ks;kcctk_gsh[0]*GH->cctk_gsh[1]*GH->cctk_gsh[2]); + + /* apply symmetry boundary conditions within loop */ + if (CartSymVI(GH,FieldIndex)<0) + CCTK_WARN(1,"CartSymVI failed in EllSOR loop"); + + /* apply boundary conditions within loop */ + if (CCTK_EQUALS(sor_bound,"robin")) + ierr = BndRobinVI(GH, sw, finf, npow, FieldIndex); + + /* synchronization of grid variable */ + CCTK_SyncGroupWithVarI(GH, FieldIndex); + + /* Leave iteration loop if tolerance criterium is met */ + if (glob_residualtol) + CCTK_WARN(2,"SOR SOLVER DID NOT CONVERGE"); + + return; +} + + -- cgit v1.2.3