aboutsummaryrefslogtreecommitdiff
path: root/src/sor_flat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sor_flat.c')
-rw-r--r--src/sor_flat.c219
1 files changed, 219 insertions, 0 deletions
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 <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#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;chebit<sorit;chebit++)
+ omega = 1.0/(1.0 - 0.25*rjacobian*rjacobian*omega);
+ if (accel_const)
+ omega = 1.8;
+
+ resnorm = 0.0;
+
+ ks = (sorit%2)+1;
+ if (GH->cctk_lsh[2]==3)
+ ks = 2;
+
+ for (k=ks;k<ke;k+=kstep) {
+ for (j=js;j<je;j++) {
+ for (i=is;i<ie;i++) {
+
+ ac = ac_orig;
+
+ ijk = CCTK_GFINDEX3D(GH,i ,j ,k );
+ ipjk = CCTK_GFINDEX3D(GH,i+1,j ,k );
+ imjk = CCTK_GFINDEX3D(GH,i-1,j ,k );
+ ijpk = CCTK_GFINDEX3D(GH,i ,j+1,k );
+ ijmk = CCTK_GFINDEX3D(GH,i ,j-1,k );
+ ijkp = CCTK_GFINDEX3D(GH,i ,j ,k+1);
+ ijkm = CCTK_GFINDEX3D(GH,i ,j ,k-1);
+
+ if (Mstorage)
+ ac += Mlin[ijk];
+
+ residual = ac * var[ijk]
+ + ae *var[ipjk] + aw*var[imjk]
+ + an *var[ijpk] + as*var[ijmk]
+ + at *var[ijkp] + ab*var[ijkm];
+
+ if (Nstorage)
+ residual +=Nlin[ijk];
+
+ resnorm = resnorm + fabs(residual);
+
+ var[ijk] = var[ijk] - omega*residual/ac;
+
+ printf(" %d %d %d %f \n",i,j,k,var[ijk]);
+
+ }
+ }
+ }
+
+ /* reduction operation on processor-local residual values */
+ ierr = CCTK_ReduceLocScalar(GH, -1, sum_handle,
+ &resnorm, &glob_residual, CCTK_VARIABLE_REAL);
+ if (ierr<0)
+ CCTK_WARN(1,"Reduction of Norm failed");
+
+ glob_residual = glob_residual /
+ (GH->cctk_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_residual<tol)
+ break;
+
+ }
+
+ if (glob_residual>tol)
+ CCTK_WARN(2,"SOR SOLVER DID NOT CONVERGE");
+
+ return;
+}
+
+