aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README20
-rw-r--r--interface.ccl27
-rw-r--r--param.ccl315
-rw-r--r--schedule.ccl2
-rw-r--r--src/Comparison.c331
-rw-r--r--src/ComparisonSolutions.F183
-rw-r--r--src/boostrotmetric.F165
-rw-r--r--src/bowl.F251
-rw-r--r--src/exactblendbound.F193
-rw-r--r--src/exactboundary.F123
-rw-r--r--src/exactcartblendbound.F207
-rw-r--r--src/exactdata.F194
-rw-r--r--src/exactgauge.F135
-rw-r--r--src/exactinitialize.F71
-rw-r--r--src/exactmetric.F136
-rw-r--r--src/fakebinary.F173
-rw-r--r--src/finkelstein.F66
-rw-r--r--src/flatschwarz.F70
-rw-r--r--src/include/pGF_ComparisonExtensions.h1
-rw-r--r--src/include/slice_normal.h103
-rw-r--r--src/kerrschild.F127
-rw-r--r--src/linextraponebound.F140
-rw-r--r--src/make.code.defn15
-rw-r--r--src/minkowski.F46
-rw-r--r--src/multiBH.F133
-rw-r--r--src/novikov.F201
-rw-r--r--src/slice_data.F327
-rw-r--r--src/slice_evolve.F132
-rw-r--r--src/slice_initialize.F41
-rw-r--r--src/starschwarz.F120
30 files changed, 4048 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..6498fbf
--- /dev/null
+++ b/README
@@ -0,0 +1,20 @@
+Cactus Code Thorn Exact
+Authors : Carsten Gundlach initially, plus many other authors.
+CVS info : $Header$
+--------------------------------------------------------------------------
+
+Purpose of the thorn:
+
+The initial purpose of this thorn was the comparison of numerical
+spacetimes against exact solutions. One particular solution,
+the boost-rotation-symmetric spacetimes, was the first application.
+
+Later, the thorn developed as a reservoir for a variety of exact spacetimes,
+some of them in different coordinate systems, and even some non-Einstein
+spcetimes. All od these exact spacetimes have been found useful for
+testing different aspect of the code. Since mamy different people have
+contributed to this thorn by adding new exact solutions, you shoudl expect
+many different styles of coding here.
+
+For more details see the documentation in the directory doc.
+
diff --git a/interface.ccl b/interface.ccl
new file mode 100644
index 0000000..64eacd0
--- /dev/null
+++ b/interface.ccl
@@ -0,0 +1,27 @@
+# Interface definition for thorn Exact
+# $Header$
+
+implements: exact
+inherits: einstein
+
+private:
+
+real Exact_slice type=GF
+{
+ slicex,
+ slicey,
+ slicez,
+ slicet
+} "position of an arbitrary slice in exact solution spacetime"
+
+real Exact_slicetemp type=GF
+{
+ slicetmp1x,
+ slicetmp1y,
+ slicetmp1z,
+ slicetmp1t,
+ slicetmp2x,
+ slicetmp2y,
+ slicetmp2z,
+ slicetmp2t
+} "Temporary grid functions" \ No newline at end of file
diff --git a/param.ccl b/param.ccl
new file mode 100644
index 0000000..a37da6a
--- /dev/null
+++ b/param.ccl
@@ -0,0 +1,315 @@
+# Parameter definitions for thorn Exact
+# $Header$
+
+shares: grid
+
+shares: einstein
+
+EXTENDS KEYWORD slicing ""
+{
+ "exact" :: Use lapse from exact solution
+} ""
+
+EXTENDS KEYWORD shift ""
+{
+ "exact" :: Use shift from exact solution
+} ""
+
+
+restricted:
+
+# General parameters
+
+KEYWORD exactmodel "The exact solution used in thorn exact"
+{
+ "minkowski" :: Minkowski spacetime
+ "boostrot" :: Boost rotation symmetric spacetime
+ "finkelstein" :: Black hole in Eddington-Finkelstein coordinates
+ "kerrschild" :: Kerr-Schild form of boosted rotating black hole
+ "flatschwarz" :: Schwazschild black-hole with flat spatial metric
+ "starschwarz" :: Schwazschild (constant density) star
+ "novikov" :: Black hole in Novikov coordinates
+ "multiBH" :: Maximally charged multi BH solutions
+ "bowl" :: Non-Einstein bowl (bag-of-gold) spacetime
+ "fakebinary" :: Non-Einstein fake-binary of Thorn et al
+} "minkowski"
+
+
+# Parameters for the blended boundaries.
+
+BOOLEAN exblend_Ks "Blend the K variables with the exact solution?"
+{
+} "yes"
+
+BOOLEAN exblend_gs "Blend the g variables with the exact solution?"
+{
+} "yes"
+
+BOOLEAN exblend_gauge "Blend the lapse and shift with the exact solution?"
+{
+} "yes"
+
+REAL exblend_rout "Outer boundary of blending region"
+{
+: :: "Positive means radial value, negative means use outer bound of grid"
+} -1.0
+
+REAL exblend_width "Width of blending zone"
+{
+: :: Positive means width in radius, negative means width = exbeldn_width*dx"
+} -3.0
+
+
+# Parameters for slice
+
+REAL slice_gauss_ampl "Amplitude of Gauss slice in exact"
+{
+0.0: :: "Positive please"
+} 0.0
+
+REAL slice_gauss_width "Width of Gauss slice in exact"
+{
+0.0: :: "Positive please"
+} 1.0
+
+
+# Parameters for boostrot
+
+REAL boostrotscale "Length scale of boost rotation data"
+{
+0.0: :: "Positive please"
+} 1.0
+
+REAL boostrotstrength "Dimensionless strength parameter"
+{
+0.0: :: "Positive please"
+} 0.1
+
+REAL boostrotsafedistance "Dimensionless safety distance"
+{
+0.0: :: "Positive please"
+} 0.01
+
+
+# Parameters for finkelstein and kerrschild.
+
+REAL kerrschild_boostv "Boost speed of black hole"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL kerrschild_eps "Fudge parameter"
+{
+: :: "Positive or negative"
+} 1.e-16
+
+REAL kerrschild_m "Black hole mass"
+{
+0.0: :: "Positive please"
+} 1.0
+
+REAL kerrschild_a "Black hole a = J/m"
+{
+0.0: :: "Positive or negative"
+} 0.0
+
+
+# Parameters for Schwarzschild star.
+
+REAL starschwarz_m "Mass of Schwarzschild star"
+{
+0.0: :: "Positive please"
+} 1.0
+
+
+REAL starschwarz_r "Radius of Schwarzschild star"
+{
+0.0: :: "Positive please"
+} 1.0
+
+
+# Parameters for bowl metric.
+
+KEYWORD bowl_type "Type of bowl metric"
+{
+ gauss :: "Gaussian bowl"
+ fermi :: "Fermi bowl"
+} "gauss"
+
+BOOLEAN bowl_evolve "Evolving bowl metric?"
+{
+} "no"
+
+REAL bowl_a "Bowl strength"
+{
+0.0: :: "Positive please"
+} 0.5
+
+REAL bowl_c "Center of deformation"
+{
+0.0: :: "Positive please"
+} 2.5
+
+REAL bowl_s "Width of deformation"
+{
+0.0: :: "Positive please"
+} 2.5
+
+REAL bowl_dx "Scale factor in x direction"
+{
+0.0: :: "Positive please"
+} 1.0
+
+REAL bowl_dy "Scale factor in y direction"
+{
+0.0: :: "Positive please"
+} 1.0
+
+REAL bowl_dz "Scale factor in z direction"
+{
+0.0: :: "Positive please"
+} 1.0
+
+REAL bowl_t0 "Center of Fermi step in time"
+{
+0.0: :: "Positive please"
+} 1.0
+
+REAL bowl_st "Width of Fermi step in time"
+{
+0.0: :: "Positive please"
+} 1.0
+
+
+# Parameters for Thorne's fake finary.
+
+KEYWORD fakebinary_atype "Thorne's binary type"
+{
+ "constant" ::
+ "quadrupole ::
+} "constant"
+
+BOOLEAN fakebinary_retarded "Use retarded time?"
+{
+} "no"
+
+REAL fakebinary_eps "Thorne's binary: fudge parameter"
+{
+0.0: :: "Positive please"
+} 1.e-16
+
+REAL fakebinary_a0 "Thorne's binary: initial separation"
+{
+0.0: :: "Positive please"
+} 5.0
+
+REAL fakebinary_omega0 "Thorne's binary: initial angular frequency"
+{
+: :: "Positive or negative"
+} 1.0
+
+REAL fakebinary_m "Thorne's binary: mass"
+{
+0.0: :: "Positive please"
+} 0.1
+
+REAL fakebinary_bround "Thorne's binary: smoothing for Newtonian potential"
+{
+: :: "Positive or negative"
+} 0.0
+
+
+# Parameters for multiBH.
+
+INT kt_nBH "number of black holes 0-4"
+{
+0: :: "Positive please"
+} 0
+
+REAL kt_hubble "Hubble constant= pm sqrt{Lambda/3}"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL m_bh1 "mass of black hole 1"
+{
+0.0: :: "Positive please"
+} 0.0
+
+REAL m_bh2 "mass of black hole 2"
+{
+0.0: :: "Positive please"
+} 0.0
+
+REAL m_bh3 "mass of black hole 3"
+{
+0.0: :: "Positive please"
+} 0.0
+
+REAL m_bh4 "mass of black hole 4"
+{
+0.0: :: "Positive please"
+} 0.0
+
+REAL co_bh1x "x coord of black hole 1"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL co_bh1y "y coord of black hole 1"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL co_bh1z "z coord of black hole 1"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL co_bh2x "x coord of black hole 2"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL co_bh2y "y coord of black hole 2"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL co_bh2z "z coord of black hole 2"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL co_bh3x "x coord of black hole 3"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL co_bh3y "y coord of black hole 3"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL co_bh3z "z coord of black hole 3"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL co_bh4x "x coord of black hole 4"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL co_bh4y "y coord of black hole 4"
+{
+: :: "Positive or negative"
+} 0.0
+
+REAL co_bh4z "z coord of black hole 4"
+{
+: :: "Positive or negative"
+} 0.0
+
+
+
diff --git a/schedule.ccl b/schedule.ccl
new file mode 100644
index 0000000..6e901c9
--- /dev/null
+++ b/schedule.ccl
@@ -0,0 +1,2 @@
+# Schedule definitions for thorn Exact
+# $Header$
diff --git a/src/Comparison.c b/src/Comparison.c
new file mode 100644
index 0000000..bc5554a
--- /dev/null
+++ b/src/Comparison.c
@@ -0,0 +1,331 @@
+/* Please god comment me ... */
+
+#include "cctk.h"
+
+static int comp_initialized = 0;
+static int comp_active = -1;
+
+static int comp_metric = 0;
+static int comp_curv = 0;
+static int comp_gauge = 0;
+
+#define f_comparisonmetric FORTRAN_NAME(comparisonmetric_,COMPARISONMETRIC,comparisonmetric)
+void FMODIFIER f_comparisonmetric(FORT_ARGS_PROTO, PROTO_FORT_FIELDS,
+ double *,
+ double *,
+ double *,
+ double *,
+ double *,
+ double *);
+#define f_comparisoncurvature FORTRAN_NAME(comparisoncurvature_,COMPARISONCURVATURE,comparisoncurvature)
+void FMODIFIER f_comparisoncurvature(FORT_ARGS_PROTO, PROTO_FORT_FIELDS,
+ double *,
+ double *,
+ double *,
+ double *,
+ double *,
+ double *);
+#define f_comparisongauge FORTRAN_NAME(comparisongauge_,COMPARISONGAUGE,comparisongauge)
+void FMODIFIER f_comparisongauge(FORT_ARGS_PROTO, PROTO_FORT_FIELDS,
+ double *,
+ double *,
+ double *,
+ double *);
+
+static int comptrips=1;
+
+void Comparison(pGH *in) {
+ void DoComparison(pGH *high, pGH *med, pGH *low,
+ int gfi, double *he, double *me, double *le);
+
+ int i,j,k;
+ double *h[6];
+ double *m[6];
+ double *l[6];
+
+ int compevery = 1;
+
+ pGH *high, *med, *low;
+
+ /* Grab the approriate grid heirarchies */
+ if (in->convlevel != 0) return;
+
+ high = in;
+ med = GetGHbyLevel(1,in->level, in->mglevel);
+ low = GetGHbyLevel(2,in->level, in->mglevel);
+
+ /* Only compare when grids are aligned. */
+ if (med) compevery = compevery * 2;
+ if (low) compevery = compevery * 2;
+
+ if (iteration % compevery != 0) return;
+
+ /* See if I'm active */
+ if (comp_active < 0) {
+ comp_active = Contains("comparison","yes");
+ }
+ if (!comp_active) return;
+
+ if (!comp_initialized) {
+ pGF *tGF;
+ comp_initialized =1;
+ for (i=0; i<high->ngridFuncs;i++) {
+ tGF = high->gridFuncs[i];
+ if (Contains_bounded("compfields",tGF->name)) {
+ tGF->do_comparison = 1;
+ if (tGF->gfno >= GFI_GXX &&
+ tGF->gfno <= GFI_GZZ)
+ comp_metric = 1;
+
+ if (tGF->gfno >= GFI_HXX &&
+ tGF->gfno <= GFI_HZZ)
+ comp_curv = 1;
+
+ if (tGF->gfno == GFI_ALP ||
+ tGF->gfno == GFI_BETAX ||
+ tGF->gfno == GFI_BETAY ||
+ tGF->gfno == GFI_BETAZ)
+ comp_gauge = 1;
+ }
+ }
+ }
+ if (!(comp_metric || comp_gauge || comp_curv)) {
+ comp_active = 0;
+ printf ("You must compare gauge, curvature, or metric");
+ return;
+ }
+
+ /* OK at this point we know we are going to do something, so
+ allocate the memory for the comparisons */
+ for (i=0;i<6;i++) {
+ h[i] = (double *)malloc(high->npoints*sizeof(double));
+ if (med)
+ m[i] = (double *)malloc( med->npoints*sizeof(double));
+ else
+ m[i] = NULL;
+ if (low)
+ l[i] = (double *)malloc( low->npoints*sizeof(double));
+ else
+ l[i] = NULL;
+ }
+
+ EnableGFDataStorage(high, high->gridFuncs[high->ngridFuncs-1]);
+ if (med)
+ EnableGFDataStorage( med, med->gridFuncs[med->ngridFuncs-1]);
+ if (low)
+ EnableGFDataStorage( low, low->gridFuncs[low->ngridFuncs-1]);
+
+ if (comp_metric) {
+ SetupFortranArrays(high);
+ f_comparisonmetric(FORT_ARGS(high), PASS_FORT_FIELDS(high),
+ h[0],h[1],h[2],h[3],h[4],h[5]);
+
+ if (med) {
+ SetupFortranArrays(med);
+ f_comparisonmetric(FORT_ARGS(med), PASS_FORT_FIELDS(med),
+ m[0],m[1],m[2],m[3],m[4],m[5]);
+ }
+
+ if (low) {
+ SetupFortranArrays(low);
+ f_comparisonmetric(FORT_ARGS(low), PASS_FORT_FIELDS(low),
+ l[0],l[1],l[2],l[3],l[4],l[5]);
+ }
+
+ for (i=GFI_GXX; i<=GFI_GZZ;i++) {
+ if (high->gridFuncs[i]->do_comparison) {
+ DoComparison(high,med,low,i,
+ h[i-GFI_GXX],m[i-GFI_GXX],l[i-GFI_GXX]);
+ }
+ }
+ }
+
+ if (comp_curv) {
+ SetupFortranArrays(high);
+ f_comparisoncurvature(FORT_ARGS(high), PASS_FORT_FIELDS(high),
+ h[0],h[1],h[2],h[3],h[4],h[5]);
+
+ if (med) {
+ SetupFortranArrays(med);
+ f_comparisoncurvature(FORT_ARGS(med), PASS_FORT_FIELDS(med),
+ m[0],m[1],m[2],m[3],m[4],m[5]);
+ }
+
+ if (low) {
+ SetupFortranArrays(low);
+ f_comparisoncurvature(FORT_ARGS(low), PASS_FORT_FIELDS(low),
+ l[0],l[1],l[2],l[3],l[4],l[5]);
+ }
+
+ for (i=GFI_HXX; i<=GFI_HZZ;i++) {
+ if (high->gridFuncs[i]->do_comparison) {
+ DoComparison(high,med,low,i,
+ h[i-GFI_HXX],m[i-GFI_HXX],l[i-GFI_HXX]);
+ }
+ }
+ }
+
+ if (comp_gauge) {
+ SetupFortranArrays(high);
+ f_comparisongauge(FORT_ARGS(high), PASS_FORT_FIELDS(high),
+ h[0],h[1],h[2],h[3]);
+
+ if (med) {
+ SetupFortranArrays(med);
+ f_comparisongauge(FORT_ARGS(med), PASS_FORT_FIELDS(med),
+ m[0],m[1],m[2],m[3]);
+ }
+
+ if (low) {
+ SetupFortranArrays(low);
+ f_comparisongauge(FORT_ARGS(low), PASS_FORT_FIELDS(low),
+ l[0],l[1],l[2],l[3]);
+ }
+
+ if (high->gridFuncs[GFI_ALP]->do_comparison) {
+ DoComparison(high,med,low,GFI_ALP,h[0],m[0],l[0]);
+ }
+
+ if (high->gridFuncs[GFI_BETAX]->do_comparison) {
+ DoComparison(high,med,low,GFI_BETAX,h[1],m[1],l[1]);
+ }
+
+ if (high->gridFuncs[GFI_BETAY]->do_comparison) {
+ DoComparison(high,med,low,GFI_BETAY,h[2],m[2],l[2]);
+ }
+
+ if (high->gridFuncs[GFI_BETAZ]->do_comparison) {
+ DoComparison(high,med,low,GFI_BETAZ,h[3],m[3],l[3]);
+ }
+ }
+
+ for (i=0;i<6;i++) {
+ free(h[i]); if (m[i]) free(m[i]); if (l[i]) free(l[i]);
+ }
+ DisableGFDataStorage(high, high->gridFuncs[high->ngridFuncs-1]);
+ if (med)
+ DisableGFDataStorage( med, med->gridFuncs[med->ngridFuncs-1]);
+ if (low)
+ DisableGFDataStorage( low, low->gridFuncs[low->ngridFuncs-1]);
+ comptrips ++ ;
+}
+
+void DoComparison(pGH *high, pGH *med, pGH *low, int gfi,
+ double *he, double *me, double *le) {
+
+ pGF *ws, *cur;
+ double max[3], nm1[3], nm2[3];
+ double sigtop, sigbot, sig3w, sig10, sig21;
+
+ int i;
+
+ printf ("Comparing %s\n",high->gridFuncs[gfi]->name);
+
+ /* Output the analytic solution if we need it */
+ cur = high->gridFuncs[gfi]; ws = high->gridFuncs[high->ngridFuncs-1];
+ if (cur->do_1dio) {
+ ws->do_1dio = comptrips;
+ for (i=0;i<high->npoints;i++)
+ ws->data[i] = he[i];
+ sprintf(ws->name,"%s_exact",cur->name);
+ IO_Write1D(high,ws);
+ ws->do_1dio = 0;
+ ws->lastio_it[1]--;
+ }
+
+ /* Diffs go into workspace */
+ for (i=0;i<high->npoints;i++)
+ ws->data[i] = cur->data[i] - he[i];
+
+ if (cur->do_1dio) {
+ ws->do_1dio = comptrips;
+ sprintf(ws->name,"%s_diff",cur->name);
+ IO_Write1D(high,ws);
+ ws->do_1dio = 0;
+ ws->lastio_it[1]--;
+ }
+
+ max[0] = pGF_MaxVal(high,ws);
+ nm1[0] = pGF_Norm1 (high,ws);
+ nm2[0] = pGF_Norm2 (high,ws);
+
+ if (med) {
+ cur = med->gridFuncs[gfi]; ws = med->gridFuncs[med->ngridFuncs-1];
+ for (i=0;i<med->npoints;i++)
+ ws->data[i] = cur->data[i] - me[i];
+ if (cur->do_1dio) {
+ ws->do_1dio = comptrips;
+ sprintf(ws->name,"%s_diff",cur->name);
+ IO_Write1D(med,ws);
+ ws->do_1dio = 0;
+ ws->lastio_it[1]--;
+ }
+
+ max[1] = pGF_MaxVal(med,ws);
+ nm1[1] = pGF_Norm1 (med,ws);
+ nm2[1] = pGF_Norm2 (med,ws);
+ }
+
+ if (low) {
+ cur = low->gridFuncs[gfi]; ws = low->gridFuncs[low->ngridFuncs-1];
+ for (i=0;i<low->npoints;i++)
+ ws->data[i] = cur->data[i] - le[i];
+ if (cur->do_1dio) {
+ ws->do_1dio = comptrips;
+ sprintf(ws->name,"%s_diff",cur->name);
+ IO_Write1D(low,ws);
+ ws->do_1dio = 0;
+ ws->lastio_it[1]--;
+ }
+
+ max[2] = pGF_MaxVal(low,ws);
+ nm1[2] = pGF_Norm1 (low,ws);
+ nm2[2] = pGF_Norm2 (low,ws);
+ } else {
+ max[2] = 0.0; nm1[2] = 0.0; nm2[2] = 0.0;
+ }
+
+ if (low) {
+ printf (" ------ : High Med Low\n");
+ printf ("Max Diff: %lf %lf %lf\n",
+ max[0],max[1],max[2]);
+ printf ("NM1 Diff: %lf %lf %lf\n",
+ nm1[0],nm1[1],nm1[2]);
+ printf ("NM2 Diff: %lf %lf %lf\n",
+ nm2[0],nm2[1],nm2[2]);
+ } else {
+ if (med) {
+ printf (" ------ : High Med \n");
+ printf ("Max Diff: %lf %lf\n",
+ max[0],max[1]);
+ printf ("NM1 Diff: %lf %lf\n",
+ nm1[0],nm1[1]);
+ printf ("NM2 Diff: %lf %lf\n",
+ nm2[0],nm2[1]);
+ }
+ }
+
+
+ if (low) {
+ sigbot = nm2[0] - nm2[1];
+ if (sigbot == 0) sig3w = 0.0;
+ else sig3w = log(fabs((nm2[1]-nm2[2])/(nm2[0]-nm2[1])))/log(2.0);
+
+ if (nm2[1] == 0) sig21 = 0.0;
+ else sig21 = log(fabs(nm2[2]/nm2[1]))/log(2.0);
+ } else {
+ sig3w = 0.0; sig21 = 0;
+ }
+
+ if (nm2[0] == 0) sig10 = 0.0;
+ else sig10 = log(fabs(nm2[1]/nm2[0]))/log(2.0);
+
+ if (low)
+ printf ("sigma: 3way %lf hm %lf ml %lf\n",
+ sig3w, sig10, sig21);
+ else
+ if (med)
+ printf ("sigma: hm %lf\n",sig10);
+
+}
+
diff --git a/src/ComparisonSolutions.F b/src/ComparisonSolutions.F
new file mode 100644
index 0000000..e37ead0
--- /dev/null
+++ b/src/ComparisonSolutions.F
@@ -0,0 +1,183 @@
+#include "cctk.h"
+#include "cctk_arguments.h"
+
+ subroutine ComparisonMetric(CCTK_FARGUMENTS,
+ $ gxx_ex, gxy_ex, gxz_ex,
+ $ gyy_ex, gyz_ex, gzz_ex)
+
+ implicit none
+
+ DECLARE_CCTK_FARGUMENTS
+
+ CCTK_REAL gxx_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL gxy_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL gxz_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL gyy_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL gyz_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL gzz_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+
+ integer i,j,k
+
+C Dummy arguments of subroutine boostrotdata: these are calculated
+C (at a point) but not used.
+
+ CCTK_REAL hxxjunk, hyyjunk, hzzjunk,
+ $ hxyjunk, hyzjunk, hxzjunk,
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk,
+ $ alpjunk, axjunk, ayjunk, azjunk,
+ $ betaxjunk, betayjunk, betazjunk,
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk
+
+C Call boostrotdata pointwise. Most of what it calculates is
+C thrown away, variables ending in ...junk.
+ do k=1,cctk_lsh(3)
+ do j=1,cctk_lsh(2)
+ do i=1,cctk_lsh(1)
+ call exactdata(x(i,j,k), y(i,j,k), z(i,j,k), cctk_time,
+ $ gxx_ex(i,j,k), gyy_ex(i,j,k), gzz_ex(i,j,k),
+ $ gxy_ex(i,j,k), gyz_ex(i,j,k), gxz_ex(i,j,k),
+ $ hxxjunk, hyyjunk, hzzjunk,
+ $ hxyjunk, hyzjunk, hxzjunk,
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk,
+ $ alpjunk, axjunk, ayjunk, azjunk,
+ $ betaxjunk, betayjunk, betazjunk,
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk)
+ end do
+ end do
+ end do
+
+ return
+ end
+
+cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+
+ subroutine ComparisonCurvature(CCTK_FARGUMENTS,
+ $ hxx_ex, hxy_ex, hxz_ex,
+ $ hyy_ex, hyz_ex, hzz_ex)
+
+ implicit none
+
+ DECLARE_CCTK_FARGUMENTS
+
+ CCTK_REAL hxx_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL hxy_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL hxz_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL hyy_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL hyz_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL hzz_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+
+ integer i,j,k
+
+ CCTK_REAL gxxjunk, gyyjunk, gzzjunk,
+ $ gxyjunk, gyzjunk, gxzjunk,
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk,
+ $ alpjunk, axjunk, ayjunk, azjunk,
+ $ betaxjunk, betayjunk, betazjunk,
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk
+
+ do k=1,cctk_lsh(3)
+ do j=1,cctk_lsh(2)
+ do i=1,cctk_lsh(1)
+ call exactdata(x(i,j,k), y(i,j,k), z(i,j,k), cctk_time,
+ $ gxxjunk, gyyjunk, gzzjunk,
+ $ gxyjunk, gyzjunk, gxzjunk,
+ $ hxx_ex(i,j,k), hyy_ex(i,j,k), hzz_ex(i,j,k),
+ $ hxy_ex(i,j,k), hyz_ex(i,j,k), hxz_ex(i,j,k),
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk,
+ $ alpjunk, axjunk, ayjunk, azjunk,
+ $ betaxjunk, betayjunk, betazjunk,
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk)
+ end do
+ end do
+ end do
+ return
+ end
+
+cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+
+c Note the exact shift comes in even if the shift is not
+c allocated (eg if shift is "none"). In this case just
+c don't use it, since it won't be compared against acctk_lsh(2)thing.
+
+ subroutine ComparisonGauge(CCTK_FARGUMENTS,
+ $ alp_ex, betax_ex, betay_ex, betaz_ex)
+
+ implicit none
+
+ DECLARE_CCTK_FARGUMENTS
+
+ CCTK_REAL alp_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL betax_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL betay_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+ CCTK_REAL betaz_ex(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+
+ integer i,j,k
+
+ CCTK_REAL gxxjunk, gyyjunk, gzzjunk,
+ $ gxyjunk, gyzjunk, gxzjunk,
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk,
+ $ hxxjunk, hyyjunk, hzzjunk,
+ $ hxyjunk, hyzjunk, hxzjunk,
+ $ axjunk, ayjunk, azjunk,
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk
+
+ do k=1,cctk_lsh(3)
+ do j=1,cctk_lsh(2)
+ do i=1,cctk_lsh(1)
+ call exactdata(x(i,j,k), y(i,j,k), z(i,j,k), cctk_time,
+ $ gxxjunk, gyyjunk, gzzjunk,
+ $ gxyjunk, gyzjunk, gxzjunk,
+ $ hxxjunk, hyyjunk, hzzjunk,
+ $ hxyjunk, hyzjunk, hxzjunk,
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk,
+ $ alp_ex(i,j,k), axjunk, ayjunk, azjunk,
+ $ betax_ex(i,j,k), betay_ex(i,j,k), betaz_ex(i,j,k),
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk)
+ end do
+ end do
+ end do
+
+ return
+ end
diff --git a/src/boostrotmetric.F b/src/boostrotmetric.F
new file mode 100644
index 0000000..6a775d3
--- /dev/null
+++ b/src/boostrotmetric.F
@@ -0,0 +1,165 @@
+
+#include "cctk.h"
+#include "cctk_parameters.h"
+
+ subroutine boostrotmetric(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx)
+
+ implicit none
+
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_REAL x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx
+ CCTK_REAL a, b, mu0, mu1, lam1, mu2, lam2,
+ $ lam3, mu4, lam4, mu5, lam5, num, div, f,
+ $ elam, emu0, delta, gfunc, tmp
+ CCTK_REAL h, d, numlim
+
+ external gfunc
+
+ logical firstcall
+
+ data firstcall /.true./
+ save firstcall, h, d, numlim
+
+C Get parameters of the exact solution.
+
+ if (firstcall) then
+
+ h = boostrotscale
+ d = boostrotstrength
+
+ numlim = boostrotsafedistance
+
+ firstcall = .false.
+
+ end if
+
+C Intermediate quantities.
+
+ a = x**2 + y**2
+ b = z**2 - t**2
+
+ num = (0.5d0 * (a + b) - h)**2 + 2.d0 * h * a
+
+C Make sure we are not sitting on one of the two source wordlines,
+C given by x = y = 0, z = +/- sqrt(h^2 + t^2)
+
+ if (num / h**4 .le. numlim) stop 'too close to source wordline'
+
+ div = 1.d0 / sqrt(num**3)
+ f = d**2 * ((0.25d0 * (a + b)**2 - h**2)**2
+ $ - 0.5d0 * h**2 * a * b) / num**4
+
+ mu0 = - d * div * (0.5d0 * a**2 + h * a)
+ mu1 = - d * div * (0.5d0 * b + a - h)
+ lam1 = d * div * (0.5d0 * b - h) - a * f
+ mu2 = gfunc(b, mu1)
+ lam2 = gfunc(b, lam1)
+
+ lam3 = d * div * (0.5d0 * b**2 - h * b)
+ lam4 = - d * div * (0.5d0 * a + h) - b * f
+ mu4 = - d * div * (0.5d0 * a + b + h)
+ mu5 = gfunc(a, - mu4)
+ lam5 = gfunc(a, lam4)
+
+ elam = exp(lam3 + a * lam4)
+ emu0 = exp(mu0)
+ delta = exp(lam3) * (mu5 - lam5)
+
+C All nonvanishing metric coefficients (downstairs).
+
+ gdxx = elam + y**2 * Delta
+ gdyy = elam + x**2 * Delta
+ gdxy = - x * y * Delta
+ gdzz = emu0 * (1.d0 + lam2 * z**2 - mu2 * t**2)
+ gdtz = - emu0 * z * t * (lam2 - mu2)
+ gdtt = - emu0 * (1.d0 + mu2 * z**2 - lam2 * t**2)
+
+C Others.
+
+ gdzx = 0.d0
+ gdyz = 0.d0
+ gdtx = 0.d0
+ gdty = 0.d0
+
+C It is clear that the 3-metric is always spacelike in the xy plane. So
+C we only need to check that gdzz is positive.
+
+ if (gdzz .le. 0.d0) then
+ write(*,*) 'WARNING 3-metric not spacelike in boostrot at'
+ write(*,*) 't =', t, 'z =', z
+ write(*,*) 'x =', x, 'y =', y
+ pause
+ end if
+
+C Calculate inverse metric. That is not too difficult as it is
+c in block-diagonal form.
+
+ tmp = gdtt * gdzz - gdtz**2
+
+ if (tmp .eq. 0.d0) then
+ write(*,*) 'boostrot metric inverse failed in tz plane'
+ STOP
+ end if
+
+ gutt = gdzz / tmp
+ guzz = gdtt / tmp
+ gutz = - gdtz / tmp
+
+ tmp = gdxx * gdyy - gdxy**2
+
+ if (tmp .eq. 0.d0) then
+ write(*,*) 'boostrot metric inverse failed in xy plane'
+ STOP
+ end if
+
+ guxx = gdyy / tmp
+ guyy = gdxx / tmp
+ guxy = - gdxy / tmp
+
+ guzx = 0.d0
+ guyz = 0.d0
+ gutx = 0.d0
+ guty = 0.d0
+
+ return
+ end
+
+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+
+C Calculates g = [exp (x f) - 1] / x as a power series for small x,
+C so that the expression is regular at x = 0.
+
+ function gfunc(x, f)
+
+ implicit none
+
+ integer n
+
+ CCTK_REAL x, f, gfunc
+ CCTK_REAL sum, tmp
+
+ if (abs(x*f) .ge. 1.d-6) then
+ gfunc = (exp(x*f) - 1.d0) / x
+ else
+ sum = 0.d0
+ tmp = f
+ do n=1,10
+ tmp = tmp / dble(n)
+ sum = sum + tmp
+ tmp = tmp * x * f
+ end do
+ gfunc = sum
+ end if
+
+ return
+ end
diff --git a/src/bowl.F b/src/bowl.F
new file mode 100644
index 0000000..c9ba202
--- /dev/null
+++ b/src/bowl.F
@@ -0,0 +1,251 @@
+#include "cctk.h"
+#include "cctk_parameters.h"
+
+ subroutine bowl(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx)
+
+c The metric given here is not a solution of
+c Einstein's equations! It is nevertheless
+c useful for tests since it has a particularly
+c nice geometry. It is a static, spherically
+c symmetric metric with no shift.
+c
+c In spherical coordinates, the metric has the
+c form:
+c
+c 2 2 2 2
+c ds = dr + R(r) d Omega
+c
+c Clearly, r measures radial proper distance, and R(r)
+c is the areal (Schwarzschild) radius.
+c
+c I choose a form of R(r) such that:
+c
+c R --> r r<<1, r>>1
+c
+c So close in, and far away we have a flat metric.
+c In the middle region, I take R to be smaller than
+c r, but still larger than zero. This deficit in
+c areal radius produces the geometry of a `bag of gold'.
+c
+c The size of the deviation from a flat geometry
+c is controled by the parameter "bowl_a".
+c If this parameter is 0, we are in flat space.
+c The width of the curved region is controled by
+c the paramter "bowl_s", and the place where the
+c curvature becomes significant (the center of the
+c deformation) is controled by "bowl_c".
+c
+c The specific form of the function R(r) is:
+c
+c R(r) = ( r - a f(r) )
+c
+c and the form of thr function f(r) depends on the
+c parameter bowl_type:
+c 2 2
+c bowl_type = "gauss" f(r) = exp(-(r-c) / s )
+c
+c bowl_type = "fermi" f(r) = 1 / ( 1 + exp(-s(r-c)) )
+c
+c There are three extra paramters (bowl_dx,bowl_dy,bowl_dz)
+c that scale the (x,y,z) axis respectively. Their default
+c value is 1. These parameters are useful to hide the
+c spherical symmetry of the metric.
+
+ implicit none
+
+ DECLARE_CCTK_PARAMETERS
+
+c Input.
+ CCTK_REAL x, y, z, t
+
+c Output.
+ CCTK_REAL gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx
+
+ logical firstcall,evolve
+
+ integer type
+ integer CCTK_Equals
+
+ CCTK_REAL a,c,s
+ CCTK_REAL dx,dy,dz
+ CCTK_REAL r,r2,rr2
+ CCTK_REAL xr,yr,zr,xr2,yr2,zr2
+ CCTK_REAL fac,det
+ CCTK_REAL tfac,st,t0
+ CCTK_REAL zero,one,two
+
+ data firstcall /.true./
+ save firstcall,evolve,type,a,c,s,dx,dy,dz,t0,st
+
+c Find {zero,one,two}.
+
+ zero = 0.0d0
+ one = 1.0d0
+ two = 2.0d0
+
+c Get parameters of the metric.
+
+ if (firstcall) then
+
+ a = bowl_a
+ c = bowl_c
+ s = bowl_s
+
+ dx = bowl_dx
+ dy = bowl_dy
+ dz = bowl_dz
+
+ if (dx.le.zero) then
+ call CCTK_WARN(0,"The parameter bowl_dx must be greater than 0")
+ end if
+
+ if (dy.le.zero) then
+ call CCTK_WARN(0,"The parameter bowl_dy must be greater than 0")
+ end if
+
+ if (dz.le.zero) then
+ call CCTK_WARN(0,"The parameter bowl_dz must be greater than 0")
+ end if
+
+ if (CCTK_Equals(bowl_type,"gauss").ne.0) then
+ type = 1
+ else if (CCTK_Equals(bowl_type,"fermi").ne.0) then
+ type = 2
+ else
+ call CCTK_WARN(0,"Unknown type of bowl metric")
+ end if
+
+ if (CCTK_Equals(bowl_evolve,"yes").ne.0) then
+ evolve = .true.
+ t0 = bowl_t0
+ st = bowl_st
+ else
+ evolve = .false.
+ end if
+
+ firstcall = .false.
+
+ end if
+
+c Multiply the bowl strength `a' with a time evolution factor.
+c The time evolution factor is taken to be a Fermi step centered
+c in `t0' and with a width `st'. The size of this step is always
+c 1 so that far in the past we will always have flat space, and
+c far in the future we will have the static bowl.
+
+ if (evolve) then
+ tfac = one/(one + dexp(-st*(t-t0)))
+ else
+ tfac = one
+ end if
+
+ a = a*tfac
+
+c Find {r2,r}.
+
+ r2 = (x/dx)**2 + (y/dy)**2 + (z/dz)**2
+ r = dsqrt(r2)
+
+c Find the form function rr2
+c
+c 2 2 2
+c rr2 = (r - a f) / r = (1 - a f / r)
+
+ if (type.eq.1) then
+
+c Gaussian bowl:
+c 2 2 2
+c rr2 = [ 1 - a exp(-(r-c) /s ) / r ]
+c
+c Notice that this really does not go to 1 at the
+c origin. To fix this, I multiply the gaussian
+c with the factor:
+c
+c fac = 1 - sech(4r)
+c
+c This goes smoothly to 0 at the origin, and climbs
+c fast to a limiting value of 1 (at r=1 it is already
+c equal to 0.96).
+
+ fac = one - two/(dexp(4.0d0*r) + dexp(-4.0d0*r))
+ rr2 = (one - a*fac*dexp(-((r-c)/s)**2)/r)**2
+
+ else if (type.eq.2) then
+
+c Fermi bowl:
+c 2
+c rr2 = [ 1 - 1 / ( 1 + exp(-s(r-c)) ) / r ]
+c
+c Again, this doesn't really go to 1 at the origin, so
+c I use the same trick as above.
+
+ fac = one - two/(dexp(4.0d0*r) + dexp(-4.0d0*r))
+ rr2 = (one - a*fac/(one + dexp(-s*(r-c)))/r)**2
+
+ end if
+
+c Give metric components.
+
+ gdtt = - one
+ gdtx = zero
+ gdty = zero
+ gdtz = zero
+
+ if (r.ne.0) then
+
+ xr = (x/dx)/r
+ yr = (y/dy)/r
+ zr = (z/dz)/r
+
+ xr2 = xr**2
+ yr2 = yr**2
+ zr2 = zr**2
+
+ gdxx = (xr2 + rr2*(yr2 + zr2))/dx**2
+ gdyy = (yr2 + rr2*(xr2 + zr2))/dy**2
+ gdzz = (zr2 + rr2*(xr2 + yr2))/dz**2
+
+ gdxy = xr*yr*(one - rr2)/(dx*dy)
+ gdyz = yr*zr*(one - rr2)/(dy*dz)
+ gdzx = xr*zr*(one - rr2)/(dx*dz)
+
+ else
+
+ gdxx = one
+ gdyy = one
+ gdzz = one
+
+ gdxy = zero
+ gdyz = zero
+ gdzx = zero
+
+ end if
+
+c Find inverse metric.
+
+ gutt = - one
+ gutx = zero
+ guty = zero
+ gutz = zero
+
+ det = gdxx*gdyy*gdzz + two*gdxy*gdzx*gdyz
+ . - gdxx*gdyz**2 - gdyy*gdzx**2 - gdzz*gdxy**2
+
+ guxx = (gdyy*gdzz - gdyz**2)/det
+ guyy = (gdxx*gdzz - gdzx**2)/det
+ guzz = (gdxx*gdyy - gdxy**2)/det
+
+ guxy = (gdzx*gdyz - gdzz*gdxy)/det
+ guyz = (gdxy*gdzx - gdxx*gdyz)/det
+ guzx = (gdxy*gdyz - gdyy*gdzx)/det
+
+ return
+ end
diff --git a/src/exactblendbound.F b/src/exactblendbound.F
new file mode 100644
index 0000000..bb7f1b7
--- /dev/null
+++ b/src/exactblendbound.F
@@ -0,0 +1,193 @@
+#include "cctk.h"
+#include "cctk_parameters.h"
+#include "cctk_arguments.h"
+#include "CactusEinstein/Einstein/src/Einstein.h"
+
+ subroutine exactblendboundary(CCTK_FARGUMENTS)
+
+ implicit none
+
+ DECLARE_CCTK_FARGUMENTS
+ DECLARE_CCTK_PARAMETERS
+
+ logical doKij, doGij, doLapse, doShift
+
+ integer i,j,k
+ integer nx,ny,nz
+ integer CCTK_Equals
+
+ CCTK_REAL router, rinner, frac, onemfrac
+ CCTK_REAL gxxe, gyye, gzze, gxye, gyze, gxze
+ CCTK_REAL kxxe, kyye, kzze, kxye, kyze, kxze
+ CCTK_REAL dxgxxe, dxgyye, dxgzze, dxgxye, dxgyze, dxgxze
+ CCTK_REAL dygxxe, dygyye, dygzze, dygxye, dygyze, dygxze
+ CCTK_REAL dzgxxe, dzgyye, dzgzze, dzgxye, dzgyze, dzgxze
+
+ CCTK_REAL alpe, axe, aye, aze
+ CCTK_REAL betaxe,betaye,betaze
+ CCTK_REAL bxxe,bxye,bxze,byxe,byye,byze,bzxe,bzye,bzze
+
+ CCTK_REAL det, uxx, uxy, uxz, uyy, uyz, uzz
+ CCTK_REAL vxe,vye,vze,sav
+
+ CCTK_REAL :: dx,dy,dz,time
+ CCTK_REAL :: ierr,xmx,xmn,ymx,ymn,zmx,zmn,rmx
+
+C Grid parameters.
+
+ nx = cctk_lsh(1)
+ ny = cctk_lsh(2)
+ nz = cctk_lsh(3)
+
+ dx = cctk_delta_space(1)
+ dy = cctk_delta_space(2)
+ dz = cctk_delta_space(3)
+
+ time = cctk_time
+
+C Other parameters.
+
+ doKij = (exblend_Ks.eq.1)
+ doGij = (exblend_gs.eq.1)
+
+ doLapse = ((exblend_gauge.eq.1).and.
+ $ (CCTK_Equals(slicing,"exact").ne.0))
+ doShift = ((exblend_gauge.eq.1).and.
+ $ (CCTK_Equals(shift,"exact").ne.0))
+
+ call CCTK_CoordRange(ierr,cctkGH,xmn,xmx,"x")
+ call CCTK_CoordRange(ierr,cctkGH,ymn,ymx,"y")
+ call CCTK_CoordRange(ierr,cctkGH,zmn,zmx,"z")
+
+ rmx = min(xmx,ymx,zmx)
+
+ if (exblend_rout.lt.0) then
+ router = rmx - 2.0d0*dx
+ else
+ router = exblend_rout
+ endif
+
+ if (exblend_width.lt.0) then
+ rinner = router + exblend_width*dx
+ else
+ rinner = router - exblend_width
+ endif
+
+ do k=1,nz
+ do j=1,ny
+ do i=1,nx
+
+c We only do anything if r >= rinner so only evaluate exact data
+c there.
+
+ if (r(i,j,k) .ge. rinner) then
+
+ call exactdata(x(i,j,k), y(i,j,k), z(i,j,k), time,
+ $ gxxe, gyye, gzze, gxye, gyze, gxze,
+ $ kxxe, kyye, kzze, kxye, kyze, kxze,
+ $ dxgxxe, dxgyye, dxgzze, dxgxye, dxgyze, dxgxze,
+ $ dygxxe, dygyye, dygzze, dygxye, dygyze, dygxze,
+ $ dzgxxe, dzgyye, dzgzze, dzgxye, dzgyze, dzgxze,
+ $ alpe, axe, aye, aze, betaxe, betaye, betaze,
+ $ bxxe, bxye, bxze, byxe,
+ $ byye, byze, bzxe, bzye, bzze)
+
+c This sucks, but we want the exact vs so we can blend them also.
+
+ det = -(gxze**2*gyye)
+ & + 2.d0*gxye*gxze*gyze
+ & - gxxe*gyze**2
+ & - gxye**2*gzze
+ & + gxxe*gyye*gzze
+
+ uxx=(-gyze**2 + gyye*gzze)/det
+ uxy=(gxze*gyze - gxye*gzze)/det
+ uyy=(-gxze**2 + gxxe*gzze)/det
+ uxz=(-gxze*gyye + gxye*gyze)/det
+ uyz=(gxye*gxze - gxxe*gyze)/det
+ uzz=(-gxye**2 + gxxe*gyye)/det
+
+c Outside of router we want to place exact data on our grid
+
+ if (r(i,j,k) .gt. router) then
+
+c This is one of those things I will invariably screw up if I type
+c it in so let the computer do it
+
+#define exassign(q) q(i,j,k) = q e
+#define exassign_grp(p) \
+ exassign(p xx) &&\
+ exassign(p xy) &&\
+ exassign(p xz) &&\
+ exassign(p yy) &&\
+ exassign(p yz) &&\
+ exassign(p zz)
+
+c Note this plays on the nasty trick that fortran doesn't give a
+c damn about spaces so gxx e is the same as gxxe for the parser...
+c Grody but effective!
+
+ if (doGij) then
+ exassign_grp(g)
+ endif
+ if (doKij) then
+ exassign_grp(k)
+ endif
+
+ if (doLapse) then
+ exassign(alp)
+ endif
+
+ if (doShift.and.(shift_state.ne.SHIFT_INACTIVE)) then
+ exassign(betax)
+ exassign(betay)
+ exassign(betaz)
+ endif
+
+c OK so we don't want to blend so use a goto to jump.
+ else
+
+c Evaluate the linear weighting fraction. Obvious...
+
+ frac = (r(i,j,k) - rinner) / (router - rinner)
+ onemfrac = 1.0D0 - frac
+
+c Once again some c-preprocessor tricks based on the whole fortran
+c space thing...
+
+#define INTPOINT(f,v) f(i,j,k) = frac * v + onemfrac * f(i,j,k)
+#define intone(f) INTPOINT(f, f e)
+#define int_grp(p) \
+ intone(p xx) &&\
+ intone(p xy) &&\
+ intone(p xz) &&\
+ intone(p yy) &&\
+ intone(p yz) &&\
+ intone(p zz)
+
+ if (doGij) then
+ int_grp(g)
+ endif
+ if (doKij) then
+ int_grp(k)
+ endif
+
+ if (doLapse) then
+ intone(alp)
+ endif
+
+ if (doShift.and.(shift_state.ne.SHIFT_INACTIVE)) then
+ intone(betax)
+ intone(betay)
+ intone(betaz)
+ endif
+
+ endif ! r > router else
+ endif ! r > rinner
+
+ enddo
+ enddo
+ enddo
+
+ return
+ end
diff --git a/src/exactboundary.F b/src/exactboundary.F
new file mode 100644
index 0000000..5e079ec
--- /dev/null
+++ b/src/exactboundary.F
@@ -0,0 +1,123 @@
+
+#include "cctk.h"
+#include "cctk_parameters.h"
+#include "cctk_arguments.h"
+
+ subroutine exactboundary(CCTK_FARGUMENTS)
+
+ implicit none
+
+ DECLARE_CCTK_FARGUMENTS
+
+ integer i,j,k
+ integer nx,ny,nz
+
+ CCTK_REAL tplusone
+ CCTK_REAL
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk,
+ $ axjunk, ayjunk, azjunk,
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk
+
+C Grid parameters.
+
+ nx = cctk_lsh(1)
+ ny = cctk_lsh(2)
+ nz = cctk_lsh(3)
+
+C Set all initial data including dijk and vi on all points which
+C are on the boundary of the domain if it really is the boundary
+C of the complete grid. Treat all six sides of the grid cube this way.
+
+c Set t = time + dt. This is necessary here because by the time
+c we reach this point the geometry has been evolved one time step
+c but the variable `time' still hasn't been updated.
+
+ tplusone = cctk_time + cctk_delta_time
+
+C Note we also always set the lapse and shift at the boundaries at
+C time t+1. This is to provide boundary conditions for testing
+C elliptic gauge conditions. If they are not used, they will be
+C overwritten by exactgauge.
+
+#define EXACTDATAPOINT \
+ call exactdata(x(i,j,k), y(i,j,k), z(i,j,k), tplusone, \
+ gxx(i,j,k), gyy(i,j,k), gzz(i,j,k), \
+ gxy(i,j,k), gyz(i,j,k), gxz(i,j,k), \
+ kxx(i,j,k), kyy(i,j,k), kzz(i,j,k), \
+ kxy(i,j,k), kyz(i,j,k), kxz(i,j,k), \
+ dxgxxjunk, dxgyyjunk, dxgzzjunk, \
+ dxgxyjunk, dxgyzjunk, dxgxzjunk, \
+ dygxxjunk, dygyyjunk, dygzzjunk, \
+ dygxyjunk, dygyzjunk, dygxzjunk, \
+ dzgxxjunk, dzgyyjunk, dzgzzjunk, \
+ dzgxyjunk, dzgyzjunk, dzgxzjunk, \
+ alp(i,j,k), axjunk, ayjunk, azjunk, \
+ betax(i,j,k), betay(i,j,k), betaz(i,j,k), \
+ bxxjunk, bxyjunk, bxzjunk, \
+ byxjunk, byyjunk, byzjunk, \
+ bzxjunk, bzyjunk, bzzjunk) &&\
+
+ if (cctk_bbox(1) .eq. 1) then
+ i=1
+ do j=1,ny
+ do k=1,nz
+ EXACTDATAPOINT
+ end do
+ end do
+ end if
+
+ if (cctk_bbox(2) .eq. 1) then
+ i=nx
+ do j=1,ny
+ do k=1,nz
+ EXACTDATAPOINT
+ end do
+ end do
+ end if
+
+ if (cctk_bbox(3) .eq. 1) then
+ j=1
+ do i=1,nx
+ do k=1,nz
+ EXACTDATAPOINT
+ end do
+ end do
+ end if
+
+ if (cctk_bbox(4) .eq. 1) then
+ j=ny
+ do i=1,nx
+ do k=1,nz
+ EXACTDATAPOINT
+ end do
+ end do
+ end if
+
+ if (cctk_bbox(5) .eq. 1) then
+ k=1
+ do j=1,ny
+ do i=1,nx
+ EXACTDATAPOINT
+ end do
+ end do
+ end if
+
+ if (cctk_bbox(6) .eq. 1) then
+ k=nz
+ do j=1,ny
+ do i=1,nx
+ EXACTDATAPOINT
+ end do
+ end do
+ end if
+
+ return
+ end
+
diff --git a/src/exactcartblendbound.F b/src/exactcartblendbound.F
new file mode 100644
index 0000000..91efdcc
--- /dev/null
+++ b/src/exactcartblendbound.F
@@ -0,0 +1,207 @@
+#include "cctk.h"
+#include "cctk_parameters.h"
+#include "cctk_arguments.h"
+#include "CactusEinstein/Einstein/src/Einstein.h"
+
+ subroutine exactcartblendboundary(CCTK_FARGUMENTS)
+
+ implicit none
+
+ DECLARE_CCTK_FARGUMENTS
+ DECLARE_CCTK_PARAMETERS
+
+ logical doKij, doGij, doDs, doVs, doLapse, doShift
+
+ integer i,j,k
+ integer nx,ny,nz
+ integer ninterps
+ integer CCTK_Equals
+
+ CCTK_REAL xblend, yblend, zblend
+ CCTK_REAL xmin, xmax, ymin, ymax, zmin, zmax
+ CCTK_REAL xfrac, yfrac, zfrac, onemxfrac, onemyfrac, onemzfrac
+ CCTK_REAL oonints
+ CCTK_REAL sfrac, onemsfrac
+ CCTK_REAL gxxe, gyye, gzze, gxye, gyze, gxze
+ CCTK_REAL kxxe, kyye, kzze, kxye, kyze, kxze
+ CCTK_REAL dxgxxe, dxgyye, dxgzze, dxgxye, dxgyze, dxgxze
+ CCTK_REAL dygxxe, dygyye, dygzze, dygxye, dygyze, dygxze
+ CCTK_REAL dzgxxe, dzgyye, dzgzze, dzgxye, dzgyze, dzgxze
+ CCTK_REAL alpe, axe, aye, aze
+ CCTK_REAL betaxe,betaye,betaze
+ CCTK_REAL bxxe,bxye,bxze,byxe,byye,byze,bzxe,bzye,bzze
+ CCTK_REAL det, uxx, uxy, uxz, uyy, uyz, uzz
+ CCTK_REAL vxe,vye,vze,sav
+
+ CCTK_REAL :: dx,dy,dz,time,ierr
+
+C Grid parameters.
+
+ nx = cctk_lsh(1)
+ ny = cctk_lsh(2)
+ nz = cctk_lsh(3)
+
+ dx = cctk_delta_space(1)
+ dy = cctk_delta_space(2)
+ dz = cctk_delta_space(3)
+
+ time = cctk_time
+
+C Other parameters.
+
+ doKij = (exblend_Ks.eq.1)
+ doGij = (exblend_gs.eq.1)
+
+ doLapse = ((exblend_gauge.eq.1).and.
+ $ (CCTK_Equals("slicing","exact").ne.0))
+ doShift = ((exblend_gauge.eq.1).and.
+ $ (CCTK_Equals(shift,"exact").ne.0))
+
+ if (exblend_width.lt.0) then
+ xblend = - exblend_width*dx
+ yblend = - exblend_width*dy
+ zblend = - exblend_width*dz
+ else
+ xblend = exblend_width
+ yblend = exblend_width
+ zblend = exblend_width
+ endif
+
+ call CCTK_CoordRange(ierr,cctkGH,xmin,xmax,"x")
+ call CCTK_CoordRange(ierr,cctkGH,ymin,ymax,"y")
+ call CCTK_CoordRange(ierr,cctkGH,zmin,zmax,"z")
+
+ do k=1,nz
+ do j=1,ny
+ do i=1,nx
+
+c We only do anything if in the blending region
+
+ if (x(i,j,k) .ge. xmax - xblend .or.
+ $ x(i,j,k) .le. xmin + xblend .or.
+ $ y(i,j,k) .ge. ymax - yblend .or.
+ $ y(i,j,k) .le. ymin + yblend .or.
+ $ z(i,j,k) .ge. zmax - zblend .or.
+ $ z(i,j,k) .le. zmin + zblend) then
+
+ call exactdata(x(i,j,k), y(i,j,k), z(i,j,k), time,
+ $ gxxe, gyye, gzze, gxye, gyze, gxze,
+ $ kxxe, kyye, kzze, kxye, kyze, kxze,
+ $ dxgxxe, dxgyye, dxgzze, dxgxye, dxgyze, dxgxze,
+ $ dygxxe, dygyye, dygzze, dygxye, dygyze, dygxze,
+ $ dzgxxe, dzgyye, dzgzze, dzgxye, dzgyze, dzgxze,
+ $ alpe, axe, aye, aze, betaxe, betaye, betaze,
+ $ bxxe, bxye, bxze, byxe,
+ $ byye, byze, bzxe, bzye, bzze)
+
+c This sucks, but we want the exact vs so we can blend them also.
+
+ det = -(gxze**2*gyye)
+ & + 2.d0*gxye*gxze*gyze
+ & - gxxe*gyze**2
+ & - gxye**2*gzze
+ & + gxxe*gyye*gzze
+
+ uxx=(-gyze**2 + gyye*gzze)/det
+ uxy=(gxze*gyze - gxye*gzze)/det
+ uyy=(-gxze**2 + gxxe*gzze)/det
+ uxz=(-gxze*gyye + gxye*gyze)/det
+ uyz=(gxye*gxze - gxxe*gyze)/det
+ uzz=(-gxye**2 + gxxe*gyye)/det
+
+c OK so 6 blending cases. If frac = 1 we get all exact
+
+ ninterps = 0
+
+ xfrac = 0.0D0
+ onemxfrac = 0.0D0
+ yfrac = 0.0D0
+ onemyfrac = 0.0D0
+ zfrac = 0.0D0
+ onemzfrac = 0.0D0
+
+ if (x(i,j,k) .le. xmin + xblend) then
+ xfrac = 1.0D0 - (x(i,j,k)-xmin) / xblend
+ onemxfrac = 1.0D0 - xfrac
+ ninterps = ninterps + 1
+ endif
+
+ if (x(i,j,k) .ge. xmax - xblend) then
+ xfrac = 1.0D0 - (xmax - x(i,j,k)) / xblend
+ onemxfrac = 1.0D0 - xfrac
+ ninterps = ninterps + 1
+ endif
+
+ if (y(i,j,k) .le. ymin + yblend) then
+ yfrac = 1.0D0 - (y(i,j,k)-ymin) / yblend
+ onemyfrac = 1.0D0 - yfrac
+ ninterps = ninterps + 1
+ endif
+
+ if (y(i,j,k) .ge. ymax - yblend) then
+ yfrac = 1.0D0 - (ymax - y(i,j,k)) / yblend
+ onemyfrac = 1.0D0 - yfrac
+ ninterps = ninterps + 1
+ endif
+
+ if (z(i,j,k) .le. zmin + zblend) then
+ zfrac = 1.0D0 - (z(i,j,k)-zmin) / zblend
+ onemzfrac = 1.0D0 - zfrac
+ ninterps = ninterps + 1
+ endif
+
+ if (z(i,j,k) .ge. zmax - zblend) then
+ zfrac = 1.0D0 - (zmax - z(i,j,k)) / zblend
+ onemzfrac = 1.0D0 - zfrac
+ ninterps = ninterps + 1
+ endif
+
+ oonints = 1.0D0 / ninterps
+
+ if (ninterps .eq. 0 .or. ninterps .gt. 3) then
+ print *,"NINTERPS error", ninterps
+ STOP
+ endif
+
+ sfrac = (xfrac + yfrac + zfrac) * oonints
+ onemsfrac = 1.0D0 - sfrac
+
+c Once again some c-preprocessor tricks based on the whole fortran
+c space thing...
+
+#define INTPOINT(f,v) f(i,j,k) = sfrac * v + onemsfrac * f(i,j,k)
+#define intone(f) INTPOINT(f, f e)
+#define int_grp(p) \
+ intone(p xx) &&\
+ intone(p xy) &&\
+ intone(p xz) &&\
+ intone(p yy) &&\
+ intone(p yz) &&\
+ intone(p zz)
+
+ if (doGij) then
+ int_grp(g)
+ endif
+
+ if (doKij) then
+ int_grp(k)
+ endif
+
+ if (doLapse) then
+ intone(alp)
+ endif
+
+ if (doShift.and.(shift_state.ne.SHIFT_INACTIVE)) then
+ intone(betax)
+ intone(betay)
+ intone(betaz)
+ endif
+
+ endif ! r > rinner
+
+ enddo
+ enddo
+ enddo
+
+ return
+ end
diff --git a/src/exactdata.F b/src/exactdata.F
new file mode 100644
index 0000000..3210715
--- /dev/null
+++ b/src/exactdata.F
@@ -0,0 +1,194 @@
+
+C This routine calculates BM initial data from a subroutine
+C exactmetric that calculates the spacetime metric and its
+C inverse.
+
+#include "cctk.h"
+#include "cctk_parameters.h"
+#include "cctk_arguments.h"
+
+ subroutine exactdata(x, y, z, t,
+ $ gxx, gyy, gzz, gxy, gyz, gxz,
+ $ hxx, hyy, hzz, hxy, hyz, hxz,
+ $ dxgxx, dxgyy, dxgzz, dxgxy, dxgyz, dxgxz,
+ $ dygxx, dygyy, dygzz, dygxy, dygyz, dygxz,
+ $ dzgxx, dzgyy, dzgzz, dzgxy, dzgyz, dzgxz,
+ $ alp, ax, ay, az, betax, betay, betaz,
+ $ bxx, bxy, bxz, byx, byy, byz, bzx, bzy, bzz)
+
+ implicit none
+
+ CCTK_REAL x, y, z, t,
+ $ gxx, gyy, gzz, gxy, gyz, gxz,
+ $ hxx, hyy, hzz, hxy, hyz, hxz,
+ $ dxgxx, dxgyy, dxgzz, dxgxy, dxgyz, dxgxz,
+ $ dygxx, dygyy, dygzz, dygxy, dygyz, dygxz,
+ $ dzgxx, dzgyy, dzgzz, dzgxy, dzgyz, dzgxz,
+ $ alp, ax, ay, az, betax, betay, betaz,
+ $ bxx, bxy, bxz, byx, byy, byz, bzx, bzy, bzz
+
+C gxx is g_xx etc.
+C hxx is K_xx etc.
+C dxgyy is (/2) dg_yy / dx (sic!)
+C alp is N, betax is N^x etc.
+C bxy is (/2) dN^y / dx (sic and sic!)
+C ax is dN / dx / N (sic!)
+
+ CCTK_REAL eps,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz,
+ $ gdtt_p, gdtx_p, gdty_p, gdtz_p,
+ $ gdxx_p, gdyy_p, gdzz_p, gdxy_p, gdyz_p, gdxz_p,
+ $ gutt_p, gutx_p, guty_p, gutz_p,
+ $ guxx_p, guyy_p, guzz_p, guxy_p, guyz_p, guxz_p,
+ $ gdtt_m, gdtx_m, gdty_m, gdtz_m,
+ $ gdxx_m, gdyy_m, gdzz_m, gdxy_m, gdyz_m, gdxz_m,
+ $ gutt_m, gutx_m, guty_m, gutz_m,
+ $ guxx_m, guyy_m, guzz_m, guxy_m, guyz_m, guxz_m
+
+ parameter (eps=1.d-6)
+
+C Get the spacetime metric and its inverse at the base point.
+
+ call exactmetric(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gxx, gyy, gzz,
+ $ gxy, gyz, gxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+C Calculate lapse and shift from the upper metric.
+
+ alp = 1.d0 / sqrt(- gutt)
+ betax = - gutx / gutt
+ betay = - guty / gutt
+ betaz = - gutz / gutt
+
+C In order to calculate the derivatives of the lapse and shift from
+C the contravariant metric, use g^tt = -1/N^2 and g^i0 = N^i / N^2
+C Note that ax is dN/dx / N and that bxy is 1/2 dN^y / dx.
+
+C Calculate x-derivatives.
+
+ call exactmetric(
+ $ x+eps, y, z, t,
+ $ gdtt_p, gdtx_p, gdty_p, gdtz_p,
+ $ gdxx_p, gdyy_p, gdzz_p, gdxy_p, gdyz_p, gdxz_p,
+ $ gutt_p, gutx_p, guty_p, gutz_p,
+ $ guxx_p, guyy_p, guzz_p, guxy_p, guyz_p, guxz_p)
+ call exactmetric(
+ $ x-eps, y, z, t,
+ $ gdtt_m, gdtx_m, gdty_m, gdtz_m,
+ $ gdxx_m, gdyy_m, gdzz_m, gdxy_m, gdyz_m, gdxz_m,
+ $ gutt_m, gutx_m, guty_m, gutz_m,
+ $ guxx_m, guyy_m, guzz_m, guxy_m, guyz_m, guxz_m)
+ dxgxx = (gdxx_p - gdxx_m) / 4.d0 / eps
+ dxgyy = (gdyy_p - gdyy_m) / 4.d0 / eps
+ dxgzz = (gdzz_p - gdzz_m) / 4.d0 / eps
+ dxgxy = (gdxy_p - gdxy_m) / 4.d0 / eps
+ dxgyz = (gdyz_p - gdyz_m) / 4.d0 / eps
+ dxgxz = (gdxz_p - gdxz_m) / 4.d0 / eps
+ ax = - 0.5d0 * (gutt_p - gutt_m) / 2.d0 / eps / gutt
+ bxx = ((- gutx_p / gutt_p) - (- gutx_m / gutt_m)) / 4.d0 / eps
+ bxy = ((- guty_p / gutt_p) - (- guty_m / gutt_m)) / 4.d0 / eps
+ bxz = ((- gutz_p / gutt_p) - (- gutz_m / gutt_m)) / 4.d0 / eps
+
+C Calculate y-derivatives.
+
+ call exactmetric(
+ $ x, y+eps, z, t,
+ $ gdtt_p, gdtx_p, gdty_p, gdtz_p,
+ $ gdxx_p, gdyy_p, gdzz_p, gdxy_p, gdyz_p, gdxz_p,
+ $ gutt_p, gutx_p, guty_p, gutz_p,
+ $ guxx_p, guyy_p, guzz_p, guxy_p, guyz_p, guxz_p)
+ call exactmetric(
+ $ x, y-eps, z, t,
+ $ gdtt_m, gdtx_m, gdty_m, gdtz_m,
+ $ gdxx_m, gdyy_m, gdzz_m, gdxy_m, gdyz_m, gdxz_m,
+ $ gutt_m, gutx_m, guty_m, gutz_m,
+ $ guxx_m, guyy_m, guzz_m, guxy_m, guyz_m, guxz_m)
+ dygxx = (gdxx_p - gdxx_m) / 4.d0 / eps
+ dygyy = (gdyy_p - gdyy_m) / 4.d0 / eps
+ dygzz = (gdzz_p - gdzz_m) / 4.d0 / eps
+ dygxy = (gdxy_p - gdxy_m) / 4.d0 / eps
+ dygyz = (gdyz_p - gdyz_m) / 4.d0 / eps
+ dygxz = (gdxz_p - gdxz_m) / 4.d0 / eps
+ ay = - 0.5d0 * (gutt_p - gutt_m) / 2.d0 / eps / gutt
+ byx = ((- gutx_p / gutt_p) - (- gutx_m / gutt_m)) / 4.d0 / eps
+ byy = ((- guty_p / gutt_p) - (- guty_m / gutt_m)) / 4.d0 / eps
+ byz = ((- gutz_p / gutt_p) - (- gutz_m / gutt_m)) / 4.d0 / eps
+
+C Calculate z-derivatives.
+
+ call exactmetric(
+ $ x, y, z+eps, t,
+ $ gdtt_p, gdtx_p, gdty_p, gdtz_p,
+ $ gdxx_p, gdyy_p, gdzz_p, gdxy_p, gdyz_p, gdxz_p,
+ $ gutt_p, gutx_p, guty_p, gutz_p,
+ $ guxx_p, guyy_p, guzz_p, guxy_p, guyz_p, guxz_p)
+ call exactmetric(
+ $ x, y, z-eps, t,
+ $ gdtt_m, gdtx_m, gdty_m, gdtz_m,
+ $ gdxx_m, gdyy_m, gdzz_m, gdxy_m, gdyz_m, gdxz_m,
+ $ gutt_m, gutx_m, guty_m, gutz_m,
+ $ guxx_m, guyy_m, guzz_m, guxy_m, guyz_m, guxz_m)
+ dzgxx = (gdxx_p - gdxx_m) / 4.d0 / eps
+ dzgyy = (gdyy_p - gdyy_m) / 4.d0 / eps
+ dzgzz = (gdzz_p - gdzz_m) / 4.d0 / eps
+ dzgxy = (gdxy_p - gdxy_m) / 4.d0 / eps
+ dzgyz = (gdyz_p - gdyz_m) / 4.d0 / eps
+ dzgxz = (gdxz_p - gdxz_m) / 4.d0 / eps
+ az = - 0.5d0 * (gutt_p - gutt_m) / 2.d0 / eps / gutt
+ bzx = ((- gutx_p / gutt_p) - (- gutx_m / gutt_m)) / 4.d0 / eps
+ bzy = ((- guty_p / gutt_p) - (- guty_m / gutt_m)) / 4.d0 / eps
+ bzz = ((- gutz_p / gutt_p) - (- gutz_m / gutt_m)) / 4.d0 / eps
+
+C Calculate t-derivatives, and extrinsic curvature.
+
+ call exactmetric(
+ $ x, y, z, t+eps,
+ $ gdtt_p, gdtx_p, gdty_p, gdtz_p,
+ $ gdxx_p, gdyy_p, gdzz_p, gdxy_p, gdyz_p, gdxz_p,
+ $ gutt_p, gutx_p, guty_p, gutz_p,
+ $ guxx_p, guyy_p, guzz_p, guxy_p, guyz_p, guxz_p)
+ call exactmetric(
+ $ x, y, z, t-eps,
+ $ gdtt_m, gdtx_m, gdty_m, gdtz_m,
+ $ gdxx_m, gdyy_m, gdzz_m, gdxy_m, gdyz_m, gdxz_m,
+ $ gutt_m, gutx_m, guty_m, gutz_m,
+ $ guxx_m, guyy_m, guzz_m, guxy_m, guyz_m, guxz_m)
+
+ hxx = - (gdxx_p - gdxx_m) / 4.d0 / eps / alp
+ $ + (dxgxx * betax + dygxx * betay + dzgxx * betaz
+ $ + 2.d0 * (bxx * gxx + bxy * gxy + bxz * gxz)) / alp
+
+ hyy = - (gdyy_p - gdyy_m) / 4.d0 / eps / alp
+ $ + (dxgyy * betax + dygyy * betay + dzgyy * betaz
+ $ + 2.d0 * (byx * gxy + byy * gyy + byz * gyz)) / alp
+
+ hzz = - (gdzz_p - gdzz_m) / 4.d0 / eps / alp
+ $ + (dxgzz * betax + dygzz * betay + dzgzz * betaz
+ $ + 2.d0 * (bzx * gxz + bzy * gyz + bzz * gzz)) / alp
+
+ hxy = - (gdxy_p - gdxy_m) / 4.d0 / eps / alp
+ $ + (dxgxy * betax + dygxy * betay + dzgxy * betaz
+ $ + bxx * gxy + bxy * gyy + bxz * gyz
+ $ + byx * gxx + byy * gxy + byz * gxz) / alp
+
+ hyz = - (gdyz_p - gdyz_m) / 4.d0 / eps / alp
+ $ + (dxgyz * betax + dygyz * betay + dzgyz * betaz
+ $ + byx * gxz + byy * gyz + byz * gzz
+ $ + bzx * gxy + bzy * gyy + bzz * gyz) / alp
+
+ hxz = - (gdxz_p - gdxz_m) / 4.d0 / eps / alp
+ $ + (dxgxz * betax + dygxz * betay + dzgxz * betaz
+ $ + bxx * gxz + bxy * gyz + bxz * gzz
+ $ + bzx * gxx + bzy * gxy + bzz * gxz) / alp
+
+
+ return
+ end
+
+
diff --git a/src/exactgauge.F b/src/exactgauge.F
new file mode 100644
index 0000000..eae23f1
--- /dev/null
+++ b/src/exactgauge.F
@@ -0,0 +1,135 @@
+#include "cctk.h"
+#include "cctk_parameters.h"
+#include "cctk_arguments.h"
+
+ subroutine exactgauge(CCTK_FARGUMENTS)
+
+ implicit none
+
+ DECLARE_CCTK_FARGUMENTS
+ DECLARE_CCTK_PARAMETERS
+
+ integer i,j,k
+ integer nx,ny,nz
+ integer CCTK_Equals
+
+ CCTK_REAL tplushalf
+ CCTK_REAL gxxjunk, gyyjunk, gzzjunk,
+ $ gxyjunk, gyzjunk, gxzjunk,
+ $ hxxjunk, hyyjunk, hzzjunk,
+ $ hxyjunk, hyzjunk, hxzjunk,
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk,
+ $ alpjunk, axjunk, ayjunk, azjunk,
+ $ betaxjunk, betayjunk, betazjunk,
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk
+
+C Grid parameters.
+
+ nx = cctk_lsh(1)
+ ny = cctk_lsh(2)
+ nz = cctk_lsh(3)
+
+C Set t = time + dt/2. This is for consistency with a second
+C order numerical scheme.
+
+ tplushalf = cctk_time + 0.5D0*cctk_delta_time
+
+C Set both lapse and shift.
+
+ if ((CCTK_Equals(slicing,"exact").ne.0).and.
+ . (CCTK_Equals(shift,"exact").ne.0) ) then
+
+ do k=1,nz
+ do j=1,ny
+ do i=1,nx
+
+ call exactdata(x(i,j,k), y(i,j,k), z(i,j,k), tplushalf,
+ $ gxxjunk, gyyjunk, gzzjunk,
+ $ gxyjunk, gyzjunk, gxzjunk,
+ $ hxxjunk, hyyjunk, hzzjunk,
+ $ hxyjunk, hyzjunk, hxzjunk,
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk,
+ $ alp(i,j,k), axjunk, ayjunk, azjunk,
+ $ betax(i,j,k), betay(i,j,k), betaz(i,j,k),
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk)
+
+ end do
+ end do
+ end do
+
+C Set lapse only.
+
+ else if (CCTK_Equals(slicing,"exact").ne.0) then
+
+ do k=1,nz
+ do j=1,ny
+ do i=1,nx
+
+ call exactdata(x(i,j,k), y(i,j,k), z(i,j,k), tplushalf,
+ $ gxxjunk, gyyjunk, gzzjunk,
+ $ gxyjunk, gyzjunk, gxzjunk,
+ $ hxxjunk, hyyjunk, hzzjunk,
+ $ hxyjunk, hyzjunk, hxzjunk,
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk,
+ $ alp(i,j,k), axjunk, ayjunk, azjunk,
+ $ betaxjunk, betayjunk, betazjunk,
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk)
+
+ end do
+ end do
+ end do
+
+C Set shift only.
+
+ else if (CCTK_Equals(shift,"exact").ne.0) then
+
+ do k=1,nz
+ do j=1,ny
+ do i=1,nx
+
+ call exactdata(x(i,j,k), y(i,j,k), z(i,j,k), tplushalf,
+ $ gxxjunk, gyyjunk, gzzjunk,
+ $ gxyjunk, gyzjunk, gxzjunk,
+ $ hxxjunk, hyyjunk, hzzjunk,
+ $ hxyjunk, hyzjunk, hxzjunk,
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk,
+ $ alpjunk, axjunk, ayjunk, azjunk,
+ $ betax(i,j,k), betay(i,j,k), betaz(i,j,k),
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk)
+
+ end do
+ end do
+ end do
+
+ end if
+
+ return
+ end
diff --git a/src/exactinitialize.F b/src/exactinitialize.F
new file mode 100644
index 0000000..e345775
--- /dev/null
+++ b/src/exactinitialize.F
@@ -0,0 +1,71 @@
+C Wrapper for boostrotdata. Calls it and vectorini.
+C Sets Cauchy data, lapse and shift, and what else is needed
+C in the Bona-Masso formalism, at an initial time.
+
+#include "cctk.h"
+#include "cctk_parameters.h"
+#include "cctk_arguments.h"
+#include "CactusEinstein/Einstein/src/Einstein.h"
+
+ subroutine exactinitialize(CCTK_FARGUMENTS)
+
+ implicit none
+
+ DECLARE_CCTK_FARGUMENTS
+
+ integer i,j,k
+ integer nx,ny,nz
+
+ CCTK_REAL alpjunk, axjunk, ayjunk, azjunk,
+ $ betaxjunk, betayjunk, betazjunk,
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk
+ CCTK_REAL
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk
+
+C Note I assume time has been initialized to physical time.
+C Set data pointwise.
+
+ nx = cctk_lsh(1)
+ ny = cctk_lsh(2)
+ nz = cctk_lsh(3)
+
+ do k=1,nz
+ do j=1,ny
+ do i=1,nx
+
+ call exactdata(x(i,j,k), y(i,j,k), z(i,j,k), cctk_time,
+ $ gxx(i,j,k), gyy(i,j,k), gzz(i,j,k),
+ $ gxy(i,j,k), gyz(i,j,k), gxz(i,j,k),
+ $ kxx(i,j,k), kyy(i,j,k), kzz(i,j,k),
+ $ kxy(i,j,k), kyz(i,j,k), kxz(i,j,k),
+ $ dxgxxjunk, dxgyyjunk, dxgzzjunk,
+ $ dxgxyjunk, dxgyzjunk, dxgxzjunk,
+ $ dygxxjunk, dygyyjunk, dygzzjunk,
+ $ dygxyjunk, dygyzjunk, dygxzjunk,
+ $ dzgxxjunk, dzgyyjunk, dzgzzjunk,
+ $ dzgxyjunk, dzgyzjunk, dzgxzjunk,
+ $ alpjunk, axjunk, ayjunk, azjunk,
+ $ betaxjunk, betayjunk, betazjunk,
+ $ bxxjunk, bxyjunk, bxzjunk,
+ $ byxjunk, byyjunk, byzjunk,
+ $ bzxjunk, bzyjunk, bzzjunk)
+
+ end do
+ end do
+ end do
+
+C Tell the code there is no need to treat the conformal factor
+C as a separate field. That is, we have set the physical metric here.
+
+ conformal_state = NOCONFORMAL_METRIC
+ psi = 1.d0
+
+ return
+ end
diff --git a/src/exactmetric.F b/src/exactmetric.F
new file mode 100644
index 0000000..48a604f
--- /dev/null
+++ b/src/exactmetric.F
@@ -0,0 +1,136 @@
+#include "cctk.h"
+#include "cctk_parameters.h"
+#include "cctk_arguments.h"
+
+C This is just a wrapper for different routines in place of exactmetric.
+
+ subroutine exactmetric(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+ implicit none
+
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_REAL x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz
+
+ logical firstcall
+
+ integer CCTK_Equals
+
+C Call the corresponding routine.
+
+ if (CCTK_Equals(exactmodel,"boostrot").eq.1) then
+
+ call boostrotmetric(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz,
+ $ gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+ elseif (CCTK_Equals(exactmodel,"finkelstein").eq.1) then
+
+ call finkelstein(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz,
+ $ gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+ elseif (CCTK_Equals(exactmodel,"kerrschild").eq.1) then
+
+ call kerrschild(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz,
+ $ gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+ elseif (CCTK_Equals(exactmodel,"flatschwarz").eq.1) then
+
+ call flatschwarz(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz,
+ $ gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+ elseif (CCTK_Equals(exactmodel,"starschwarz").eq.1) then
+
+ call starschwarz(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz,
+ $ gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+ elseif (CCTK_Equals(exactmodel,"novikov").eq.1) then
+
+ call novikov(x,y,z,t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz,
+ $ gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+ elseif (CCTK_Equals(exactmodel,"bowl").eq.1) then
+
+ call bowl(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz,
+ $ gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+ elseif (CCTK_Equals(exactmodel,"minkowski").eq.1) then
+
+ call minkowski(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz,
+ $ gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+ elseif (CCTK_Equals(exactmodel,"fakebinary").eq.1) then
+
+ call fakebinary(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz,
+ $ gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+ elseif (CCTK_Equals(exactmodel,"multiBH").eq.1) then
+
+ call multi_BHs(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz,
+ $ gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+ else
+
+ call CCTK_WARN(0,"Unknown value of parameter exactmodel")
+
+ end if
+
+ return
+ end
diff --git a/src/fakebinary.F b/src/fakebinary.F
new file mode 100644
index 0000000..2db00a6
--- /dev/null
+++ b/src/fakebinary.F
@@ -0,0 +1,173 @@
+C fakebinary.F
+C Bernd Bruegmann, 6/98
+C
+C Compute Thorne's four metric that, although not a solution to the
+C Einstein equations, has several characteristic features of a binary
+C star system. See gr-qc/98......
+
+#include "cctk.h"
+#include "cctk_parameters.h"
+
+ subroutine fakebinary(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz)
+
+ implicit none
+
+ DECLARE_CCTK_PARAMETERS
+
+C input
+ CCTK_REAL x, y, z, t
+
+C output
+ CCTK_REAL gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdxz,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guxz
+
+C static
+
+ logical firstcall
+
+ integer CCTK_Equals
+
+ CCTK_REAL eps, m, a0, omega0, bround, atype, aretarded
+
+ data firstcall /.true./
+ save firstcall, eps, m, a0, omega0, bround, atype, aretarded
+
+C temps
+ CCTK_REAL a, omega, tau, f
+ CCTK_REAL c, c0, c1, c2, c3
+ CCTK_REAL rho, r, sinp, cosp, phi, sint, cost, tx, ty, tz, px, py, pz
+ CCTK_REAL a2, b2, bx, by, bz, detgd
+
+C get parameters of the exact solution.
+
+ if (firstcall) then
+
+ firstcall = .false.
+
+ eps = fakebinary_eps
+ m = fakebinary_m
+ a0 = fakebinary_a0
+
+ omega0 = fakebinary_omega0
+ bround = fakebinary_bround
+
+ bround = max(bround, eps)
+
+ if (CCTK_Equals(fakebinary_atype,"constant").ne.0) then
+ atype = 0.d0
+ elseif (CCTK_Equals(fakebinary_atype,"quadrupole").ne.0) then
+ atype = 1.d0
+ else
+ call CCTK_Warn(0,"Unknown value of parameter fakebinary_atype")
+ endif
+
+ if (fakebinary_retarded.ne.0) then
+ aretarded = 1.d0
+ else
+ aretarded = 0.d0
+ endif
+
+ end if
+
+C spherical coordinates
+
+ rho = max(sqrt(x**2 + y**2), eps)
+ r = sqrt(rho**2 + z**2)
+ sinp = y / rho
+ cosp = x / rho
+ phi = acos(cosp)
+ sint = rho / r
+ cost = z / r
+ tx = cost*cosp
+ ty = cost*sinp
+ tz = sint
+ px = - sinp
+ py = cosp
+ pz = 0
+
+C distance function a(T-R)
+
+ tau = 5.d0/128.d0 * a0**4 / m**3
+ a = a0 * (1.d0 - atype * 4.d0*(t - aretarded*r)/tau)**(0.25d0)
+
+C orbital frequency omega(T-R)
+
+ omega = 0.5d0*(m/a**3)**2
+
+C 1/r type potential f
+
+ c = y**2 + z**2 + bround**2;
+ f = ((x-a)**2 + c)**(-0.5d0) + ((x+a)**2 + c)**(-0.5d0)
+
+C the three metric, tt part
+
+ c3 = 2.d0*(phi + omega*r)
+ c0 = - 4.d0 * m * a**2 * omega**3 * (omega*r)**4
+ . / (1 + (omega*r)**2)**(2.5d0)
+ c1 = (1 + cost**2) * cos(c3) * c0
+ c2 = - 2.d0 * cost * sin(c3) * c0
+ gdxx = c1 * (tx*tx - px*px) + c2 * (tx*px + px*tx)
+ gdxy = c1 * (tx*ty - px*py) + c2 * (tx*py + px*ty)
+ gdxz = c1 * (tx*tz - px*pz) + c2 * (tx*pz + px*tz)
+ gdyy = c1 * (ty*ty - py*py) + c2 * (ty*py + py*ty)
+ gdyz = c1 * (ty*tz - py*pz) + c2 * (ty*pz + py*tz)
+ gdzz = c1 * (tz*tz - pz*pz) + c2 * (tz*pz + pz*tz)
+
+C the three metric, add conformally flat part
+
+ c = (1.d0 + m * f)**2
+ gdxx = gdxx + c
+ gdyy = gdyy + c
+ gdzz = gdzz + c
+
+C the shift vector and covector
+
+ c = (1.d0 - 2*m*a**2/(r**2+a**2) * f) * omega * rho
+ bx = c * px
+ by = c * py
+ bz = c * pz
+ gdtx = gdxx*bx + gdxy*by + gdxz*bz
+ gdty = gdxy*bx + gdyy*by + gdyz*bz
+ gdtz = gdxz*bx + gdyz*by + gdzz*bz
+ b2 = gdtx*bx + gdty*by + gdtz*bz
+
+C lapse squard and time-time component of the four metric
+
+ a2 = (1.d0 - m * f)**2
+ gdtt = b2 - a2
+
+C done with metric, find its inverse
+C inverse three metric
+
+ detgd = -(gdxz**2*gdyy) + 2*gdxy*gdxz*gdyz - gdxx*gdyz**2
+ . - gdxy**2*gdzz - gdxx*gdyy*gdzz
+ guxx = (-gdyz**2 + gdyy*gdzz) / detgd
+ guxy = (gdxz*gdyz - gdxy*gdzz) / detgd
+ guxz = (-(gdxz*gdyy) + gdxy*gdyz) / detgd
+ guyy = (-gdxz**2 + gdxx*gdzz) / detgd
+ guyz = (gdxy*gdxz - gdxx*gdyz) / detgd
+ guzz = (-gdxy**2 + gdxx*gdyy) / detgd
+
+C inverse four metric
+
+ gutt = - 1.d0/a2
+ gutx = bx/a2
+ guty = by/a2
+ gutz = bz/a2
+ guxx = guxx - bx*bx/a2
+ guxy = guxy - bx*by/a2
+ guxz = guxz - bx*bz/a2
+ guyy = guyy - by*by/a2
+ guyz = guyz - by*bz/a2
+ guzz = guzz - bz*bz/a2
+
+C done!
+ return
+ end
diff --git a/src/finkelstein.F b/src/finkelstein.F
new file mode 100644
index 0000000..1e96fe9
--- /dev/null
+++ b/src/finkelstein.F
@@ -0,0 +1,66 @@
+#include "cctk.h"
+#include "cctk_parameters.h"
+
+ subroutine finkelstein(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx)
+
+ implicit none
+
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_REAL x, y, z, t
+ CCTK_REAL gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx
+
+ logical firstcall
+
+ CCTK_REAL eps, m
+
+ data firstcall /.true./
+ save firstcall, eps, m
+
+ CCTK_REAL r
+
+C Get parameters of the exact solution.
+
+ if (firstcall) then
+
+ eps = kerrschild_eps
+ m = kerrschild_m
+
+ firstcall = .false.
+
+ end if
+
+ r = max(sqrt(x**2 + y**2 + z**2), eps)
+
+ gdtt = - (1.d0 - 2.d0 * m / r)
+ gdtx = 2.d0 * m * x / r**2
+ gdty = 2.d0 * m * y / r**2
+ gdtz = 2.d0 * m * z / r**2
+ gdxx = 1.d0 + 2.d0 * m * x**2 / r**3
+ gdyy = 1.d0 + 2.d0 * m * y**2 / r**3
+ gdzz = 1.d0 + 2.d0 * m * z**2 / r**3
+ gdxy = 2.d0 * m * x * y / r**3
+ gdyz = 2.d0 * m * y * z / r**3
+ gdzx = 2.d0 * m * z * x / r**3
+
+ gutt = - (1.d0 + 2.d0 * m / r)
+ gutx = 2.d0 * m * x / r**2
+ guty = 2.d0 * m * y / r**2
+ gutz = 2.d0 * m * z / r**2
+ guxx = 1.d0 - 2.d0 * m * x**2 / r**3
+ guyy = 1.d0 - 2.d0 * m * y**2 / r**3
+ guzz = 1.d0 - 2.d0 * m * z**2 / r**3
+ guxy = - 2.d0 * m * x * y / r**3
+ guyz = - 2.d0 * m * y * z / r**3
+ guzx = - 2.d0 * m * z * x / r**3
+
+ return
+ end
diff --git a/src/flatschwarz.F b/src/flatschwarz.F
new file mode 100644
index 0000000..9566517
--- /dev/null
+++ b/src/flatschwarz.F
@@ -0,0 +1,70 @@
+#include "cctk.h"
+#include "cctk_parameters.h"
+
+ subroutine flatschwarz(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx)
+
+ implicit none
+
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_REAL x, y, z, t
+ CCTK_REAL gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx
+
+ logical firstcall
+
+ CCTK_REAL eps, m
+
+ data firstcall /.true./
+ save firstcall, eps, m
+
+ CCTK_REAL r, bx, by, bz, b2
+
+C Get parameters of the exact solution.
+
+ if (firstcall) then
+
+ eps = kerrschild_eps
+ m = kerrschild_m
+
+ firstcall = .false.
+
+ end if
+
+ r = max(sqrt(x**2 + y**2 + z**2), eps)
+ bx = sqrt(2.d0 * m / r) * x / r
+ by = sqrt(2.d0 * m / r) * y / r
+ bz = sqrt(2.d0 * m / r) * z / r
+ b2 = 2.d0 * m / r
+
+ gdtt = - 1.d0 + b2
+ gdtx = bx
+ gdty = by
+ gdtz = bz
+ gdxx = 1.d0
+ gdyy = 1.d0
+ gdzz = 1.d0
+ gdxy = 0.d0
+ gdyz = 0.d0
+ gdzx = 0.d0
+
+ gutt = - 1.d0
+ gutx = bx
+ guty = by
+ gutz = bz
+ guxx = 1.d0 - bx**2
+ guyy = 1.d0 - by**2
+ guzz = 1.d0 - bz**2
+ guxy = - bx * by
+ guyz = - by * bz
+ guzx = - bz * bx
+
+ return
+ end
diff --git a/src/include/pGF_ComparisonExtensions.h b/src/include/pGF_ComparisonExtensions.h
new file mode 100644
index 0000000..0cca003
--- /dev/null
+++ b/src/include/pGF_ComparisonExtensions.h
@@ -0,0 +1 @@
+ int do_comparison;
diff --git a/src/include/slice_normal.h b/src/include/slice_normal.h
new file mode 100644
index 0000000..4b41d85
--- /dev/null
+++ b/src/include/slice_normal.h
@@ -0,0 +1,103 @@
+C Fill in remaining components of metric.
+ do m=1,4
+ do n=1,m-1
+ gu(m,n) = gu(n,m)
+ gd(m,n) = gd(n,m)
+ end do
+ end do
+
+C Calculate normal vector with respect to the slice, with indices down,
+C and not yet normalized.
+C n_A = epsilon_ABCD X^A_,1 X^B_,2 X^C_,3.
+C Easiest to hardwired this with an editor.
+ nd(1) = s1d(2,1)*s1d(3,2)*s1d(4,3)
+ $ + s1d(3,1)*s1d(4,2)*s1d(2,3)
+ $ + s1d(4,1)*s1d(2,2)*s1d(3,3)
+ $ - s1d(2,1)*s1d(4,2)*s1d(3,3)
+ $ - s1d(4,1)*s1d(3,2)*s1d(2,3)
+ $ - s1d(3,1)*s1d(2,2)*s1d(4,3)
+
+ nd(2) = - s1d(3,1)*s1d(4,2)*s1d(1,3)
+ $ - s1d(4,1)*s1d(1,2)*s1d(3,3)
+ $ -s1d(1,1)*s1d(3,2)*s1d(4,3)
+ $ + s1d(3,1)*s1d(1,2)*s1d(4,3)
+ $ + s1d(1,1)*s1d(4,2)*s1d(3,3)
+ $ + s1d(4,1)*s1d(3,2)*s1d(1,3)
+
+ nd(3) = s1d(4,1)*s1d(1,2)*s1d(2,3)
+ $ + s1d(1,1)*s1d(2,2)*s1d(4,3)
+ $ + s1d(2,1)*s1d(4,2)*s1d(1,3)
+ $ - s1d(4,1)*s1d(2,2)*s1d(1,3)
+ $ - s1d(2,1)*s1d(1,2)*s1d(4,3)
+ $ - s1d(1,1)*s1d(4,2)*s1d(2,3)
+
+ nd(4) = s1d(1,1)*s1d(2,2)*s1d(3,3)
+ $ + s1d(2,1)*s1d(3,2)*s1d(1,3)
+ $ + s1d(3,1)*s1d(1,2)*s1d(2,3)
+ $ - s1d(1,1)*s1d(3,2)*s1d(2,3)
+ $ - s1d(3,1)*s1d(2,2)*s1d(1,3)
+ $ - s1d(2,1)*s1d(1,2)*s1d(3,3)
+
+C Normalize normal vector and raise its index, both with the exact
+C solution metric.
+C - N^2 = g^AB n_A n_B).
+ norm = 0.d0
+ do m=1,4
+ do n=1,4
+ norm = norm + nd(m) * nd(n) * gu(m,n)
+ end do
+ end do
+C Debugging test.
+ if (norm .ge. 0.d0) then
+ write(6,*) 'slice normal no longer timelike'
+ write(6,*) 'grid point', i, j, k
+ write(6,*) 'x^i', x(i,j,k), y(i,j,k), z(i,j,k)
+ write(6,*) 'x^A', slicex(i,j,k), slicey(i,j,k),
+ $ slicez(i,j,k), slicet(i,j,k)
+ write(6,*) 'n_A', nd(1), nd(2), nd(3), nd(4)
+ write(6,*) 'n_A n^A', norm
+ write(6,*) 'dx^A/dx^i'
+ do m=1,4
+ do n=1,3
+ write(6,*) m, n, s1d(m,n)
+ end do
+ end do
+ write(6,*) 'g^AB'
+ do m=1,4
+ do n=1,4
+ write(6,*) m, n, gu(m,n)
+ end do
+ end do
+ STOP
+ end if
+C And now n^A = - 1/N g^AB n_B. (Sign so that it is future-pointing.)
+ do m=1,4
+ nu(m) = 0.d0
+ do n=1,4
+ nu(m) = nu(m) + gu(m,n) * nd(n)
+ end do
+ nu(m) = - nu(m) / sqrt(-norm)
+ end do
+
+C dX^A/dt = alpha n^A + beta^i X^A_,i. Store as a GF.
+ slicetmp2x(i,j,k) = alp(i,j,k) * nu(1)
+ $ + betax(i,j,k) * s1d(1,1)
+ $ + betay(i,j,k) * s1d(1,2)
+ $ + betaz(i,j,k) * s1d(1,3)
+
+ slicetmp2y(i,j,k) = alp(i,j,k) * nu(2)
+ $ + betax(i,j,k) * s1d(2,1)
+ $ + betay(i,j,k) * s1d(2,2)
+ $ + betaz(i,j,k) * s1d(2,3)
+
+ slicetmp2z(i,j,k) = alp(i,j,k) * nu(3)
+ $ + betax(i,j,k) * s1d(3,1)
+ $ + betay(i,j,k) * s1d(3,2)
+ $ + betaz(i,j,k) * s1d(3,3)
+
+ slicetmp2t(i,j,k) = alp(i,j,k) * nu(4)
+ $ + betax(i,j,k) * s1d(4,1)
+ $ + betay(i,j,k) * s1d(4,2)
+ $ + betaz(i,j,k) * s1d(4,3)
+
+
diff --git a/src/kerrschild.F b/src/kerrschild.F
new file mode 100644
index 0000000..2c37b37
--- /dev/null
+++ b/src/kerrschild.F
@@ -0,0 +1,127 @@
+#include "cctk.h"
+#include "cctk_parameters.h"
+
+C Kerr-Schild form of boosted rotating black hole.
+C Program g_ab = eta_ab + H l_a l_b, g^ab = eta^ab - H l^a l^b.
+C Here eta_ab is Minkowski in Cartesian coordinates, H is a scalar,
+C and l is a null vector.
+
+ subroutine kerrschild(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx)
+
+ implicit none
+
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_REAL x, y, z, t
+ CCTK_REAL gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx
+
+ CCTK_REAL gamma, t0, z0, x0, y0, rho02, r02, r0, costheta0,
+ $ lt0, lx0, ly0, lz0, hh, lt, lx, ly, lz
+
+ logical firstcall
+ CCTK_REAL boostv, eps, m, a
+ data firstcall /.true./
+ save firstcall, boostv, eps, m, a
+
+
+C Get parameters of the exact solution.
+
+ if (firstcall) then
+
+ boostv = kerrschild_boostv
+ eps = kerrschild_eps
+
+ m = kerrschild_m
+ a = kerrschild_a
+
+ firstcall = .false.
+
+ end if
+
+C Boost factor.
+
+ gamma = 1.d0 / sqrt(1.d0 - boostv**2)
+
+C Lorentz transform t,x,y,z -> t0,x0,y0,z0.
+C t0 is never used, but is here for illustration, and we introduce
+C x0 and y0 also only for clarity.
+C Note that z0 = 0 means z = vt for the BH.
+
+ t0 = gamma * (t - boostv * z)
+ z0 = gamma * (z - boostv * t)
+ x0 = x
+ y0 = y
+
+C Coordinate distance to center of black hole. Note it moves!
+
+ rho02 = x0**2 + y0**2 + z0**2
+
+C Spherical auxiliary coordinate r and angle theta in BH rest frame.
+
+ r02 = 0.5d0 * (rho02 - a**2)
+ $ + sqrt(0.25d0 * (rho02 - a**2)**2 + a**2 * z0**2)
+ if (r02 .lt. eps) then
+ write(6,*) 'r02 too small in kerrschild'
+ write(6,*) x0, y0, z0
+ write(6,*) rho02, a**2, r02
+ end if
+ r02 = max(r02,eps)
+ r0 = sqrt(r02)
+ costheta0 = z0 / r0
+
+C Coefficient H. Note this transforms as a scalar, so does not carry
+C the suffix 0.
+ hh = m * r0 / (r0**2 + a**2 * costheta0**2)
+
+C Components of l_a in rest frame. Note indices down.
+ lt0 = 1.d0
+ lx0 = (r0 * x0 + a * y0) / (r0**2 + a**2)
+ ly0 = (r0 * y0 - a * x0) / (r0**2 + a**2)
+ lz0 = z0 / r0
+
+C Now boost it to coordinates x, y, z, t.
+C This is the reverse Lorentz transformation, but applied
+C to a one-form, so the sign of boostv is the same as the forward
+C Lorentz transformation applied to the coordinates.
+
+ lt = gamma * (lt0 - boostv * lz0)
+ lz = gamma * (lz0 - boostv * lt0)
+ lx = lx0
+ ly = ly0
+
+C Down metric. g_ab = flat_ab + H l_a l_b
+
+ gdtt = - 1.d0 + 2.d0 * hh * lt * lt
+ gdtx = 2.d0 * hh * lt * lx
+ gdty = 2.d0 * hh * lt * ly
+ gdtz = 2.d0 * hh * lt * lz
+ gdxx = 1.d0 + 2.d0 * hh * lx * lx
+ gdyy = 1.d0 + 2.d0 * hh * ly * ly
+ gdzz = 1.d0 + 2.d0 * hh * lz * lz
+ gdxy = 2.d0 * hh * lx * ly
+ gdyz = 2.d0 * hh * ly * lz
+ gdzx = 2.d0 * hh * lz * lx
+
+C Up metric. g^ab = flat^ab - H l^a l^b.
+C Notice that g^ab = g_ab and l^i = l_i and l^0 = - l_0 in flat spacetime.
+ gutt = - 1.d0 - 2.d0 * hh * lt * lt
+ gutx = 2.d0 * hh * lt * lx
+ guty = 2.d0 * hh * lt * ly
+ gutz = 2.d0 * hh * lt * lz
+ guxx = 1.d0 - 2.d0 * hh * lx * lx
+ guyy = 1.d0 - 2.d0 * hh * ly * ly
+ guzz = 1.d0 - 2.d0 * hh * lz * lz
+ guxy = - 2.d0 * hh * lx * ly
+ guyz = - 2.d0 * hh * ly * lz
+ guzx = - 2.d0 * hh * lz * lx
+
+ return
+ end
diff --git a/src/linextraponebound.F b/src/linextraponebound.F
new file mode 100644
index 0000000..09a2ea7
--- /dev/null
+++ b/src/linextraponebound.F
@@ -0,0 +1,140 @@
+#include "cctk.h"
+#include "cctk_arguments.h"
+
+ subroutine linextraponebound(CCTK_FARGUMENTS,var)
+
+ implicit none
+
+ DECLARE_CCTK_FARGUMENTS
+
+ integer nx,ny,nz
+
+ CCTK_REAL var(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3))
+
+C Grid parameters.
+
+ nx = cctk_lsh(1)
+ ny = cctk_lsh(2)
+ nz = cctk_lsh(3)
+
+C Linear extrapolation from the interiors to the boundaries.
+C Does not support octant or quadrant.
+
+C 6 faces.
+
+ if (cctk_bbox(1).eq.1 .and. nx.ge.4 ) then
+ var(1,:,:) = 2.d0 * var(2,:,:) - var(3,:,:)
+ endif
+ if (cctk_bbox(3).eq.1 .and. ny.ge.4 ) then
+ var(:,1,:) = 2.d0 * var(:,2,:) - var(:,3,:)
+ endif
+ if (cctk_bbox(5).eq.1 .and. nz.ge.4 ) then
+ var(:,:,1) = 2.d0 * var(:,:,2) - var(:,:,3)
+ endif
+ if (cctk_bbox(2).eq.1 .and. nx.ge.4 ) then
+ var(nx,:,:) = 2.d0 * var(nx-1,:,:) - var(nx-2,:,:)
+ endif
+ if (cctk_bbox(4).eq.1 .and. ny.ge.4 ) then
+ var(:,ny,:) = 2.d0 * var(:,ny-1,:) - var(:,ny-2,:)
+ endif
+ if (cctk_bbox(6).eq.1 .and. nz.ge.4 ) then
+ var(:,:,nz) = 2.d0 * var(:,:,nz-1) - var(:,:,nz-2)
+ endif
+
+C 12 edges.
+C 4 round face x=min.
+ if ( cctk_bbox(1).eq.1 .and. nx.ge.4
+ $ .and. cctk_bbox(3).eq.1 .and. ny.ge.4 ) then
+ var(1,1,:) = 2.d0 * var(2,2,:) - var(3,3,:)
+ end if
+
+ if ( cctk_bbox(1).eq.1 .and. nx.ge.4
+ $ .and. cctk_bbox(4).eq.1 .and. ny.ge.4 ) then
+ var(1,ny,:) = 2.d0 * var(2,ny-1,:) - var(2,ny-2,:)
+ end if
+
+ if ( cctk_bbox(1).eq.1 .and. nx.ge.4
+ $ .and. cctk_bbox(5).eq.1 .and. nz.ge.4 ) then
+ var(1,:,1) = 2.d0 * var(2,:,2) - var(3,:,3)
+ end if
+
+ if ( cctk_bbox(1).eq.1 .and. nx.ge.4
+ $ .and. cctk_bbox(6).eq.1 .and. nz.ge.4 ) then
+ var(1,:,nz) = 2.d0 * var(2,:,nz-1) - var(3,:,nz-2)
+ end if
+
+C 4 around face x=max.
+ if ( cctk_bbox(2).eq.1 .and. nx.ge.4
+ $ .and. cctk_bbox(3).eq.1 .and. ny.ge.4 ) then
+ var(nx,1,:) = 2.d0 * var(nx-1,2,:) - var(nx-2,3,:)
+ end if
+
+ if ( cctk_bbox(2).eq.1 .and. nx.ge.4
+ $ .and. cctk_bbox(4).eq.1 .and. ny.ge.4 ) then
+ var(nx,ny,:) = 2.d0 * var(nx-1,ny-1,:) - var(nx-2,ny-2,:)
+ end if
+
+ if ( cctk_bbox(2).eq.1 .and. nx.ge.4
+ $ .and. cctk_bbox(5).eq.1 .and. nz.ge.4 ) then
+ var(nx,:,1) = 2.d0 * var(nx-1,:,2) - var(nx-2,:,3)
+ end if
+
+ if ( cctk_bbox(2).eq.1 .and. nx.ge.4
+ $ .and. cctk_bbox(6).eq.1 .and. nz.ge.4 ) then
+ var(nx,:,nz) = 2.d0 * var(nx-1,:,nz-1) - var(nx-2,:,nz-2)
+ end if
+
+C Remaining 2 in y=min.
+ if ( cctk_bbox(3).eq.1 .and. ny.ge.4
+ $ .and. cctk_bbox(5).eq.1 .and. nz.ge.4 ) then
+ var(:,1,1) = 2.d0 * var(:,2,2) - var(:,3,3)
+ end if
+
+ if ( cctk_bbox(3).eq.1 .and. ny.ge.4
+ $ .and. cctk_bbox(6).eq.1 .and. nz.ge.4 ) then
+ var(:,1,nz) = 2.d0 * var(:,2,nz-1) - var(:,2,nz-2)
+ end if
+
+C Remaining 2 in y=ymax.
+ if ( cctk_bbox(4).eq.1 .and. ny.ge.4
+ $ .and. cctk_bbox(5).eq.1 .and. nz.ge.4 ) then
+ var(:,ny,1) = 2.d0 * var(:,ny-1,2) - var(:,ny-2,3)
+ end if
+
+ if ( cctk_bbox(4).eq.1 .and. ny.ge.4
+ $ .and. cctk_bbox(6).eq.1 .and. nz.ge.4 ) then
+ var(:,ny,nz) = 2.d0 * var(:,ny-1,nz-1) - var(:,ny-2,nz-2)
+ end if
+
+C 8 corners.
+
+ if (nx.ge.4 .and. ny.ge.4 .and. nz.ge.4) then
+ if (cctk_bbox(1).eq.1 .and. cctk_bbox(3).eq.1 .and. cctk_bbox(5).eq.1) then
+ var(1,1,1) = 2.d0*var(2,2,2) - var(3,3,3)
+ end if
+ if (cctk_bbox(1).eq.1 .and. cctk_bbox(3).eq.1 .and. cctk_bbox(6).eq.1) then
+ var(1,1,nz) = 2.d0*var(2,2,nz-1) - var(3,3,nz-2)
+ end if
+ if (cctk_bbox(1).eq.1 .and. cctk_bbox(4).eq.1 .and. cctk_bbox(5).eq.1) then
+ var(1,ny,1) = 2.d0*var(2,ny-1,2) - var(3,ny-2,3)
+ end if
+ if (cctk_bbox(1).eq.1 .and. cctk_bbox(4).eq.1 .and. cctk_bbox(6).eq.1) then
+ var(1,ny,nz) = 2.d0*var(2,ny-1,nz-1) - var(3,ny-2,nz-2)
+ end if
+ if (cctk_bbox(2).eq.1 .and. cctk_bbox(3).eq.1 .and. cctk_bbox(5).eq.1) then
+ var(nx,1,1) = 2.d0*var(nx-1,2,2) - var(nx-2,3,3)
+ end if
+ if (cctk_bbox(2).eq.1 .and. cctk_bbox(3).eq.1 .and. cctk_bbox(6).eq.1) then
+ var(nx,1,nz) = 2.d0*var(nx-1,2,nz-1) - var(nx-2,3,nz-2)
+ end if
+ if (cctk_bbox(2).eq.1 .and. cctk_bbox(4).eq.1 .and. cctk_bbox(5).eq.1) then
+ var(nx,ny,1) = 2.d0*var(nx-1,ny-1,2) - var(nx-2,ny-2,3)
+ end if
+ if (cctk_bbox(2).eq.1 .and. cctk_bbox(4).eq.1 .and. cctk_bbox(6).eq.1) then
+ var(nx,ny,nz) = 2.d0*var(nx-1,ny-1,nz-1) - var(nx-2,ny-2,nz-2)
+ end if
+ end if
+
+
+ return
+ end
diff --git a/src/make.code.defn b/src/make.code.defn
new file mode 100644
index 0000000..c3a4561
--- /dev/null
+++ b/src/make.code.defn
@@ -0,0 +1,15 @@
+# Main make.code.defn file for thorn Exact
+# $Header$
+
+# Source files in this directory
+SRCS = exactinitialize.F exactgauge.F exactboundary.F \
+ exactdata.F exactmetric.F \
+ boostrotmetric.F finkelstein.F kerrschild.F flatschwarz.F \
+ starschwarz.F bowl.F novikov.F minkowski.F fakebinary.F multiBH.F\
+ exactblendbound.F exactcartblendbound.F \
+ slice_initialize.F slice_evolve.F slice_data.F linextraponebound.F
+# ComparisonSolutions.F Comparison.c
+
+# Subdirectories containing source files
+SUBDIRS =
+
diff --git a/src/minkowski.F b/src/minkowski.F
new file mode 100644
index 0000000..ed76b17
--- /dev/null
+++ b/src/minkowski.F
@@ -0,0 +1,46 @@
+#include "cctk.h"
+
+ subroutine minkowski(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx)
+
+ implicit none
+
+c Input.
+
+ CCTK_REAL x, y, z, t
+
+c Output.
+
+ CCTK_REAL gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx
+
+ gdtt = -1.d0
+ gdtx = 0.d0
+ gdty = 0.d0
+ gdtz = 0.d0
+ gdxx = 1.d0
+ gdyy = 1.d0
+ gdzz = 1.d0
+ gdxy = 0.d0
+ gdyz = 0.d0
+ gdzx = 0.d0
+
+ gutt = -1.d0
+ gutx = 0.d0
+ guty = 0.d0
+ gutz = 0.d0
+ guxx = 1.d0
+ guyy = 1.d0
+ guzz = 1.d0
+ guxy = 0.d0
+ guyz = 0.d0
+ guzx = 0.d0
+
+ return
+ end
diff --git a/src/multiBH.F b/src/multiBH.F
new file mode 100644
index 0000000..51f9b25
--- /dev/null
+++ b/src/multiBH.F
@@ -0,0 +1,133 @@
+c=======================================================================
+c23456789012345678901234567890123456789012345678901234567890123456789012
+c-----------------------------------------------------------------------
+c by Hisaaki Shinkai shinkai@wurel.wustl.edu 19980603
+c-----------------------------------------------------------------------
+c This is for maximally charged multi BH solutions such as
+c Majumdar-Papapetrou (1947) or Kastor-Traschen (1993) solution.
+c See also doc/KTsol.tex for brief review of this solution.
+c-----------------------------------------------------------------------
+c For usage: in your par file
+c exactmodel = "multiBH"
+c kt_hubble = 0.0 # 0.0 means MP solution
+c kt_nBH = 2 # number of BHs (upto 4, currently)
+c m_bh1,co_bh1x,co_bh1y,co_bh1z = 1.0, -2.0,0.0,0.0 # masses and
+c m_bh2,co_bh2x,co_bh2y,co_bh2z = 1.0, 2.0,0.0,0.0 # locations
+c-----------------------------------------------------------------------
+
+#include "cctk.h"
+#include "cctk_parameters.h"
+
+ subroutine multi_BHs(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx)
+
+ implicit none
+
+ DECLARE_CCTK_PARAMETERS
+
+c Input.
+ CCTK_REAL x, y, z, t
+
+c Output.
+ CCTK_REAL gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx
+
+ logical firstcall
+
+ CCTK_REAL kt_r, kt_aa, kt_omega
+ CCTK_REAL one,zero
+ CCTK_REAL kt_xbh(10),kt_ybh(10),kt_zbh(10),kt_mbh(10)
+
+ integer i
+
+ data firstcall /.true./
+ save firstcall,kt_xbh,kt_ybh,kt_zbh,kt_mbh
+
+c Get parameters of the exact solution.
+
+ if (firstcall) then
+
+ write(*,*) ' welcome to Kastor-Traschen (Majumdar-Papapetrou)'
+
+ if(kt_nBH.ge.1) then
+ kt_xbh(1) = co_bh1x
+ kt_ybh(1) = co_bh1y
+ kt_zbh(1) = co_bh1z
+ kt_mbh(1) = m_bh1
+ endif
+
+ if(kt_nBH.ge.2) then
+ kt_xbh(2) = co_bh2x
+ kt_ybh(2) = co_bh2y
+ kt_zbh(2) = co_bh2z
+ kt_mbh(2) = m_bh2
+ endif
+
+ if(kt_nBH.ge.3) then
+ kt_xbh(3) = co_bh3x
+ kt_ybh(3) = co_bh3y
+ kt_zbh(3) = co_bh3z
+ kt_mbh(3) = m_bh3
+ endif
+
+ if(kt_nBH.ge.4) then
+ kt_xbh(4) = co_bh4x
+ kt_ybh(4) = co_bh4y
+ kt_zbh(4) = co_bh4z
+ kt_mbh(4) = m_bh4
+ endif
+
+ write(*,*) 'time=',t
+ write(*,*) ' mass BH(x,y,z) '
+
+ do i=1,kt_nBH
+ write(*,'(4e12.3)') kt_mbh(i),kt_xbh(i),kt_ybh(i),kt_zbh(i)
+ enddo
+
+ firstcall = .false.
+
+ end if
+
+ one =1.0
+ zero=0.0
+
+ kt_aa=exp(kt_hubble*t)
+ kt_omega=1.0
+
+ do i=1,kt_nBH
+ kt_r=sqrt((x-kt_xbh(i))**2+(y-kt_ybh(i))**2+(z-kt_zbh(i))**2)
+ kt_omega= kt_omega+kt_mbh(i)/kt_aa/kt_r
+ enddo
+
+c write(*,*) kt_omega,kt_aa
+
+ gdtt = -1.0/kt_omega**2
+ gdtx = zero
+ gdty = zero
+ gdtz = zero
+ gdxx = (kt_aa*kt_omega)**2
+ gdyy = (kt_aa*kt_omega)**2
+ gdzz = (kt_aa*kt_omega)**2
+ gdxy = zero
+ gdyz = zero
+ gdzx = zero
+
+ gutt = one/gdtt
+ gutx = zero
+ guty = zero
+ gutz = zero
+ guxx = one/gdxx
+ guyy = one/gdyy
+ guzz = one/gdzz
+ guxy = zero
+ guyz = zero
+ guzx = zero
+
+ return
+ end
diff --git a/src/novikov.F b/src/novikov.F
new file mode 100644
index 0000000..0b5120c
--- /dev/null
+++ b/src/novikov.F
@@ -0,0 +1,201 @@
+#include "cctk.h"
+#include "cctk_parameters.h"
+
+ subroutine novikov(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx)
+
+c The metric given here corresponds to the novikov solution
+c in isotropic coordinates, as presented first in Bruegman96
+c then in correct form in Cactus paper 1. This code is the code
+c which was used for the comparisons in cactus paper 1, and is written
+c by PW with input from BB.
+
+ implicit none
+
+ DECLARE_CCTK_PARAMETERS
+
+c Input.
+
+ CCTK_REAL x, y, z, t
+
+c Output.
+
+ CCTK_REAL gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx
+
+c Internal.
+
+ logical firstcall
+
+ CCTK_REAL mass,radius
+ CCTK_REAL r,c,psi4
+ CCTK_REAL zero,one,two
+
+ CCTK_REAL nov_dr_drmax, nov_rmax, nov_r
+ CCTK_REAL grr, gqq, detg
+
+ CCTK_REAL psi4_o_r2
+
+ data firstcall /.true./
+ save firstcall
+
+c Find {zero,one,two}.
+
+ zero = 0.0D0
+ one = 1.0D0
+ two = 2.0D0
+
+c Get parameters of the metric. (just the mass)
+ mass = 1.0D0
+
+c Find r.
+ r = dsqrt(x**2 + y**2 + z**2)
+
+c Find conformal factor.
+ c = mass/(two*r)
+ psi4 = (one + c)**4
+
+c Evaluate novikov stuff. Note abs(t) since the data is time
+c symmetric (the metric is, at least...)
+ grr = nov_dr_drmax(abs(t),abs(r))
+ gqq = nov_r(abs(t),abs(r))
+
+ grr = grr **2
+ gqq = gqq**2 / nov_rmax(abs(r))**2
+
+
+c Find metric components.
+ psi4_o_r2 = psi4 / r**2
+
+ gdtt = - 1.0D0
+
+ gdtx = zero
+ gdty = zero
+ gdtz = zero
+
+c This is just straightforward spherical -> cartesian I hope... ;-)
+c Note at t=0 (grr = gqq = 1) this gives the expected result
+c (namely diagonal psi^4, since psi4_o_r2 = psi^4 / r^2)
+ gdxx = (grr * x**2 + gqq * (y**2 + z**2)) * psi4_o_r2
+ gdyy = (grr * y**2 + gqq * (x**2 + z**2)) * psi4_o_r2
+ gdzz = (grr * z**2 + gqq * (x**2 + y**2)) * psi4_o_r2
+
+ gdxy = (grr - gqq) * x * y * psi4_o_r2
+ gdzx = (grr - gqq) * x * z * psi4_o_r2
+ gdyz = (grr - gqq) * y * z * psi4_o_r2
+
+c Find inverse metric.
+ gutt = one/gdtt
+ gutx = zero
+ guty = zero
+ gutz = zero
+ detg = gdtt*gdxx*gdyy*gdzz-gdtt*gdxx*gdyz**2/4.D0-gdtt*gdxy**2*gdz
+ $z/4.D0+gdtt*gdxy*gdzx*gdyz/4.D0-gdtt*gdzx**2*gdyy/4.D0
+ guxx = -gdtt*(-4.D0*gdyy*gdzz+gdyz**2)/(4.D0 * detg)
+ guxy = -gdtt*(2.D0*gdxy*gdzz-gdzx*gdyz)/(4.D0 * detg)
+ guzx = gdtt*(gdxy*gdyz-2.D0*gdzx*gdyy)/(4.D0 * detg)
+ guyy = gdtt*(4.D0*gdxx*gdzz-gdzx**2)/(4.D0 * detg)
+ guyz = -gdtt*(2.D0*gdxx*gdyz-gdxy*gdzx)/(4.D0 * detg)
+ guzz = gdtt*(4.D0*gdxx*gdyy-gdxy**2)/(4.D0 * detg)
+
+ guxx = one/psi4
+ guyy = one/psi4
+ guzz = one/psi4
+
+ guxy = zero
+ guyz = zero
+ guzx = zero
+
+ return
+ end
+
+c These are functions which evaluate the novikov stuff.
+
+c dr/drmax
+ CCTK_REAL function nov_dr_drmax(tauin,rbarin)
+
+ implicit none
+
+ CCTK_REAL rbarin, tauin
+ CCTK_REAL rt, nov_r, rmaxt, nov_rmax
+
+ rt = nov_r(tauin, rbarin)
+ rmaxt = nov_rmax(rbarin)
+ nov_dr_drmax = 1.5D0 - rt / (2.0D0 * rmaxt) +
+ $ 1.5D0 * sqrt(rmaxt / rt - 1.0D0) *
+ $ acos(sqrt(rt/rmaxt))
+
+ return
+ end
+
+
+
+
+c Bisection to invert the function below. This is pretty crappy
+c but it works.
+ CCTK_REAL function nov_r(tauin, rbarin)
+ implicit none
+c input
+ CCTK_REAL tauin, rbarin
+
+c funtions
+ CCTK_REAL nov_rmax, nov_tau
+
+c temps
+ CCTK_REAL rg, drg, delt, ttmp, rmt
+ CCTK_REAL eps
+ integer nit
+ nit = 0
+ delt = 1000.0D0
+ rmt = nov_rmax(rbarin)
+ rg = rmt
+ drg = rg / 2.0D0
+ eps = 1.d-6 * rmt
+ do while (delt .gt. eps .and. nit .lt. 100)
+ ttmp = nov_tau(rg, rmt)
+ delt = abs(tauin - ttmp)
+ if (delt .gt. eps) then
+ if (ttmp .gt. tauin .or. rg .lt. drg) then
+ rg = rg + drg
+c Enforce upper bound
+ if (rg .gt. rmt) rg = rmt
+ drg = drg / 2.0D0
+ else
+ rg = rg - drg
+ endif
+ endif
+c write (*,*) rg, ttmp, tauin
+ nit = nit + 1
+ enddo
+ if (nit .ge. 100) then
+ write (*,*) "Novikov: inversion did not converge"
+ endif
+ nov_r = rg
+ return
+ end
+
+c Evaluate tau as a function of r and rmax
+ CCTK_REAL function nov_tau(r, rmax)
+ implicit none
+ CCTK_REAL r, rmax
+
+ nov_tau= rmax * dsqrt(0.5D0 * r * (1.0D0 - r / rmax)) +
+ $ 2.0D0 * (rmax / 2)**(3.0/2.0) *
+ $ acos (dsqrt(r/rmax))
+
+ return
+ end
+
+c Evaluate rmax as a function of rbar
+ CCTK_REAL function nov_rmax(rbar)
+ implicit none
+ CCTK_REAL rbar
+ nov_rmax = (1.0D0 + 2.0D0*rbar)**2 / (4.0D0 * rbar)
+ return
+ end
diff --git a/src/slice_data.F b/src/slice_data.F
new file mode 100644
index 0000000..33e0140
--- /dev/null
+++ b/src/slice_data.F
@@ -0,0 +1,327 @@
+C Extract Cauchy data from the slice x^A(x^i) stored in slicex,
+C slicey, slicez, slicet, and calculate dx^A/dt.
+
+#include "cctk.h"
+#include "cctk_arguments.h"
+
+ subroutine slice_data(CCTK_FARGUMENTS)
+
+ implicit none
+
+ DECLARE_CCTK_FARGUMENTS
+
+ integer i, j, k, l, m, n, p, q, s
+ integer nx,ny,nz
+
+ CCTK_REAL s1d(4,3), nd(4), nu(4), norm, gd(4,4), gu(4,4), g3(3,3),
+ $ gd_p(4,4), gd_m(4,4), gd1d(4,4,4), s2d(4,3,3), h3(3,3),
+ $ ex_eps, d3(3,3,3)
+
+ CCTK_REAL dx,dy,dz
+
+ parameter (ex_eps=1.d-6)
+
+C Grid parameters.
+
+ nx = cctk_lsh(1)
+ ny = cctk_lsh(2)
+ nz = cctk_lsh(3)
+
+ dx = cctk_delta_space(1)
+ dy = cctk_delta_space(2)
+ dz = cctk_delta_space(3)
+
+C Sum over interior points on the slice.
+
+ do k=2,nz-1
+ do j=2,ny-1
+ do i=2,nx-1
+
+C Calculate first derivatives of slice coordinates.
+
+ s1d(1,1) = 0.5d0 * (slicex(i+1,j,k) - slicex(i-1,j,k))/dx
+ s1d(1,2) = 0.5d0 * (slicex(i,j+1,k) - slicex(i,j-1,k))/dy
+ s1d(1,3) = 0.5d0 * (slicex(i,j,k+1) - slicex(i,j,k-1))/dz
+
+ s1d(2,1) = 0.5d0 * (slicey(i+1,j,k) - slicey(i-1,j,k))/dx
+ s1d(2,2) = 0.5d0 * (slicey(i,j+1,k) - slicey(i,j-1,k))/dy
+ s1d(2,3) = 0.5d0 * (slicey(i,j,k+1) - slicey(i,j,k-1))/dz
+
+ s1d(3,1) = 0.5d0 * (slicez(i+1,j,k) - slicez(i-1,j,k))/dx
+ s1d(3,2) = 0.5d0 * (slicez(i,j+1,k) - slicez(i,j-1,k))/dy
+ s1d(3,3) = 0.5d0 * (slicez(i,j,k+1) - slicez(i,j,k-1))/dz
+
+ s1d(4,1) = 0.5d0 * (slicet(i+1,j,k) - slicet(i-1,j,k))/dx
+ s1d(4,2) = 0.5d0 * (slicet(i,j+1,k) - slicet(i,j-1,k))/dy
+ s1d(4,3) = 0.5d0 * (slicet(i,j,k+1) - slicet(i,j,k-1))/dz
+
+C Now we need the exact solution metric in the preferred coordinates x^A.
+
+ call exactmetric(
+ $ slicex(i,j,k), slicey(i,j,k), slicez(i,j,k),
+ $ slicet(i,j,k),
+ $ gd(4,4), gd(1,4), gd(2,4), gd(3,4),
+ $ gd(1,1), gd(2,2), gd(3,3),
+ $ gd(1,2), gd(2,3), gd(1,3),
+ $ gu(4,4), gu(1,4), gu(2,4), gu(3,4),
+ $ gu(1,1), gu(2,2), gu(3,3),
+ $ gu(1,2), gu(2,3), gu(1,3))
+
+C Calculate n^A and dx^A/dt
+
+#include "include/slice_normal.h"
+
+C Calculate g_ij = X^A,i X^B,j g_AB, at first in a temp.
+
+ g3 = 0.d0
+
+ do p=1,3
+ do q=p,3
+ do m=1,4
+ do n=1,4
+ g3(p,q) = g3(p,q)
+ $ + s1d(m,p) * s1d(n,q) * gd(m,n)
+ end do
+ end do
+ end do
+ end do
+
+ gxx(i,j,k) = g3(1,1)
+ gxy(i,j,k) = g3(1,2)
+ gxz(i,j,k) = g3(1,3)
+ gyy(i,j,k) = g3(2,2)
+ gyz(i,j,k) = g3(2,3)
+ gzz(i,j,k) = g3(3,3)
+
+C Calculate x^A,ij. Do this by hand, and loop over first index
+C with an editor (hint for proofreading).
+
+ s2d(1,1,1) = (slicex(i+1,j,k) + slicex(i-1,j,k)
+ $ - 2.d0 * slicex(i,j,k)) / dx**2
+ s2d(1,2,2) = (slicex(i,j+1,k) + slicex(i,j-1,k)
+ $ - 2.d0 * slicex(i,j,k)) / dy**2
+ s2d(1,3,3) = (slicex(i,j,k+1) + slicex(i,j,k-1)
+ $ - 2.d0 * slicex(i,j,k)) / dz**2
+ s2d(1,1,2) = (slicex(i+1,j+1,k) - slicex(i-1,j+1,k)
+ $ - slicex(i+1,j-1,k) + slicex(i-1,j-1,k)) / (4.*dx*dy)
+ s2d(1,1,3) = (slicex(i+1,j,k+1) - slicex(i-1,j,k+1)
+ $ - slicex(i+1,j,k-1) + slicex(i-1,j,k-1)) / (4.*dy*dz)
+ s2d(1,2,3) = (slicex(i,j+1,k+1) - slicex(i,j-1,k+1)
+ $ - slicex(i,j+1,k-1) + slicex(i,j-1,k-1)) / (4.*dx*dz)
+ s2d(1,2,1) = s2d(1,1,2)
+ s2d(1,3,2) = s2d(1,2,3)
+ s2d(1,3,1) = s2d(1,1,3)
+
+ s2d(2,1,1) = (slicey(i+1,j,k) + slicey(i-1,j,k)
+ $ - 2.d0 * slicey(i,j,k)) / dx**2
+ s2d(2,2,2) = (slicey(i,j+1,k) + slicey(i,j-1,k)
+ $ - 2.d0 * slicey(i,j,k)) / dy**2
+ s2d(2,3,3) = (slicey(i,j,k+1) + slicey(i,j,k-1)
+ $ - 2.d0 * slicey(i,j,k)) / dz**2
+ s2d(2,1,2) = (slicey(i+1,j+1,k) - slicey(i-1,j+1,k)
+ $ - slicey(i+1,j-1,k) + slicey(i-1,j-1,k)) / (4.*dx*dy)
+ s2d(2,1,3) = (slicey(i+1,j,k+1) - slicey(i-1,j,k+1)
+ $ - slicey(i+1,j,k-1) + slicey(i-1,j,k-1)) / (4.*dy*dz)
+ s2d(2,2,3) = (slicey(i,j+1,k+1) - slicey(i,j-1,k+1)
+ $ - slicey(i,j+1,k-1) + slicey(i,j-1,k-1)) / (4.*dx*dz)
+ s2d(2,2,1) = s2d(2,1,2)
+ s2d(2,3,2) = s2d(2,2,3)
+ s2d(2,3,1) = s2d(2,1,3)
+
+ s2d(3,1,1) = (slicez(i+1,j,k) + slicez(i-1,j,k)
+ $ - 2.d0 * slicez(i,j,k)) / dx**2
+ s2d(3,2,2) = (slicez(i,j+1,k) + slicez(i,j-1,k)
+ $ - 2.d0 * slicez(i,j,k)) / dy**2
+ s2d(3,3,3) = (slicez(i,j,k+1) + slicez(i,j,k-1)
+ $ - 2.d0 * slicez(i,j,k)) / dz**2
+ s2d(3,1,2) = (slicez(i+1,j+1,k) - slicez(i-1,j+1,k)
+ $ - slicez(i+1,j-1,k) + slicez(i-1,j-1,k)) / (4.*dx*dy)
+ s2d(3,1,3) = (slicez(i+1,j,k+1) - slicez(i-1,j,k+1)
+ $ - slicez(i+1,j,k-1) + slicez(i-1,j,k-1)) / (4.*dy*dz)
+ s2d(3,2,3) = (slicez(i,j+1,k+1) - slicez(i,j-1,k+1)
+ $ - slicez(i,j+1,k-1) + slicez(i,j-1,k-1)) / (4.*dx*dz)
+ s2d(3,2,1) = s2d(3,1,2)
+ s2d(3,3,2) = s2d(3,2,3)
+ s2d(3,3,1) = s2d(3,1,3)
+
+ s2d(4,1,1) = (slicet(i+1,j,k) + slicet(i-1,j,k)
+ $ - 2.d0 * slicet(i,j,k)) / dx**2
+ s2d(4,2,2) = (slicet(i,j+1,k) + slicet(i,j-1,k)
+ $ - 2.d0 * slicet(i,j,k)) / dy**2
+ s2d(4,3,3) = (slicet(i,j,k+1) + slicet(i,j,k-1)
+ $ - 2.d0 * slicet(i,j,k)) / dz**2
+ s2d(4,1,2) = (slicet(i+1,j+1,k) - slicet(i-1,j+1,k)
+ $ - slicet(i+1,j-1,k) + slicet(i-1,j-1,k)) / (4.*dx*dy)
+ s2d(4,1,3) = (slicet(i+1,j,k+1) - slicet(i-1,j,k+1)
+ $ - slicet(i+1,j,k-1) + slicet(i-1,j,k-1)) / (4.*dy*dz)
+ s2d(4,2,3) = (slicet(i,j+1,k+1) - slicet(i,j-1,k+1)
+ $ - slicet(i,j+1,k-1) + slicet(i,j-1,k-1)) / (4.*dx*dz)
+ s2d(4,2,1) = s2d(4,1,2)
+ s2d(4,3,2) = s2d(4,2,3)
+ s2d(4,3,1) = s2d(4,1,3)
+
+
+C Calculate g_AB,C. Need to sum explicitly over C. Do this with
+C the editor.
+
+ call exactmetric(
+ $ slicex(i,j,k)+ex_eps, slicey(i,j,k), slicez(i,j,k),
+ $ slicet(i,j,k),
+ $ gd_p(4,4), gd_p(1,4), gd_p(2,4), gd_p(3,4),
+ $ gd_p(1,1), gd_p(2,2), gd_p(3,3),
+ $ gd_p(1,2), gd_p(2,3), gd_p(1,3),
+ $ gu(4,4), gu(1,4), gu(2,4), gu(3,4),
+ $ gu(1,1), gu(2,2), gu(3,3),
+ $ gu(1,2), gu(2,3), gu(1,3))
+ call exactmetric(
+ $ slicex(i,j,k)-ex_eps, slicey(i,j,k), slicez(i,j,k),
+ $ slicet(i,j,k),
+ $ gd_m(4,4), gd_m(1,4), gd_m(2,4), gd_m(3,4),
+ $ gd_m(1,1), gd_m(2,2), gd_m(3,3),
+ $ gd_m(1,2), gd_m(2,3), gd_m(1,3),
+ $ gu(4,4), gu(1,4), gu(2,4), gu(3,4),
+ $ gu(1,1), gu(2,2), gu(3,3),
+ $ gu(1,2), gu(2,3), gu(1,3))
+ do m=1,4
+ do n=m,4
+ gd1d(m,n,1) = (gd_p(m,n) - gd_m(m,n)) / (2.*ex_eps)
+ end do
+ end do
+
+ call exactmetric(
+ $ slicex(i,j,k), slicey(i,j,k)+ex_eps, slicez(i,j,k),
+ $ slicet(i,j,k),
+ $ gd_p(4,4), gd_p(1,4), gd_p(2,4), gd_p(3,4),
+ $ gd_p(1,1), gd_p(2,2), gd_p(3,3),
+ $ gd_p(1,2), gd_p(2,3), gd_p(1,3),
+ $ gu(4,4), gu(1,4), gu(2,4), gu(3,4),
+ $ gu(1,1), gu(2,2), gu(3,3),
+ $ gu(1,2), gu(2,3), gu(1,3))
+ call exactmetric(
+ $ slicex(i,j,k), slicey(i,j,k)-ex_eps, slicez(i,j,k),
+ $ slicet(i,j,k),
+ $ gd_m(4,4), gd_m(1,4), gd_m(2,4), gd_m(3,4),
+ $ gd_m(1,1), gd_m(2,2), gd_m(3,3),
+ $ gd_m(1,2), gd_m(2,3), gd_m(1,3),
+ $ gu(4,4), gu(1,4), gu(2,4), gu(3,4),
+ $ gu(1,1), gu(2,2), gu(3,3),
+ $ gu(1,2), gu(2,3), gu(1,3))
+ do m=1,4
+ do n=m,4
+ gd1d(m,n,2) = (gd_p(m,n) - gd_m(m,n)) / (2.*ex_eps)
+ end do
+ end do
+
+ call exactmetric(
+ $ slicex(i,j,k), slicey(i,j,k), slicez(i,j,k)+ex_eps,
+ $ slicet(i,j,k),
+ $ gd_p(4,4), gd_p(1,4), gd_p(2,4), gd_p(3,4),
+ $ gd_p(1,1), gd_p(2,2), gd_p(3,3),
+ $ gd_p(1,2), gd_p(2,3), gd_p(1,3),
+ $ gu(4,4), gu(1,4), gu(2,4), gu(3,4),
+ $ gu(1,1), gu(2,2), gu(3,3),
+ $ gu(1,2), gu(2,3), gu(1,3))
+ call exactmetric(
+ $ slicex(i,j,k), slicey(i,j,k), slicez(i,j,k)-ex_eps,
+ $ slicet(i,j,k),
+ $ gd_m(4,4), gd_m(1,4), gd_m(2,4), gd_m(3,4),
+ $ gd_m(1,1), gd_m(2,2), gd_m(3,3),
+ $ gd_m(1,2), gd_m(2,3), gd_m(1,3),
+ $ gu(4,4), gu(1,4), gu(2,4), gu(3,4),
+ $ gu(1,1), gu(2,2), gu(3,3),
+ $ gu(1,2), gu(2,3), gu(1,3))
+ do m=1,4
+ do n=m,4
+ gd1d(m,n,3) = (gd_p(m,n) - gd_m(m,n)) / (2.*ex_eps)
+ end do
+ end do
+
+ call exactmetric(
+ $ slicex(i,j,k), slicey(i,j,k), slicez(i,j,k),
+ $ slicet(i,j,k)+ex_eps,
+ $ gd_p(4,4), gd_p(1,4), gd_p(2,4), gd_p(3,4),
+ $ gd_p(1,1), gd_p(2,2), gd_p(3,3),
+ $ gd_p(1,2), gd_p(2,3), gd_p(1,3),
+ $ gu(4,4), gu(1,4), gu(2,4), gu(3,4),
+ $ gu(1,1), gu(2,2), gu(3,3),
+ $ gu(1,2), gu(2,3), gu(1,3))
+ call exactmetric(
+ $ slicex(i,j,k), slicey(i,j,k), slicez(i,j,k),
+ $ slicet(i,j,k)-ex_eps,
+ $ gd_m(4,4), gd_m(1,4), gd_m(2,4), gd_m(3,4),
+ $ gd_m(1,1), gd_m(2,2), gd_m(3,3),
+ $ gd_m(1,2), gd_m(2,3), gd_m(1,3),
+ $ gu(4,4), gu(1,4), gu(2,4), gu(3,4),
+ $ gu(1,1), gu(2,2), gu(3,3),
+ $ gu(1,2), gu(2,3), gu(1,3))
+ do m=1,4
+ do n=m,4
+ gd1d(m,n,4) = (gd_p(m,n) - gd_m(m,n)) / (2.*ex_eps)
+ end do
+ end do
+
+C Fill in remaining components of metric derivative.
+
+ do l=1,4
+ do m=1,4
+ do n=1,m-1
+ gd1d(m,n,l) = gd1d(n,m,l)
+ end do
+ end do
+ end do
+
+C Calculate K_ij.
+
+ h3 = 0.d0
+ do p=1,3
+ do q=p,3
+ do l=1,4
+ do m=1,4
+ h3(p,q) = h3(p,q)
+ $ + s2d(l,p,q) * nu(m) * gd(l,m)
+ do n=1,4
+ h3(p,q) = h3(p,q) + 0.5d0 * (
+ $ s1d(l,p) * s1d(n,q) * nu(m)
+ $ + s1d(n,p) * s1d(m,q) * nu(l)
+ $ - s1d(l,p) * s1d(m,q) * nu(n) )
+ $ * gd1d(l,m,n)
+ end do
+ end do
+ end do
+ end do
+ end do
+
+ kxx(i,j,k) = h3(1,1)
+ kxy(i,j,k) = h3(1,2)
+ kxz(i,j,k) = h3(1,3)
+ kyy(i,j,k) = h3(2,2)
+ kyz(i,j,k) = h3(2,3)
+ kzz(i,j,k) = h3(3,3)
+
+ end do
+ end do
+ end do
+
+C Synchronize and bound slicetmp2, which contains dx^A/dt.
+C This is really just for output, and will eventually be redundant.
+
+ call linextraponebound(CCTK_FARGUMENTS,slicetmp2x)
+ call synconefunc(slicetmp2x)
+ call linextraponebound(CCTK_FARGUMENTS,slicetmp2y)
+ call synconefunc(slicetmp2y)
+ call linextraponebound(CCTK_FARGUMENTS,slicetmp2z)
+ call synconefunc(slicetmp2z)
+ call linextraponebound(CCTK_FARGUMENTS,slicetmp2t)
+ call synconefunc(slicetmp2t)
+
+ kxx = - kxx
+ kxy = - kxy
+ kxz = - kxz
+ kyy = - kyy
+ kyz = - kyz
+ kzz = - kzz
+
+ return
+ end
+
+
diff --git a/src/slice_evolve.F b/src/slice_evolve.F
new file mode 100644
index 0000000..8a0f786
--- /dev/null
+++ b/src/slice_evolve.F
@@ -0,0 +1,132 @@
+C Evolve the slice in the exact spacetime.
+
+#include "cctk.h"
+#include "cctk_arguments.h"
+
+ subroutine slice_evolve(CCTK_FARGUMENTS)
+
+ implicit none
+
+ DECLARE_CCTK_FARGUMENTS
+
+ integer i,j,k,m,n
+ integer nx,ny,nz
+
+ CCTK_REAL s1d(4,3), nd(4), nu(4), norm, gd(4,4), gu(4,4)
+ CCTK_REAL dx,dy,dz,dt
+
+C Grid parameters.
+
+ nx = cctk_lsh(1)
+ ny = cctk_lsh(2)
+ nz = cctk_lsh(3)
+
+ dx = cctk_delta_space(1)
+ dy = cctk_delta_space(2)
+ dz = cctk_delta_space(3)
+
+ dt = cctk_delta_time
+
+C Lax, or forward in time, step.
+C dxA/dt has previously been stored in slicetmp2
+C by slice_data.
+
+ slicetmp1x = slicex + 0.5d0 * dt * slicetmp2x
+ slicetmp1y = slicey + 0.5d0 * dt * slicetmp2y
+ slicetmp1z = slicez + 0.5d0 * dt * slicetmp2z
+ slicetmp1t = slicet + 0.5d0 * dt * slicetmp2t
+
+C Synchronize and bound slice.
+
+ call linextraponebound(CCTK_FARGUMENTS,slicetmp1x)
+ call synconefunc(slicetmp1x)
+ call linextraponebound(CCTK_FARGUMENTS,slicetmp1y)
+ call synconefunc(slicetmp1y)
+ call linextraponebound(CCTK_FARGUMENTS,slicetmp1z)
+ call synconefunc(slicetmp1z)
+ call linextraponebound(CCTK_FARGUMENTS,slicetmp1t)
+ call synconefunc(slicetmp1t)
+
+C Prepare leapfrog step.
+C Sum over interior points on the slice, now at midpoint slicetmp1.
+
+ do k=2,nz-1
+ do j=2,ny-1
+ do i=2,nx-1
+
+C Calculate first derivatives of slice coordinates.
+
+ s1d(1,1) = 0.5d0*(slicetmp1x(i+1,j,k) - slicetmp1x(i-1,j,k))/dx
+ s1d(1,2) = 0.5d0*(slicetmp1x(i,j+1,k) - slicetmp1x(i,j-1,k))/dy
+ s1d(1,3) = 0.5d0*(slicetmp1x(i,j,k+1) - slicetmp1x(i,j,k-1))/dz
+
+ s1d(2,1) = 0.5d0*(slicetmp1y(i+1,j,k) - slicetmp1y(i-1,j,k))/dx
+ s1d(2,2) = 0.5d0*(slicetmp1y(i,j+1,k) - slicetmp1y(i,j-1,k))/dy
+ s1d(2,3) = 0.5d0*(slicetmp1y(i,j,k+1) - slicetmp1y(i,j,k-1))/dz
+
+ s1d(3,1) = 0.5d0*(slicetmp1z(i+1,j,k) - slicetmp1z(i-1,j,k))/dx
+ s1d(3,2) = 0.5d0*(slicetmp1z(i,j+1,k) - slicetmp1z(i,j-1,k))/dy
+ s1d(3,3) = 0.5d0*(slicetmp1z(i,j,k+1) - slicetmp1z(i,j,k-1))/dz
+
+ s1d(4,1) = 0.5d0*(slicetmp1t(i+1,j,k) - slicetmp1t(i-1,j,k))/dx
+ s1d(4,2) = 0.5d0*(slicetmp1t(i,j+1,k) - slicetmp1t(i,j-1,k))/dy
+ s1d(4,3) = 0.5d0*(slicetmp1t(i,j,k+1) - slicetmp1t(i,j,k-1))/dz
+
+C Now we need the exact solution metric in the preferred coordinates
+C x^A.
+ call exactmetric(
+ $ slicetmp1x(i,j,k), slicetmp1y(i,j,k), slicetmp1z(i,j,k),
+ $ slicetmp1t(i,j,k),
+ $ gd(4,4), gd(1,4), gd(2,4), gd(3,4),
+ $ gd(1,1), gd(2,2), gd(3,3),
+ $ gd(1,2), gd(2,3), gd(1,3),
+ $ gu(4,4), gu(1,4), gu(2,4), gu(3,4),
+ $ gu(1,1), gu(2,2), gu(3,3),
+ $ gu(1,2), gu(2,3), gu(1,3))
+
+C Calculate n^A and dx^A/dt
+#include "include/slice_normal.h"
+
+ end do
+ end do
+ end do
+
+C Synchronize and bound slicetmp2, which contains dx^A/dt.
+
+ call linextraponebound(CCTK_FARGUMENTS,slicetmp2x)
+ call synconefunc(slicetmp2x)
+ call linextraponebound(CCTK_FARGUMENTS,slicetmp2y)
+ call synconefunc(slicetmp2y)
+ call linextraponebound(CCTK_FARGUMENTS,slicetmp2z)
+ call synconefunc(slicetmp2z)
+ call linextraponebound(CCTK_FARGUMENTS,slicetmp2t)
+ call synconefunc(slicetmp2t)
+
+C Leapfrog step.
+
+ slicex = slicex + dt * slicetmp2x
+ slicey = slicey + dt * slicetmp2y
+ slicez = slicez + dt * slicetmp2z
+ slicet = slicet + dt * slicetmp2t
+
+C Synchronize and bound slice.
+
+ call linextraponebound(CCTK_FARGUMENTS,slicex)
+ call synconefunc(slicex)
+ call linextraponebound(CCTK_FARGUMENTS,slicey)
+ call synconefunc(slicey)
+ call linextraponebound(CCTK_FARGUMENTS,slicez)
+ call synconefunc(slicez)
+ call linextraponebound(CCTK_FARGUMENTS,slicet)
+ call synconefunc(slicet)
+
+C Extract Cauchy data at the new position, and store dxA/dt
+C for use in the next Lax step.
+
+ call slice_data(CCTK_FARGUMENTS)
+
+ return
+ end
+
+
+
diff --git a/src/slice_initialize.F b/src/slice_initialize.F
new file mode 100644
index 0000000..8871387
--- /dev/null
+++ b/src/slice_initialize.F
@@ -0,0 +1,41 @@
+
+#include "cctk.h"
+#include "cctk_arguments.h"
+#include "CactusEinstein/Einstein/src/Einstein.h"
+
+ subroutine slice_initialize(CCTK_FARGUMENTS)
+
+ implicit none
+
+ DECLARE_CCTK_FARGUMENTS
+
+ CCTK_REAL slice_gauss_ampl, slice_gauss_width
+
+C Initialize position of slice in exact solution spacetime.
+C For now something simple.
+
+ slicex = x
+ slicey = y
+ slicez = z
+ slicet = slice_gauss_ampl*exp(-(x**2 + y**2 + z**2)
+ $ /slice_gauss_width**2)
+
+C Calculate Cauchy data and dx^A/dt.
+
+ call slice_data(CCTK_FARGUMENTS)
+
+C Extrapolate g, K, etc. to the boundary, where slice_data cannot
+C calculate them, because it cannot take derivatives there. At all
+C other timesteps cactus will do this automatically.
+
+ call boundaries(CCTK_FARGUMENTS)
+
+C This wasted a day of work. PW found it...
+
+ conformal_state = NOCONFORMAL_METRIC
+ psi = 1.0D0
+
+ return
+ end
+
+
diff --git a/src/starschwarz.F b/src/starschwarz.F
new file mode 100644
index 0000000..fa47b2f
--- /dev/null
+++ b/src/starschwarz.F
@@ -0,0 +1,120 @@
+#include "cctk.h"
+#include "cctk_parameters.h"
+
+ subroutine starschwarz(
+ $ x, y, z, t,
+ $ gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx)
+
+c The metric given here corresponds to a constant
+c density star, also known as a `Schwarzschild' star.
+c It is obviously not a vacuum solution, so if someone
+c wants to evolve it, we will need to add here the
+c matter variables. For the moment, only the metric
+c is given.
+c
+c The metric is given as a conformally flat metric.
+c Turns out that in the original areal radius, the
+c metric variables have a kink at the surface of the
+c star, but they are smooth in the conformal form.
+c
+c Thanks to Philippos Papadopoulos for suggesting
+c the use of this metric.
+
+ implicit none
+
+ DECLARE_CCTK_PARAMETERS
+
+c Input.
+
+ CCTK_REAL x, y, z, t
+
+c Output.
+
+ CCTK_REAL gdtt, gdtx, gdty, gdtz,
+ $ gdxx, gdyy, gdzz, gdxy, gdyz, gdzx,
+ $ gutt, gutx, guty, gutz,
+ $ guxx, guyy, guzz, guxy, guyz, guzx
+
+c Internal.
+
+ logical firstcall
+
+ CCTK_REAL mass,radius
+ CCTK_REAL r,c,psi4
+ CCTK_REAL zero,one,two
+
+ data firstcall /.true./
+ save firstcall
+
+c Find {zero,one,two}.
+
+ zero = 0.0D0
+ one = 1.0D0
+ two = 2.0D0
+
+c Get parameters of the metric.
+
+ if (firstcall) then
+
+ mass = starschwarz_m
+ radius = starschwarz_r
+
+ firstcall = .false.
+
+ end if
+
+c Find r.
+
+ r = dsqrt(x**2 + y**2 + z**2)
+
+c Find conformal factor.
+
+ if (r.le.radius) then
+
+ c = mass/(two*radius)
+
+ psi4 = (one + c)**6/(one + c*(r/radius)**2)**2
+
+ else
+
+ c = mass/(two*r)
+
+ psi4 = (one + c)**4
+
+ end if
+
+c Find metric components.
+
+ gdtt = - psi4
+
+ gdtx = zero
+ gdty = zero
+ gdtz = zero
+
+ gdxx = psi4
+ gdyy = psi4
+ gdzz = psi4
+
+ gdxy = zero
+ gdyz = zero
+ gdzx = zero
+
+c Find inverse metric.
+
+ gutx = zero
+ guty = zero
+ gutz = zero
+
+ guxx = one/psi4
+ guyy = one/psi4
+ guzz = one/psi4
+
+ guxy = zero
+ guyz = zero
+ guzx = zero
+
+ return
+ end