aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--interface.ccl96
-rw-r--r--param.ccl90
-rw-r--r--schedule.ccl145
-rw-r--r--src/NoExcision_mod.F90266
-rw-r--r--src/cg.F90634
-rw-r--r--src/getlevelinfo.cc45
-rw-r--r--src/make.code.defn2
-rw-r--r--src/make.code.deps1
-rw-r--r--src/overwrite.F90206
-rw-r--r--src/overwriteBSSN.F90248
-rw-r--r--src/reduce.F9097
-rw-r--r--src/reduce.c34
-rw-r--r--src/smooth.F90150
13 files changed, 1926 insertions, 88 deletions
diff --git a/interface.ccl b/interface.ccl
index 0aa4916..968f4cf 100644
--- a/interface.ccl
+++ b/interface.ccl
@@ -3,4 +3,98 @@
IMPLEMENTS: NoExcision
-INHERITS: ADMBase StaticConformal grid
+INHERITS: ADMBase StaticConformal grid SphericalSurface Boundary
+
+USES INCLUDE: Boundary.h
+
+USES INCLUDE: carpet.hh
+
+CCTK_INT FUNCTION MoLQueryEvolvedRHS (CCTK_INT IN EvolvedIndex)
+USES FUNCTION MoLQueryEvolvedRHS
+
+CCTK_INT FUNCTION Boundary_SelectGroupForBC(CCTK_POINTER_TO_CONST IN GH, \
+ CCTK_INT IN faces, \
+ CCTK_INT IN boundary_width, \
+ CCTK_INT IN table_handle, \
+ CCTK_STRING IN var_name, \
+ CCTK_STRING IN bc_name)
+
+USES FUNCTION Boundary_SelectGroupForBC
+
+CCTK_INT smask type=GF timelevels=1 tags='tensortypealias="scalar" Prolongation="None"'
+{
+ nes_mask
+} "mask for smoothing"
+
+CCTK_REAL cg_res_metric type=GF timelevels=1 tags='tensortypealias="dd_sym" Prolongation="None"'
+{
+ resgxx, resgxy, resgxz, resgyy, resgyz, resgzz
+} "Conjugate Gradient residual for the metric"
+
+CCTK_REAL cg_res_curv type=GF timelevels=1 tags='tensortypealias="dd_sym" Prolongation="None"'
+{
+ reskxx, reskxy, reskxz, reskyy, reskyz, reskzz
+} "Conjugate Gradient residual for the extrinsic curvature"
+
+CCTK_REAL cg_res_shift type=GF timelevels=1 tags='tensortypealias="u" Prolongation="None"'
+{
+ resx, resy, resz
+} "Conjugate Gradient residual for the shift"
+
+CCTK_REAL cg_res_lapse type=GF timelevels=1 tags='tensortypealias="scalar" Prolongation="None"'
+{
+ res
+} "Conjugate Gradient residual for the lapse"
+
+
+CCTK_REAL cg_d_metric type=GF timelevels=1 tags='tensortypealias="dd_sym" Prolongation="None"'
+{
+ dgxx, dgxy, dgxz, dgyy, dgyz, dgzz
+} "Conjugate Gradient d for the metric"
+
+CCTK_REAL cg_d_curv type=GF timelevels=1 tags='tensortypealias="dd_sym" Prolongation="None"'
+{
+ dkxx, dkxy, dkxz, dkyy, dkyz, dkzz
+} "Conjugate Gradient d for the extrinsic curvature"
+
+CCTK_REAL cg_d_shift type=GF timelevels=1 tags='tensortypealias="u" Prolongation="None"'
+{
+ dx, dy, dz
+} "Conjugate Gradient d for the shift"
+
+CCTK_REAL cg_d_lapse type=GF timelevels=1 tags='tensortypealias="scalar" Prolongation="None"'
+{
+ d
+} "Conjugate Gradient d for the lapse"
+
+
+CCTK_REAL cg_q_metric type=GF timelevels=1 tags='tensortypealias="dd_sym" Prolongation="None"'
+{
+ qgxx, qgxy, qgxz, qgyy, qgyz, qgzz
+} "Conjugate Gradient q for the metric"
+
+CCTK_REAL cg_q_curv type=GF timelevels=1 tags='tensortypealias="dd_sym" Prolongation="None"'
+{
+ qkxx, qkxy, qkxz, qkyy, qkyz, qkzz
+} "Conjugate Gradient q for the extrinsic curvature"
+
+CCTK_REAL cg_q_shift type=GF timelevels=1 tags='tensortypealias="u" Prolongation="None"'
+{
+ qx, qy, qz
+} "Conjugate Gradient q for the shift"
+
+CCTK_REAL cg_q_lapse type=GF timelevels=1 tags='tensortypealias="scalar" Prolongation="None"'
+{
+ q
+} "Conjugate Gradient q for the lapse"
+
+
+CCTK_REAL cg_red_all type=GF timelevels=1 tags='tensortypealias="scalar" Prolongation="None"'
+{
+ redgxx, redgxy, redgxz, redgyy, redgyz, redgzz
+ redkxx, redkxy, redkxz, redkyy, redkyz, redkzz
+ red, redx, redy, redz
+} "Conjugate Gradient red for all variables"
+
+# Control variable for smoothing loop
+CCTK_INT loop_control TYPE=SCALAR
diff --git a/param.ccl b/param.ccl
index 1fe7342..6d93bd3 100644
--- a/param.ccl
+++ b/param.ccl
@@ -5,13 +5,18 @@ BOOLEAN verbose "Produce some screen output"
{
} "no"
+KEYWORD method "Method to use"
+{
+ "old" :: "Use old method"
+ "new" :: "Use new method"
+} "old"
+
+
INT num_regions "Number of no-excision regions"
{
0:10 :: ""
} 0
-
-
BOOLEAN overwrite_geometry[10] "Set the geometry to Minkowski"
{
} "yes"
@@ -40,27 +45,100 @@ BOOLEAN overwrite_shift[10] "Set the shift to zero"
-REAL centre_x[10] "X-coordinate of the centre of the region"
+REAL centre_x[10] "x-coordinate of the centre of the region"
{
(*:*) :: ""
} 0.0
-REAL centre_y[10] "Y-coordinate of the centre of the region"
+REAL centre_y[10] "y-coordinate of the centre of the region"
{
(*:*) :: ""
} 0.0
-REAL centre_z[10] "Z-coordinate of the centre of the region"
+REAL centre_z[10] "z-coordinate of the centre of the region"
{
(*:*) :: ""
} 0.0
+KEYWORD region_shape[10] "Shape of the region"
+{
+ "sphere" :: "use radius"
+ "ellipsoid" :: "use radius_x, radius_y, and radius_z"
+ "surface" :: "use a spherical surface shape"
+} "sphere"
+
REAL radius[10] "Radius of the region"
{
0.0:*) :: ""
} 1.0
-REAL smoothing_zone_width[10] "Width of smoothing zone inside the region"
+REAL radius_x[10] "x-radius of the region"
+{
+ 0.0:*) :: ""
+} 1.0
+
+REAL radius_y[10] "y-radius of the region"
{
0.0:*) :: ""
+} 1.0
+
+REAL radius_z[10] "z-radius of the region"
+{
+ 0.0:*) :: ""
+} 1.0
+
+INT surface_index[10] "Spherical surface index"
+{
+ 0:* :: "must be an index of a spherical surface"
+} 0
+
+
+
+BOOLEAN reduce_rhs[10] "Reduce RHS"
+{
+} "no"
+
+REAL reduction_factor[10] "Reduction factor for RHS (0=complete, 1=no reduction)"
+{
+ *:* :: ""
+} 0.0
+
+
+
+KEYWORD smoothing_function[10] "Smoothing function"
+{
+ "linear" :: "linear ramp"
+ "spline" :: "cubic spline ramp"
+ "cosine" :: "cosine ramp"
+} "linear"
+
+REAL smoothing_zone_width[10] "Relative width of smoothing zone inside the region"
+{
+ 0.0:1.0 :: ""
} 0.0
+
+INT smoothing_iterations "Smoothing iterations"
+{
+ 0:* :: ""
+} 10
+
+REAL smoothing_factor "Initial moothing factor"
+{
+ (0:2) :: ""
+} 1.2
+
+
+
+BOOLEAN smooth_regions "Smooth overwritten regions?"
+{
+} "no"
+
+INT smoothing_order "Order of the derivatives used for CG smoothing"
+{
+ 2:6:2 :: ""
+} 6
+
+REAL smoothing_eps "CG smoothing stop criteria"
+{
+ (0.0:* :: ""
+} 1e-6
diff --git a/schedule.ccl b/schedule.ccl
index ac7b7b1..54d402b 100644
--- a/schedule.ccl
+++ b/schedule.ccl
@@ -1,7 +1,150 @@
# Schedule definitions for thorn NoExcision
# $Header$
-SCHEDULE NoExcision_Overwrite AT initial AFTER (ADMBase_InitialData ADMBase_InitialGauge)
+SCHEDULE NoExcision_Overwrite IN ADMBase_PostInitial
{
LANG: Fortran
} "Overwrite regions with Minkowski"
+
+if (CCTK_Equals(method,"new")) {
+ schedule NoExcision_SetSym at CCTK_BASEGRID
+ {
+ LANG: Fortran
+ } "Register the symmetries for the conjugate gradient functions."
+}
+
+if (smooth_regions) {
+ if (CCTK_Equals(method,"old")) {
+ SCHEDULE NoExcision_Smooth IN ADMBase_PostInitial AFTER NoExcision_Overwrite
+ {
+ LANG: Fortran
+ } "Smooth regions"
+ } else {
+
+ SCHEDULE GROUP NoExcision_CGSmoothing IN ADMBase_PostInitial
+ {
+ STORAGE: cg_res_metric, cg_res_curv, cg_res_shift, cg_res_lapse
+ STORAGE: cg_d_metric, cg_d_curv, cg_d_shift, cg_d_lapse
+ STORAGE: cg_q_metric, cg_q_curv, cg_q_shift, cg_q_lapse
+ STORAGE: cg_red_all
+ STORAGE: smask
+ STORAGE: loop_control
+
+ } "Conjugate Gradient smoothing"
+
+ SCHEDULE NoExcision_CGInit_1 IN NoExcision_CGSmoothing
+ {
+ LANG: Fortran
+ } "Initialise the conjugate gradient method 1"
+
+ SCHEDULE NoExcision_CGApplySym AS NoExcision_CGApplySym_p1 IN NoExcision_CGSmoothing AFTER NoExcision_CGInit_1
+ {
+ LANG: Fortran
+ SYNC: cg_d_metric
+ SYNC: cg_d_curv
+ SYNC: cg_d_shift
+ SYNC: cg_d_lapse
+ SYNC: cg_res_metric
+ SYNC: cg_res_curv
+ SYNC: cg_res_shift
+ SYNC: cg_res_lapse
+ SYNC: cg_red_all
+ } "Select variables for boundary conditions 1"
+
+ SCHEDULE GROUP ApplyBCs AS NoExcision_CGApplyBCs_p1 IN NoExcision_CGSmoothing AFTER NoExcision_CGApplySym_p1
+ {
+ } "Apply boundary conditions (Symmetries) 1"
+
+ SCHEDULE NoExcision_CGInit_2 IN NoExcision_CGSmoothing AFTER NoExcision_CGApplySym_p1
+ {
+ LANG: Fortran
+ OPTIONS: level
+ } "Initialise the conjugate gradient method 2"
+
+ SCHEDULE GROUP NoExcision_Smoothing IN NoExcision_CGSmoothing AFTER NoExcision_CGInit_2 while NoExcision::loop_control
+ {
+ } "Smooth regions"
+
+ SCHEDULE NoExcision_CG_1 IN NoExcision_Smoothing
+ {
+ LANG: Fortran
+ } "Conjugate gradients step 1"
+
+ SCHEDULE NoExcision_CGApplySym AS NoExcision_CGApplySym_p2 IN NoExcision_Smoothing AFTER NoExcision_CG_1
+ {
+ LANG: Fortran
+ SYNC: cg_q_metric
+ SYNC: cg_q_curv
+ SYNC: cg_q_shift
+ SYNC: cg_q_lapse
+ SYNC: cg_red_all
+ } "Select variables for boundary conditions 2"
+
+ SCHEDULE GROUP ApplyBCs AS NoExcision_CGApplyBCs_p2 IN NoExcision_Smoothing AFTER NoExcision_CGApplySym_p2
+ {
+ } "Apply boundary conditions (Symmetries) 2"
+
+ SCHEDULE NoExcision_CG_2 IN NoExcision_Smoothing AFTER NoExcision_CG_1
+ {
+ LANG: Fortran
+ OPTIONS: level
+ } "Conjugate gradients step 2"
+
+ SCHEDULE NoExcision_CG_3 IN NoExcision_Smoothing
+ {
+ LANG: Fortran
+ } "Conjugate gradients step 3"
+
+ SCHEDULE NoExcision_CGApplySym AS NoExcision_CGApplySym_p3 IN NoExcision_Smoothing AFTER NoExcision_CG_3
+ {
+ LANG: Fortran
+ SYNC: cg_res_metric
+ SYNC: cg_res_curv
+ SYNC: cg_res_shift
+ SYNC: cg_res_lapse
+ SYNC: metric
+ SYNC: curv
+ SYNC: shift
+ SYNC: lapse
+ SYNC: cg_red_all
+ } "Select variables for boundary conditions 3"
+
+ SCHEDULE GROUP ApplyBCs AS NoExcision_CGApplyBCs_p3 IN NoExcision_Smoothing AFTER NoExcision_CGApplySym_p3
+ {
+ } "Apply boundary conditions (Symmetries) 3"
+
+ SCHEDULE NoExcision_CG_4 IN NoExcision_Smoothing AFTER NoExcision_CG_1
+ {
+ LANG: Fortran
+ OPTIONS: level
+ } "Conjugate gradients step 4"
+
+ SCHEDULE NoExcision_CG_5 IN NoExcision_Smoothing
+ {
+ LANG: Fortran
+ } "Conjugate gradients step 5"
+
+ SCHEDULE NoExcision_CGApplySym AS NoExcision_CGApplySym_p4 IN NoExcision_CGSmoothing AFTER NoExcision_CG_5
+ {
+ LANG: Fortran
+ SYNC: cg_d_metric
+ SYNC: cg_d_curv
+ SYNC: cg_d_shift
+ SYNC: cg_d_lapse
+ } "Select variables for boundary conditions 4"
+
+ SCHEDULE GROUP ApplyBCs AS NoExcision_CGApplyBCs_p4 IN NoExcision_CGSmoothing AFTER NoExcision_CGApplySym_p4
+ {
+ } "Apply boundary conditions (Symmetries) 4"
+ }
+}
+
+#SCHEDULE NoExcision_OverwriteBSSN AT poststep
+#{
+# LANG: Fortran
+#} "Overwrite regions with Minkowski"
+
+SCHEDULE NoExcision_Reduce IN MoL_PostRHS
+{
+ LANG: C
+} "Reduce RHS"
diff --git a/src/NoExcision_mod.F90 b/src/NoExcision_mod.F90
new file mode 100644
index 0000000..646d335
--- /dev/null
+++ b/src/NoExcision_mod.F90
@@ -0,0 +1,266 @@
+! $Header$
+
+#include "cctk.h"
+
+module NoExcision_mod
+
+ implicit none
+
+ CCTK_REAL, parameter :: zero = 0.0
+ integer, parameter :: wp = kind(zero)
+ CCTK_REAL, parameter :: one = 1.0_wp
+ CCTK_REAL, parameter :: two = 2.0_wp
+ CCTK_INT :: infnorm_handle, sum_handle
+ CCTK_INT :: sym_selector
+ CCTK_INT :: loop_counter
+ CCTK_REAL, dimension(16) :: infnormresid
+ CCTK_REAL, dimension(16) :: delta_new, delta_old, alpha, beta, absres
+ character(len=18), dimension(16) :: red_names = (/ 'NoExcision::redgxx', &
+ 'NoExcision::redgxy', &
+ 'NoExcision::redgxz', &
+ 'NoExcision::redgyy', &
+ 'NoExcision::redgyz', &
+ 'NoExcision::redgzz', &
+ 'NoExcision::redkxx', &
+ 'NoExcision::redkxy', &
+ 'NoExcision::redkxz', &
+ 'NoExcision::redkyy', &
+ 'NoExcision::redkyz', &
+ 'NoExcision::redkzz', &
+ 'NoExcision::red', &
+ 'NoExcision::redx', &
+ 'NoExcision::redy', &
+ 'NoExcision::redz' /)
+ character(len=5), dimension(16) :: var_names = (/ ' gxx', ' gxy', &
+ ' gxz', ' gyy', &
+ ' gyz', ' gzz', &
+ ' kxx', ' kxy', &
+ ' kxz', ' kyy', &
+ ' kyz', ' kzz', &
+ ' alp', 'betax', &
+ 'betay', 'betaz' /)
+ integer :: nx, ny, nz
+ integer :: ii
+ logical, dimension(16) :: cont = (/ (.true., ii=1, 16) /)
+
+ contains
+
+ ! This is the basic residual calculation routine...
+
+ subroutine residual (val, mask, res, si, order )
+ CCTK_REAL, dimension(:,:,:), intent(in) :: val
+ CCTK_INT, dimension(:,:,:), intent(in) :: mask
+ CCTK_REAL, dimension(:,:,:), intent(out) :: res
+ CCTK_REAL, intent(in) :: si
+ CCTK_INT, intent(in) :: order
+ CCTK_REAL, parameter :: six = 6.0_wp
+ CCTK_REAL, parameter :: sixth = 1.0_wp / six
+ CCTK_REAL, parameter :: four = 4.0_wp
+ CCTK_REAL, parameter :: eighteen = 18.0_wp
+ CCTK_REAL, parameter :: eighteenth = 1.0_wp / eighteen
+ CCTK_REAL, parameter :: fifteen = 15.0_wp
+ CCTK_REAL, parameter :: sixty = 60.0_wp
+ CCTK_REAL, parameter :: sixtieth = 1.0_wp / sixty
+ integer :: i, j, k
+
+ select case (order)
+ case (2)
+
+ do k = 2, nz-1
+ do j = 2, ny-1
+ do i = 2, nx-1
+
+ if (mask(i,j,k) > 0) then
+
+ res(i,j,k) = val(i+1,j,k) + val(i-1,j,k) + val(i,j+1,k) + &
+ val(i,j-1,k) + val(i,j,k+1) + val(i,j,k-1) - &
+ six * val(i,j,k)
+ res(i,j,k) = sign(one,si) * res(i,j,k)
+
+ end if
+
+ end do
+ end do
+ end do
+
+ case (4)
+
+ do k = 3, nz-2
+ do j = 3, ny-2
+ do i = 3, nx-2
+
+ if (mask(i,j,k) > 0) then
+
+ res(i,j,k) = - ( val(i+2,j,k) + val(i-2,j,k) + &
+ val(i,j+2,k) + val(i,j-2,k) + &
+ val(i,j,k+2) + val(i,j,k-2) ) + &
+ four * ( val(i+1,j,k) + val(i-1,j,k) + &
+ val(i,j+1,k) + val(i,j-1,k) + &
+ val(i,j,k+1) + val(i,j,k-1) ) - &
+ eighteen * val(i,j,k)
+ res(i,j,k) = sign(one,si) * res(i,j,k)
+
+ end if
+
+ end do
+ end do
+ end do
+
+ case (6)
+
+ do k = 4, nz-3
+ do j = 4, ny-3
+ do i = 4, nx-3
+
+ if (mask(i,j,k) > 0) then
+
+ res(i,j,k) = ( val(i+3,j,k) + val(i-3,j,k) + &
+ val(i,j+3,k) + val(i,j-3,k) + &
+ val(i,j,k+3) + val(i,j,k-3) ) - &
+ six * ( val(i+2,j,k) + val(i-2,j,k) + &
+ val(i,j+2,k) + val(i,j-2,k) + &
+ val(i,j,k+2) + val(i,j,k-2) ) + &
+ fifteen * ( val(i+1,j,k) + val(i-1,j,k) + &
+ val(i,j+1,k) + val(i,j-1,k) + &
+ val(i,j,k+1) + val(i,j,k-1) ) - &
+ sixty * val(i,j,k)
+ res(i,j,k) = sign(one,si) * res(i,j,k)
+
+ end if
+
+ end do
+ end do
+ end do
+
+ case default
+
+ call CCTK_WARN ( 0, 'Internal error: Order out of range' )
+
+ end select
+
+ end subroutine residual
+
+
+ ! This is the routine calculating residuals for all variables, that
+ ! have not yet converged.
+
+ subroutine residual_all ( v1, v2, v3, v4, v5, v6, v7, v8, &
+ v9, v10, v11, v12, v13, v14, v15, v16, &
+ r1, r2, r3, r4, r5, r6, r7, r8, &
+ r9, r10, r11, r12, r13, r14, r15, r16, &
+ mask, si, order )
+
+ CCTK_REAL, dimension(:,:,:), intent(in) :: v1, v2, v3, v4, v5, v6, &
+ v7, v8, v9, v10, v11, v12, &
+ v13, v14, v15, v16
+ CCTK_REAL, dimension(:,:,:), intent(out) :: r1, r2, r3, r4, r5, r6, &
+ r7, r8, r9, r10, r11, r12, &
+ r13, r14, r15, r16
+ CCTK_INT, dimension(:,:,:), intent(in) :: mask
+ CCTK_REAL, intent(in) :: si
+ CCTK_INT, intent(in) :: order
+
+ if ( cont(1) ) call residual ( v1, mask, r1, si, order )
+ if ( cont(2) ) call residual ( v2, mask, r2, si, order )
+ if ( cont(3) ) call residual ( v3, mask, r3, si, order )
+ if ( cont(4) ) call residual ( v4, mask, r4, si, order )
+ if ( cont(5) ) call residual ( v5, mask, r5, si, order )
+ if ( cont(6) ) call residual ( v6, mask, r6, si, order )
+ if ( cont(7) ) call residual ( v7, mask, r7, si, order )
+ if ( cont(8) ) call residual ( v8, mask, r8, si, order )
+ if ( cont(9) ) call residual ( v9, mask, r9, si, order )
+ if ( cont(10) ) call residual ( v10, mask, r10, si, order )
+ if ( cont(11) ) call residual ( v11, mask, r11, si, order )
+ if ( cont(12) ) call residual ( v12, mask, r12, si, order )
+ if ( cont(13) ) call residual ( v13, mask, r13, si, order )
+ if ( cont(14) ) call residual ( v14, mask, r14, si, order )
+ if ( cont(15) ) call residual ( v15, mask, r15, si, order )
+ if ( cont(16) ) call residual ( v16, mask, r16, si, order )
+
+ end subroutine residual_all
+
+
+ ! This routine multiplies two variables. Only does it according
+ ! to the mask and only for variables that have not converged yet.
+
+ subroutine multiply ( u1, u2, u3, u4, u5, u6, u7, u8, &
+ u9, u10, u11, u12, u13, u14, u15, u16, &
+ v1, v2, v3, v4, v5, v6, v7, v8, &
+ v9, v10, v11, v12, v13, v14, v15, v16, &
+ r1, r2, r3, r4, r5, r6, r7, r8, &
+ r9, r10, r11, r12, r13, r14, r15, r16, &
+ mask )
+
+ CCTK_REAL, dimension(:,:,:), intent(in) :: u1, u2, u3, u4, u5, u6, &
+ u7, u8, u9, u10, u11, u12, &
+ u13, u14, u15, u16
+ CCTK_REAL, dimension(:,:,:), intent(in) :: v1, v2, v3, v4, v5, v6, &
+ v7, v8, v9, v10, v11, v12, &
+ v13, v14, v15, v16
+ CCTK_REAL, dimension(:,:,:), intent(out) :: r1, r2, r3, r4, r5, r6, &
+ r7, r8, r9, r10, r11, r12, &
+ r13, r14, r15, r16
+ CCTK_INT, dimension(:,:,:), intent(in) :: mask
+
+ if ( cont(1) ) where ( mask > 0 ) r1 = u1*v1
+ if ( cont(2) ) where ( mask > 0 ) r2 = u2*v2
+ if ( cont(3) ) where ( mask > 0 ) r3 = u3*v3
+ if ( cont(4) ) where ( mask > 0 ) r4 = u4*v4
+ if ( cont(5) ) where ( mask > 0 ) r5 = u5*v5
+ if ( cont(6) ) where ( mask > 0 ) r6 = u6*v6
+ if ( cont(7) ) where ( mask > 0 ) r7 = u7*v7
+ if ( cont(8) ) where ( mask > 0 ) r8 = u8*v8
+ if ( cont(9) ) where ( mask > 0 ) r9 = u9*v9
+ if ( cont(10) ) where ( mask > 0 ) r10 = u10*v10
+ if ( cont(11) ) where ( mask > 0 ) r11 = u11*v11
+ if ( cont(12) ) where ( mask > 0 ) r12 = u12*v12
+ if ( cont(13) ) where ( mask > 0 ) r13 = u13*v13
+ if ( cont(14) ) where ( mask > 0 ) r14 = u14*v14
+ if ( cont(15) ) where ( mask > 0 ) r15 = u15*v15
+ if ( cont(16) ) where ( mask > 0 ) r16 = u16*v16
+
+ end subroutine multiply
+
+
+ ! This routine takes the product of a scalar and a variable and
+ ! adds it to the product of another scalar and variable. Does it
+ ! according to the mask and only for variables that have not yet
+ ! converged.
+
+ subroutine multiply_sum ( u1, u2, u3, u4, u5, u6, u7, u8, &
+ u9, u10, u11, u12, u13, u14, u15, u16, &
+ v1, v2, v3, v4, v5, v6, v7, v8, &
+ v9, v10, v11, v12, v13, v14, v15, v16, &
+ c1, c2, mask )
+
+ CCTK_REAL, dimension(:,:,:), intent(inout) :: u1, u2, u3, u4, u5, u6, &
+ u7, u8, u9, u10, u11, u12, &
+ u13, u14, u15, u16
+ CCTK_REAL, dimension(:,:,:), intent(in) :: v1, v2, v3, v4, v5, v6, &
+ v7, v8, v9, v10, v11, v12, &
+ v13, v14, v15, v16
+ CCTK_REAL, dimension(16), intent(in) :: c1, c2
+ CCTK_INT, dimension(:,:,:), intent(in) :: mask
+
+
+ if ( cont(1) ) where ( mask > 0 ) u1 = c1(1)*u1 + c2(1)*v1
+ if ( cont(2) ) where ( mask > 0 ) u2 = c1(2)*u2 + c2(2)*v2
+ if ( cont(3) ) where ( mask > 0 ) u3 = c1(3)*u3 + c2(3)*v3
+ if ( cont(4) ) where ( mask > 0 ) u4 = c1(4)*u4 + c2(4)*v4
+ if ( cont(5) ) where ( mask > 0 ) u5 = c1(5)*u5 + c2(5)*v5
+ if ( cont(6) ) where ( mask > 0 ) u6 = c1(6)*u6 + c2(6)*v6
+ if ( cont(7) ) where ( mask > 0 ) u7 = c1(7)*u7 + c2(7)*v7
+ if ( cont(8) ) where ( mask > 0 ) u8 = c1(8)*u8 + c2(8)*v8
+ if ( cont(9) ) where ( mask > 0 ) u9 = c1(9)*u9 + c2(9)*v9
+ if ( cont(10) ) where ( mask > 0 ) u10 = c1(10)*u10 + c2(10)*v10
+ if ( cont(11) ) where ( mask > 0 ) u11 = c1(11)*u11 + c2(11)*v11
+ if ( cont(12) ) where ( mask > 0 ) u12 = c1(12)*u12 + c2(12)*v12
+ if ( cont(13) ) where ( mask > 0 ) u13 = c1(13)*u13 + c2(13)*v13
+ if ( cont(14) ) where ( mask > 0 ) u14 = c1(14)*u14 + c2(14)*v14
+ if ( cont(15) ) where ( mask > 0 ) u15 = c1(15)*u15 + c2(15)*v15
+ if ( cont(16) ) where ( mask > 0 ) u16 = c1(16)*u16 + c2(16)*v16
+
+ end subroutine multiply_sum
+
+
+end module NoExcision_mod
diff --git a/src/cg.F90 b/src/cg.F90
new file mode 100644
index 0000000..71f56c0
--- /dev/null
+++ b/src/cg.F90
@@ -0,0 +1,634 @@
+! $Header$
+
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Functions.h"
+#include "cctk_Parameters.h"
+
+subroutine NoExcision_CGInit_1 (CCTK_ARGUMENTS)
+
+ use NoExcision_mod
+
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_FUNCTIONS
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_INT :: my_level, n_levels
+ CCTK_INT :: ierr
+ CCTK_INT, dimension(3) :: sym
+
+ nx = cctk_lsh(1); ny = cctk_lsh(2); nz = cctk_lsh(3)
+
+ loop_control = 0
+
+ call NoExcision_levelinfo ( cctkGH, my_level, n_levels )
+
+ if ( my_level == n_levels-1 ) then
+
+ where (abs(gxx) < 1d-8 .and. abs(alp) < 1d-8)
+ nes_mask = 1
+ elsewhere
+ nes_mask = 0
+ end where
+
+ call CCTK_INFO ( 'Starting smoothing procedure' )
+
+ resgxx = zero; resgxy = zero; resgxz = zero
+ resgyy = zero; resgyz = zero; resgzz = zero
+ reskxx = zero; reskxy = zero; reskxz = zero
+ reskyy = zero; reskyz = zero; reskzz = zero
+ res = zero; resx = zero; resy = zero; resz = zero
+
+ dgxx = zero; dgxy = zero; dgxz = zero
+ dgyy = zero; dgyz = zero; dgzz = zero
+ dkxx = zero; dkxy = zero; dkxz = zero
+ dkyy = zero; dkyz = zero; dkzz = zero
+ d = zero; dx = zero; dy = zero; dz = zero
+
+ qgxx = zero; qgxy = zero; qgxz = zero
+ qgyy = zero; qgyz = zero; qgzz = zero
+ qkxx = zero; qkxy = zero; qkxz = zero
+ qkyy = zero; qkyz = zero; qkzz = zero
+ q = zero; qx = zero; qy = zero; qz = zero
+
+ redgxx = zero; redgxy = zero; redgxz = zero
+ redgyy = zero; redgyz = zero; redgzz = zero
+ redkxx = zero; redkxy = zero; redkxz = zero
+ redkyy = zero; redkyz = zero; redkzz = zero
+ red = zero; redx = zero; redy = zero; redz = zero
+
+ ! r = b - A x.
+ ! Since x=0 and we actually use A': b = -A' 0 and r = b = -A' 0.
+
+ call residual_all ( gxx, gxy, gxz, gyy, gyz, gzz, &
+ kxx, kxy, kxz, kyy, kyz, kzz, &
+ alp, betax, betay, betaz, &
+ resgxx, resgxy, resgxz, resgyy, resgyz, resgzz, &
+ reskxx, reskxy, reskxz, reskyy, reskyz, reskzz, &
+ res, resx, resy, resz, &
+ nes_mask, -one, smoothing_order )
+
+ ! d = r = b.
+
+ call residual_all ( gxx, gxy, gxz, gyy, gyz, gzz, &
+ kxx, kxy, kxz, kyy, kyz, kzz, &
+ alp, betax, betay, betaz, &
+ dgxx, dgxy, dgxz, dgyy, dgyz, dgzz, &
+ dkxx, dkxy, dkxz, dkyy, dkyz, dkzz, &
+ d, dx, dy, dz, &
+ nes_mask, -one, smoothing_order )
+
+ ! red = r*r.
+
+ call multiply ( resgxx, resgxy, resgxz, resgyy, resgyz, resgzz, &
+ reskxx, reskxy, reskxz, reskyy, reskyz, reskzz, &
+ res, resx, resy, resz, &
+ resgxx, resgxy, resgxz, resgyy, resgyz, resgzz, &
+ reskxx, reskxy, reskxz, reskyy, reskyz, reskzz, &
+ res, resx, resy, resz, &
+ redgxx, redgxy, redgxz, redgyy, redgyz, redgzz, &
+ redkxx, redkxy, redkxz, redkyy, redkyz, redkzz, &
+ red, redx, redy, redz, nes_mask )
+
+ call CCTK_ReductionArrayHandle ( sum_handle, 'sum' )
+ if ( sum_handle .lt. 0 ) then
+ call CCTK_WARN(0,'Could not obtain a handle for sum reduction')
+ end if
+
+ call CCTK_ReductionArrayHandle ( infnorm_handle, 'norm_inf' )
+ if ( infnorm_handle .lt. 0 ) then
+ call CCTK_WARN(0,'Could not obtain a handle for norm_inf reduction')
+ end if
+
+ loop_counter = 0
+ loop_control = 1
+
+ sym_selector = 1
+
+ end if
+
+end subroutine NoExcision_CGInit_1
+
+
+subroutine NoExcision_CGInit_2 (CCTK_ARGUMENTS)
+
+ use NoExcision_mod
+
+
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_FUNCTIONS
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_INT :: res_var, ierr
+ integer :: i
+ character(len=56) :: conv_message
+
+ if ( loop_control == 1 ) then
+ do i = 1, 16
+ if ( cont(i) ) then
+ call CCTK_VarIndex ( res_var, red_names(i) )
+ if ( res_var < 0 ) then
+ call CCTK_WARN ( 0, 'Could not get index to grid function red' )
+ end if
+
+ ! delta_new = r^T r.
+
+ call CCTK_Reduce ( ierr, cctkGH, -1, sum_handle, 1, &
+ CCTK_VARIABLE_REAL, delta_new(i), 1, res_var )
+
+ call CCTK_Reduce ( ierr, cctkGH, -1, infnorm_handle, 1, &
+ CCTK_VARIABLE_REAL, infnormresid(i), 1, res_var )
+
+ ! Since we are reducing r*r, we have to take the square root.
+
+ infnormresid(i) = sqrt(infnormresid(i))
+
+ end if
+ end do
+
+ ! Check if some variables has already converged. This happens when the
+ ! variable is identically zero.
+
+ do i = 1, 16
+ if ( cont(i) ) then
+ if ( infnormresid(i) < smoothing_eps ) then
+ write ( conv_message, '(a23,i8,a20,a5)' ) 'CG method converged in ', &
+ loop_counter, ' steps for variable ', var_names(i)
+ call CCTK_INFO ( conv_message )
+ cont(i) = .false.
+ end if
+ end if
+ end do
+
+ if ( .not. any ( cont ) ) then
+ loop_control = 0
+ end if
+
+ end if
+
+end subroutine NoExcision_CGInit_2
+
+
+subroutine NoExcision_CG_1 (CCTK_ARGUMENTS)
+
+ use NoExcision_mod
+
+ implicit none
+
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_FUNCTIONS
+ DECLARE_CCTK_PARAMETERS
+
+ nx = cctk_lsh(1); ny=cctk_lsh(2); nz = cctk_lsh(3)
+
+ loop_counter = loop_counter + 1
+
+ ! Since d is zero outside of the active region we have:
+ ! q = A d = A' d.
+
+ call residual_all ( dgxx, dgxy, dgxz, dgyy, dgyz, dgzz, &
+ dkxx, dkxy, dkxz, dkyy, dkyz, dkzz, &
+ d, dx, dy, dz, &
+ qgxx, qgxy, qgxz, qgyy, qgyz, qgzz, &
+ qkxx, qkxy, qkxz, qkyy, qkyz, qkzz, &
+ q, qx, qy, qz, &
+ nes_mask, one, smoothing_order )
+
+ ! red = d*q = d*(A d)
+
+ call multiply ( dgxx, dgxy, dgxz, dgyy, dgyz, dgzz, &
+ dkxx, dkxy, dkxz, dkyy, dkyz, dkzz, &
+ d, dx, dy, dz, &
+ qgxx, qgxy, qgxz, qgyy, qgyz, qgzz, &
+ qkxx, qkxy, qkxz, qkyy, qkyz, qkzz, &
+ q, qx, qy, qz, &
+ redgxx, redgxy, redgxz, redgyy, redgyz, redgzz, &
+ redkxx, redkxy, redkxz, redkyy, redkyz, redkzz, &
+ red, redx, redy, redz, nes_mask )
+
+ sym_selector = 2
+
+end subroutine NoExcision_CG_1
+
+
+subroutine NoExcision_CG_2 (CCTK_ARGUMENTS)
+
+ use NoExcision_mod
+
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_FUNCTIONS
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_INT res_var, ierr
+
+ integer :: i
+
+ if ( loop_control == 1 ) then
+ do i = 1, 16
+ if ( cont(i) ) then
+ call CCTK_VarIndex ( res_var, red_names(i) )
+ if ( res_var < 0 ) then
+ call CCTK_WARN ( 0, 'Could not get index to grid function red' )
+ end if
+
+ ! alpha = delta_new / ( d^T A d ).
+ call CCTK_Reduce ( ierr, cctkGH, -1, sum_handle, 1, &
+ CCTK_VARIABLE_REAL, alpha(i), 1, res_var )
+
+ alpha(i) = delta_new(i) / alpha(i)
+
+ end if
+ end do
+
+ end if
+
+end subroutine NoExcision_CG_2
+
+
+subroutine NoExcision_CG_3 (CCTK_ARGUMENTS)
+
+ use NoExcision_mod
+
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_FUNCTIONS
+ DECLARE_CCTK_PARAMETERS
+
+ nx = cctk_lsh(1); ny=cctk_lsh(2); nz = cctk_lsh(3)
+
+ ! x = x + alpha * d.
+
+ call multiply_sum ( gxx, gxy, gxz, gyy, gyz, gzz, &
+ kxx, kxy, kxz, kyy, kyz, kzz, &
+ alp, betax, betay, betaz, &
+ dgxx, dgxy, dgxz, dgyy, dgyz, dgzz, &
+ dkxx, dkxy, dkxz, dkyy, dkyz, dkzz, &
+ d, dx, dy, dz, &
+ (/ (one, i=1, 16) /), alpha, nes_mask )
+
+ if ( mod ( loop_counter, 50 ) == 0 ) then
+
+ ! Restart:
+ ! r = b - A x = - A' x
+
+ call residual_all ( gxx, gxy, gxz, gyy, gyz, gzz, &
+ kxx, kxy, kxz, kyy, kyz, kzz, &
+ alp, betax, betay, betaz, &
+ resgxx, resgxy, resgxz, resgyy, resgyz, resgzz, &
+ reskxx, reskxy, reskxz, reskyy, reskyz, reskzz, &
+ res, resx, resy, resz, &
+ nes_mask, -one, smoothing_order )
+ else
+
+ ! r = r - alpha q.
+
+ call multiply_sum ( resgxx, resgxy, resgxz, resgyy, resgyz, resgzz, &
+ reskxx, reskxy, reskxz, reskyy, reskyz, reskzz, &
+ res, resx, resy, resz, &
+ qgxx, qgxy, qgxz, qgyy, qgyz, qgzz, &
+ qkxx, qkxy, qkxz, qkyy, qkyz, qkzz, &
+ q, qx, qy, qz, &
+ (/ (one, i=1, 16) /), -alpha, nes_mask )
+
+ end if
+
+ ! delta_old = delta_new.
+
+ where ( cont ) delta_old = delta_new
+
+ ! red = r*r.
+ call multiply ( resgxx, resgxy, resgxz, resgyy, resgyz, resgzz, &
+ reskxx, reskxy, reskxz, reskyy, reskyz, reskzz, &
+ res, resx, resy, resz, &
+ resgxx, resgxy, resgxz, resgyy, resgyz, resgzz, &
+ reskxx, reskxy, reskxz, reskyy, reskyz, reskzz, &
+ res, resx, resy, resz, &
+ redgxx, redgxy, redgxz, redgyy, redgyz, redgzz, &
+ redkxx, redkxy, redkxz, redkyy, redkyz, redkzz, &
+ red, redx, redy, redz, nes_mask )
+
+ sym_selector = 3
+
+end subroutine NoExcision_CG_3
+
+
+subroutine NoExcision_CG_4 (CCTK_ARGUMENTS)
+
+ use NoExcision_mod
+
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_FUNCTIONS
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_INT res_var, ierr
+
+ integer :: i
+
+ if ( loop_control == 1 ) then
+ do i = 1, 16
+ if ( cont(i) ) then
+ call CCTK_VarIndex ( res_var, red_names(i) )
+ if ( res_var < 0 ) then
+ call CCTK_WARN ( 0, 'Could not get index to grid function red' )
+ end if
+
+ ! delta_new = r^T r.
+ call CCTK_Reduce ( ierr, cctkGH, -1, sum_handle, 1, &
+ CCTK_VARIABLE_REAL, delta_new(i), 1, res_var )
+
+ call CCTK_Reduce ( ierr, cctkGH, -1, infnorm_handle, 1, &
+ CCTK_VARIABLE_REAL, infnormresid(i), 1, res_var )
+ infnormresid(i) = sqrt(infnormresid(i))
+ end if
+ end do
+
+ end if
+
+end subroutine NoExcision_CG_4
+
+
+subroutine NoExcision_CG_5 (CCTK_ARGUMENTS)
+
+ use NoExcision_mod
+
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_FUNCTIONS
+ DECLARE_CCTK_PARAMETERS
+
+ integer :: i
+ character(len=192) :: res_message, var_message
+ character(len=56) :: conv_message
+ character(len=18) :: iter_message
+
+ nx = cctk_lsh(1); ny=cctk_lsh(2); nz = cctk_lsh(3)
+
+ ! beta = delta_new / delta_old
+
+ where ( cont ) beta = delta_new / delta_old
+
+ ! d = r + beta d
+
+ call multiply_sum ( dgxx, dgxy, dgxz, dgyy, dgyz, dgzz, &
+ dkxx, dkxy, dkxz, dkyy, dkyz, dkzz, &
+ d, dx, dy, dz, &
+ resgxx, resgxy, resgxz, resgyy, resgyz, resgzz, &
+ reskxx, reskxy, reskxz, reskyy, reskyz, reskzz, &
+ res, resx, resy, resz, &
+ beta, (/ (one, i=1, 16) /), nes_mask )
+
+ if ( verbose > 0 .and. mod(loop_counter,100) == 0 ) then
+ write (var_message, '(16(a3,a9))' ) (' | ', var_names(i), i=1, 16)
+ call CCTK_INFO ( var_message )
+ end if
+ if ( verbose > 0 .and. mod(loop_counter,10) == 0 ) then
+ write (iter_message, '(a10,i8)' ), 'Iteration ', loop_counter
+ write (res_message, '(16(a3,es9.3))' ) (' | ', infnormresid(i), i=1, 16 )
+ call CCTK_INFO ( iter_message )
+ call CCTK_INFO ( res_message )
+ end if
+
+ ! Check if any variables have converged during this iteration.
+
+ do i = 1, 16
+ if ( cont(i) ) then
+ if ( infnormresid(i) < smoothing_eps ) then
+ write ( conv_message, '(a23,i8,a20,a5)' ) 'CG method converged in ', &
+ loop_counter, ' steps for variable ', var_names(i)
+ call CCTK_INFO ( conv_message )
+ cont(i) = .false.
+ end if
+ end if
+ end do
+
+ ! If all variables have converged we exit.
+
+ if ( .not. any ( cont ) ) then
+ loop_control = 0
+ end if
+
+ sym_selector = 4
+
+end subroutine NoExcision_CG_5
+
+
+! I leave this in here in case somebody uses CartGrid3D symmetries...
+! Not tested, though...
+
+subroutine NoExcision_SetSym(CCTK_ARGUMENTS)
+
+ implicit none
+
+ DECLARE_CCTK_ARGUMENTS
+
+ CCTK_INT :: ierr
+ CCTK_INT, dimension(3) :: sym
+
+ sym = 1
+
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::resgxx' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::resgyy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::resgzz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::reskxx' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::reskyy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::reskzz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dgxx' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dgyy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dgzz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dkxx' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dkyy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dkzz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qgxx' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qgyy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qgzz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qkxx' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qkyy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qkzz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::res' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::d' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::q' )
+
+ call SetCartSymGN ( ierr, cctkGH, sym, 'noexcision::cg_red_all' )
+
+ sym(1) = -1; sym(2) = -1; sym(3) = 1
+
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::resgxy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::reskxy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dgxy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dkxy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qgxy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qkxy' )
+
+ sym(1) = -1; sym(2) = 1; sym(3) = -1
+
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::resgxz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::reskxz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dgxz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dkxz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qgxz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qkxz' )
+
+ sym(1) = 1; sym(2) = -1; sym(3) = -1
+
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::resgyz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::reskyz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dgyz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dkyz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qgyz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qkyz' )
+
+ sym(1) = -1; sym(2) = 1; sym(3) = 1
+
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::resx' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dx' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qx' )
+
+ sym(1) = 1; sym(2) = -1; sym(3) = 1
+
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::resy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dy' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qy' )
+
+ sym(1) = 1; sym(2) = 1; sym(3) = -1
+
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::resz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::dz' )
+ call SetCartSymVN ( ierr, cctkGH, sym, 'noexcision::qz' )
+
+end subroutine NoExcision_SetSym
+
+
+subroutine NoExcision_CGApplySym(CCTK_ARGUMENTS)
+
+ use NoExcision_mod
+
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_PARAMETERS
+ DECLARE_CCTK_FUNCTIONS
+
+ CCTK_INT :: ierr
+
+ if ( loop_control > 0 ) then
+
+ if ( sym_selector <1 .or. sym_selector > 4 ) then
+ call CCTK_WARN ( 0, 'Internal error. Inconsistent symmetry selector' )
+ end if
+
+ select case ( sym_selector )
+ case (1, 4)
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_d_lapse', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_d_lapse for boundary condition' )
+ end if
+
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_d_shift', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_d_shift for boundary condition' )
+ end if
+
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_d_curv', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_d_curv for boundary condition' )
+ end if
+
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_d_metric', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_d_metric for boundary condition' )
+ end if
+ end select
+
+ select case ( sym_selector )
+ case (1, 3)
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_res_lapse', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_res_lapse for boundary condition' )
+ end if
+
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_res_shift', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_res_shift for boundary condition' )
+ end if
+
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_res_curv', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_res_curv for boundary condition' )
+ end if
+
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_res_metric', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_res_metric for boundary condition' )
+ end if
+ end select
+
+ select case ( sym_selector )
+ case (1, 2, 3)
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_red_all', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_red_all for boundary condition' )
+ end if
+ end select
+
+ select case ( sym_selector )
+ case (2)
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_q_lapse', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_q_lapse for boundary condition' )
+ end if
+
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_q_shift', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_q_shift for boundary condition' )
+ end if
+
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_q_curv', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_q_curv for boundary condition' )
+ end if
+
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'NoExcision::cg_q_metric', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select cg_q_metric for boundary condition' )
+ end if
+ end select
+
+ select case ( sym_selector )
+ case (3)
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'ADMBase::lapse', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select lapse for boundary condition' )
+ end if
+
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'ADMBase::shift', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select shift for boundary condition' )
+ end if
+
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'ADMBase::curv', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select curv for boundary condition' )
+ end if
+
+ ierr = Boundary_SelectGroupForBC ( cctkGH, CCTK_ALL_FACES, 1, -1, &
+ 'ADMBase::metric', 'None' )
+ if ( ierr /= 0 ) then
+ call CCTK_WARN ( 0, 'Could not select metric for boundary condition' )
+ end if
+ end select
+
+ end if
+
+end subroutine NoExcision_CGApplySym
diff --git a/src/getlevelinfo.cc b/src/getlevelinfo.cc
new file mode 100644
index 0000000..4b68abb
--- /dev/null
+++ b/src/getlevelinfo.cc
@@ -0,0 +1,45 @@
+/* $Header$ */
+
+#include <cstdio>
+#include <cmath>
+
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Parameters.h"
+#include "cctk_DefineThorn.h"
+
+#include "carpet.hh"
+
+namespace NoExcision {
+
+#ifdef HAVE_CARPET
+ using namespace Carpet;
+#endif
+
+ extern "C"
+ void NoExcision_levelinfo(const cGH * cctkGH,
+ CCTK_INT * my_level,
+ CCTK_INT * n_levels)
+ {
+
+ *my_level = 0;
+ *n_levels = 1;
+
+#ifdef HAVE_CARPET
+
+ if ( CCTK_IsThornActive ( "Carpet" ) ) {
+ *my_level = reflevel;
+ *n_levels = reflevels;
+ }
+
+#endif
+
+ }
+
+ extern "C"
+ CCTK_FCALL void CCTK_FNAME (NoExcision_levelinfo) (CCTK_POINTER_TO_CONST * cctkGH, CCTK_INT * my_level, CCTK_INT * n_levels)
+ {
+ NoExcision_levelinfo((const cGH *)* cctkGH, my_level, n_levels);
+ }
+
+} // namespace NoExcision
diff --git a/src/make.code.defn b/src/make.code.defn
index 7dd625c..a174c46 100644
--- a/src/make.code.defn
+++ b/src/make.code.defn
@@ -2,7 +2,7 @@
# $Header$
# Source files in this directory
-SRCS = overwrite.F90
+SRCS = NoExcision_mod.F90 overwrite.F90 smooth.F90 reduce.F90 reduce.c getlevelinfo.cc cg.F90
# Subdirectories containing source files
SUBDIRS =
diff --git a/src/make.code.deps b/src/make.code.deps
new file mode 100644
index 0000000..e7f8124
--- /dev/null
+++ b/src/make.code.deps
@@ -0,0 +1 @@
+cg.F90.o: NoExcision_mod.F90.o
diff --git a/src/overwrite.F90 b/src/overwrite.F90
index 6c6089f..3df9ffb 100644
--- a/src/overwrite.F90
+++ b/src/overwrite.F90
@@ -10,85 +10,114 @@ subroutine NoExcision_Overwrite (CCTK_ARGUMENTS)
DECLARE_CCTK_ARGUMENTS
DECLARE_CCTK_FUNCTIONS
DECLARE_CCTK_PARAMETERS
-
+
CCTK_REAL, parameter :: zero=0
CCTK_REAL :: dist2 (cctk_lsh(1), cctk_lsh(2), cctk_lsh(3))
- CCTK_REAL :: cx, cy, cz, rad, width
+ CCTK_REAL :: cx, cy, cz, radx, rady, radz, width
integer :: n
+
+ integer, parameter :: sm_linear = 1
+ integer, parameter :: sm_spline = 2
+ integer, parameter :: sm_cosine = 3
+ integer :: sm_type
+
+ if (CCTK_EQUALS(method,"old")) then
+ do n = 1, num_regions
+
+ cx = centre_x(n)
+ cy = centre_y(n)
+ cz = centre_z(n)
+ if (CCTK_EQUALS(region_shape(n), "sphere")) then
+ radx = radius(n)
+ rady = radius(n)
+ radz = radius(n)
+ else if (CCTK_EQUALS(region_shape(n), "ellipsoid")) then
+ radx = radius_x(n)
+ rady = radius_y(n)
+ radz = radius_z(n)
+ else
+ call CCTK_WARN (0, "internal error")
+ end if
+
+ if (CCTK_EQUALS (smoothing_function(n), "linear")) then
+ sm_type = sm_linear
+ else if (CCTK_EQUALS (smoothing_function(n), "spline")) then
+ sm_type = sm_spline
+ else if (CCTK_EQUALS (smoothing_function(n), "cosine")) then
+ sm_type = sm_cosine
+ else
+ call CCTK_WARN (0, "internal error")
+ end if
+ width = smoothing_zone_width(n)
+
+ dist2 = ((x - cx) / radx)**2 + ((y - cy) / rady)**2 &
+ & + ((z - cz) / radz)**2
+
+ if (overwrite_geometry(n) /= 0) then
+
+ if (conformal_state >= 1) then
+ where (dist2 <= 1)
+ psi = 1
+ end where
+ end if
+ if (conformal_state >= 2) then
+ where (dist2 <= 1)
+ psix = 0
+ psiy = 0
+ psiz = 0
+ end where
+ end if
+ if (conformal_state >= 3) then
+ where (dist2 <= 1)
+ psixx = 0
+ psixy = 0
+ psixz = 0
+ psiyy = 0
+ psiyz = 0
+ psizz = 0
+ end where
+ end if
- do n = 1, num_regions
-
- cx = centre_x(n)
- cy = centre_y(n)
- cz = centre_z(n)
- rad = radius(n)
- width = smoothing_zone_width(n)
-
- dist2 = (x - cx)**2 + (y - cy)**2 + (z - cz)**2
-
- if (overwrite_geometry(n) /= 0) then
-
- if (conformal_state >= 1) then
- where (dist2 <= rad**2)
- psi = 1
- end where
- end if
- if (conformal_state >= 2) then
- where (dist2 <= rad**2)
- psix = 0
- psiy = 0
- psiz = 0
- end where
- end if
- if (conformal_state >= 3) then
- where (dist2 <= rad**2)
- psixx = 0
- psixy = 0
- psixz = 0
- psiyy = 0
- psiyz = 0
- psizz = 0
- end where
- end if
-
- where (dist2 <= rad**2)
- gxx = smooth (gxx, Minkowski_scale(n), dist2)
- gxy = smooth (gxy, zero , dist2)
- gxz = smooth (gxz, zero , dist2)
- gyy = smooth (gyy, Minkowski_scale(n), dist2)
- gyz = smooth (gyz, zero , dist2)
- gzz = smooth (gzz, Minkowski_scale(n), dist2)
- kxx = smooth (kxx, zero , dist2)
- kxy = smooth (kxy, zero , dist2)
- kxz = smooth (kxz, zero , dist2)
- kyy = smooth (kyy, zero , dist2)
- kyz = smooth (kyz, zero , dist2)
- kzz = smooth (kzz, zero , dist2)
- end where
-
- end if
-
- if (overwrite_lapse(n) /= 0) then
-
- where (dist2 <= rad**2)
- alp = smooth (alp, lapse_scale(n), dist2)
- end where
-
- end if
-
- if (overwrite_shift(n) /= 0) then
-
- if (shift_state /= 0) then
- where (dist2 <= rad**2)
- betax = smooth (betax, zero, dist2)
- betay = smooth (betay, zero, dist2)
- betaz = smooth (betaz, zero, dist2)
- end where
- end if
-
- end if
-
- end do
+ where (dist2 <= 1)
+ gxx = smooth (gxx, Minkowski_scale(n), dist2)
+ gxy = smooth (gxy, zero , dist2)
+ gxz = smooth (gxz, zero , dist2)
+ gyy = smooth (gyy, Minkowski_scale(n), dist2)
+ gyz = smooth (gyz, zero , dist2)
+ gzz = smooth (gzz, Minkowski_scale(n), dist2)
+ kxx = smooth (kxx, zero , dist2)
+ kxy = smooth (kxy, zero , dist2)
+ kxz = smooth (kxz, zero , dist2)
+ kyy = smooth (kyy, zero , dist2)
+ kyz = smooth (kyz, zero , dist2)
+ kzz = smooth (kzz, zero , dist2)
+ end where
+
+ end if
+
+ if (overwrite_lapse(n) /= 0) then
+
+ where (dist2 <= 1)
+ alp = smooth (alp, lapse_scale(n), dist2)
+ end where
+
+ end if
+
+ if (overwrite_shift(n) /= 0) then
+
+ if (shift_state /= 0) then
+ where (dist2 <= 1)
+ betax = smooth (betax, zero, dist2)
+ betay = smooth (betay, zero, dist2)
+ betaz = smooth (betaz, zero, dist2)
+ end where
+ end if
+
+ end if
+
+ end do
+
+ end if
contains
@@ -98,13 +127,32 @@ contains
CCTK_REAL, intent(in) :: goodval
CCTK_REAL, intent(in) :: dist2
- if (dist2 <= (rad-width)**2) then
+ CCTK_REAL, parameter :: zero=0, two=2, half=1/two
+ integer, parameter :: rk = kind(zero)
+ CCTK_REAL, parameter :: pi = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068_rk
+ CCTK_REAL :: dist
+ CCTK_REAL :: x, f
+
+ if (dist2 <= (1 - width)**2) then
newval = goodval
- else if (width == 0 .or. dist2 >= rad**2) then
+ else if (width == 0 .or. dist2 >= 1) then
newval = oldval
else
- newval = goodval &
- & + (oldval - goodval) * (sqrt(dist2) - (rad-width)) / width
+ dist = sqrt(dist2)
+ x = 1 - (1 - dist) / width
+ select case (sm_type)
+ case (sm_linear)
+ f = x
+ case (sm_spline)
+ if (x < half) then
+ f = 2 * x**2
+ else
+ f = 1 - 2 * (1-x)**2
+ end if
+ case (sm_cosine)
+ f = (1 - cos (pi * x)) / 2
+ end select
+ newval = oldval * f + goodval * (1 - f)
end if
end function smooth
diff --git a/src/overwriteBSSN.F90 b/src/overwriteBSSN.F90
new file mode 100644
index 0000000..cef380a
--- /dev/null
+++ b/src/overwriteBSSN.F90
@@ -0,0 +1,248 @@
+! $Header$
+
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Functions.h"
+#include "cctk_Parameters.h"
+
+subroutine NoExcision_OverwriteBSSN (CCTK_ARGUMENTS)
+ implicit none
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_FUNCTIONS
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_REAL, parameter :: zero=0
+ CCTK_REAL :: dist2 (cctk_lsh(1), cctk_lsh(2), cctk_lsh(3))
+ CCTK_REAL :: cx, cy, cz, radx, rady, radz, width, scale
+ integer :: timelevels
+ integer :: n
+
+ integer, parameter :: sm_linear = 1
+ integer, parameter :: sm_spline = 2
+ integer :: sm_type
+
+ do n = 1, num_regions
+
+ if (cctk_iteration == iteration(n)) then
+
+ cx = centre_x(n)
+ cy = centre_y(n)
+ cz = centre_z(n)
+ if (CCTK_EQUALS(region_shape(n), "sphere")) then
+ radx = radius(n)
+ rady = radius(n)
+ radz = radius(n)
+ else if (CCTK_EQUALS(region_shape(n), "ellipsoid")) then
+ radx = radius_x(n)
+ rady = radius_y(n)
+ radz = radius_z(n)
+ else
+ call CCTK_WARN (0, "internal error")
+ end if
+
+ if (CCTK_EQUALS (smoothing_function(n), "linear")) then
+ sm_type = sm_linear
+ else if (CCTK_EQUALS (smoothing_function(n), "spline")) then
+ sm_type = sm_spline
+ else
+ call CCTK_WARN (0, "internal error")
+ end if
+ width = smoothing_zone_width(n)
+
+ dist2 = ((x - cx) / radx)**2 + ((y - cy) / rady)**2 &
+ & + ((z - cz) / radz)**2
+
+ if (overwrite_geometry(n) /= 0) then
+
+ scale = Minkowski_scale(n)
+
+ if (conformal_state >= 1) then
+ where (dist2 <= 1)
+ psi = 1
+ end where
+ end if
+ if (conformal_state >= 2) then
+ where (dist2 <= 1)
+ psix = 0
+ psiy = 0
+ psiz = 0
+ end where
+ end if
+ if (conformal_state >= 3) then
+ where (dist2 <= 1)
+ psixx = 0
+ psixy = 0
+ psixz = 0
+ psiyy = 0
+ psiyz = 0
+ psizz = 0
+ end where
+ end if
+
+ where (dist2 <= 1)
+ ADM_BS_phi = smooth (ADM_BS_phi, zero , dist2)
+ ADM_BS_gxx = smooth (ADM_BS_gxx, scale, dist2)
+ ADM_BS_gxy = smooth (ADM_BS_gxy, zero , dist2)
+ ADM_BS_gxz = smooth (ADM_BS_gxz, zero , dist2)
+ ADM_BS_gyy = smooth (ADM_BS_gyy, scale, dist2)
+ ADM_BS_gyz = smooth (ADM_BS_gyz, zero , dist2)
+ ADM_BS_gzz = smooth (ADM_BS_gzz, scale, dist2)
+ ADM_BS_Gx = smooth (ADM_BS_Gx , zero , dist2)
+ ADM_BS_Gy = smooth (ADM_BS_Gy , zero , dist2)
+ ADM_BS_Gz = smooth (ADM_BS_Gz , zero , dist2)
+ ADM_BS_K = smooth (ADM_BS_K , zero , dist2)
+ ADM_BS_Axx = smooth (ADM_BS_Axx, zero , dist2)
+ ADM_BS_Axy = smooth (ADM_BS_Axy, zero , dist2)
+ ADM_BS_Axz = smooth (ADM_BS_Axz, zero , dist2)
+ ADM_BS_Ayy = smooth (ADM_BS_Ayy, zero , dist2)
+ ADM_BS_Ayz = smooth (ADM_BS_Ayz, zero , dist2)
+ ADM_BS_Azz = smooth (ADM_BS_Azz, zero , dist2)
+ end where
+ call CCTK_ActiveTimeLevelsVN &
+ (timelevels, cctkGH, "ADM_BSSN::ADM_BS_phi")
+ if (timelevels > 1) then
+ where (dist2 <= 1)
+ ADM_BS_phi_p = smooth (ADM_BS_phi_p, zero , dist2)
+ ADM_BS_gxx_p = smooth (ADM_BS_gxx_p, scale, dist2)
+ ADM_BS_gxy_p = smooth (ADM_BS_gxy_p, zero , dist2)
+ ADM_BS_gxz_p = smooth (ADM_BS_gxz_p, zero , dist2)
+ ADM_BS_gyy_p = smooth (ADM_BS_gyy_p, scale, dist2)
+ ADM_BS_gyz_p = smooth (ADM_BS_gyz_p, zero , dist2)
+ ADM_BS_gzz_p = smooth (ADM_BS_gzz_p, scale, dist2)
+ ADM_BS_Gx_p = smooth (ADM_BS_Gx_p , zero , dist2)
+ ADM_BS_Gy_p = smooth (ADM_BS_Gy_p , zero , dist2)
+ ADM_BS_Gz_p = smooth (ADM_BS_Gz_p , zero , dist2)
+ ADM_BS_K_p = smooth (ADM_BS_K_p , zero , dist2)
+ ADM_BS_Axx_p = smooth (ADM_BS_Axx_p, zero , dist2)
+ ADM_BS_Axy_p = smooth (ADM_BS_Axy_p, zero , dist2)
+ ADM_BS_Axz_p = smooth (ADM_BS_Axz_p, zero , dist2)
+ ADM_BS_Ayy_p = smooth (ADM_BS_Ayy_p, zero , dist2)
+ ADM_BS_Ayz_p = smooth (ADM_BS_Ayz_p, zero , dist2)
+ ADM_BS_Azz_p = smooth (ADM_BS_Azz_p, zero , dist2)
+ end where
+ end if
+ if (timelevels > 2) then
+ where (dist2 <= 1)
+ ADM_BS_phi_p_p = smooth (ADM_BS_phi_p_p, zero , dist2)
+ ADM_BS_gxx_p_p = smooth (ADM_BS_gxx_p_p, scale, dist2)
+ ADM_BS_gxy_p_p = smooth (ADM_BS_gxy_p_p, zero , dist2)
+ ADM_BS_gxz_p_p = smooth (ADM_BS_gxz_p_p, zero , dist2)
+ ADM_BS_gyy_p_p = smooth (ADM_BS_gyy_p_p, scale, dist2)
+ ADM_BS_gyz_p_p = smooth (ADM_BS_gyz_p_p, zero , dist2)
+ ADM_BS_gzz_p_p = smooth (ADM_BS_gzz_p_p, scale, dist2)
+ ADM_BS_Gx_p_p = smooth (ADM_BS_Gx_p_p , zero , dist2)
+ ADM_BS_Gy_p_p = smooth (ADM_BS_Gy_p_p , zero , dist2)
+ ADM_BS_Gz_p_p = smooth (ADM_BS_Gz_p_p , zero , dist2)
+ ADM_BS_K_p_p = smooth (ADM_BS_K_p_p , zero , dist2)
+ ADM_BS_Axx_p_p = smooth (ADM_BS_Axx_p_p, zero , dist2)
+ ADM_BS_Axy_p_p = smooth (ADM_BS_Axy_p_p, zero , dist2)
+ ADM_BS_Axz_p_p = smooth (ADM_BS_Axz_p_p, zero , dist2)
+ ADM_BS_Ayy_p_p = smooth (ADM_BS_Ayy_p_p, zero , dist2)
+ ADM_BS_Ayz_p_p = smooth (ADM_BS_Ayz_p_p, zero , dist2)
+ ADM_BS_Azz_p_p = smooth (ADM_BS_Azz_p_p, zero , dist2)
+ end where
+ end if
+
+ end if
+
+ if (overwrite_lapse(n) /= 0) then
+
+ scale = lapse_scale(n)
+
+ where (dist2 <= 1)
+ alp = smooth (alp , scale, dist2)
+ ADM_BS_dtalp = smooth (ADM_BS_dtalp, zero , dist2)
+ end where
+ call CCTK_ActiveTimeLevelsVN &
+ (timelevels, cctkGH, "ADMBase::alp")
+ if (timelevels > 1) then
+ where (dist2 <= 1)
+ alp_p = smooth (alp_p , scale, dist2)
+ ADM_BS_dtalp_p = smooth (ADM_BS_dtalp_p, zero , dist2)
+ end where
+ end if
+ if (timelevels > 2) then
+ where (dist2 <= 1)
+ alp_p_p = smooth (alp_p_p , scale, dist2)
+ ADM_BS_dtalp_p_p = smooth (ADM_BS_dtalp_p_p, zero , dist2)
+ end where
+ end if
+
+ end if
+
+ if (overwrite_shift(n) /= 0) then
+
+ if (shift_state /= 0) then
+ where (dist2 <= 1)
+ betax = smooth (betax , zero, dist2)
+ betay = smooth (betay , zero, dist2)
+ betaz = smooth (betaz , zero, dist2)
+ ADM_BS_Bx = smooth (ADM_BS_Bx, zero, dist2)
+ ADM_BS_By = smooth (ADM_BS_By, zero, dist2)
+ ADM_BS_Bz = smooth (ADM_BS_Bz, zero, dist2)
+ end where
+ call CCTK_ActiveTimeLevelsVN &
+ (timelevels, cctkGH, "ADMBase::betax")
+ if (timelevels > 1) then
+ where (dist2 <= 1)
+ betax_p = smooth (betax_p , zero, dist2)
+ betay_p = smooth (betay_p , zero, dist2)
+ betaz_p = smooth (betaz_p , zero, dist2)
+ ADM_BS_Bx_p = smooth (ADM_BS_Bx_p, zero, dist2)
+ ADM_BS_By_p = smooth (ADM_BS_By_p, zero, dist2)
+ ADM_BS_Bz_p = smooth (ADM_BS_Bz_p, zero, dist2)
+ end where
+ end if
+ if (timelevels > 2) then
+ where (dist2 <= 1)
+ betax_p_p = smooth (betax_p_p , zero, dist2)
+ betay_p_p = smooth (betay_p_p , zero, dist2)
+ betaz_p_p = smooth (betaz_p_p , zero, dist2)
+ ADM_BS_Bx_p_p = smooth (ADM_BS_Bx_p_p, zero, dist2)
+ ADM_BS_By_p_p = smooth (ADM_BS_By_p_p, zero, dist2)
+ ADM_BS_Bz_p_p = smooth (ADM_BS_Bz_p_p, zero, dist2)
+ end where
+ end if
+ end if
+
+ end if
+
+ end if
+
+ end do
+
+contains
+
+ elemental function smooth (oldval, goodval, dist2) result (newval)
+ CCTK_REAL :: newval
+ CCTK_REAL, intent(in) :: oldval
+ CCTK_REAL, intent(in) :: goodval
+ CCTK_REAL, intent(in) :: dist2
+
+ CCTK_REAL, parameter :: two=2, half=1/two
+ CCTK_REAL :: dist
+ CCTK_REAL :: x, f
+
+ if (dist2 <= (1 - width)**2) then
+ newval = goodval
+ else if (width == 0 .or. dist2 >= 1) then
+ newval = oldval
+ else
+ dist = sqrt(dist2)
+ x = 1 - (1 - dist) / width
+ select case (sm_type)
+ case (sm_linear)
+ f = x
+ case (sm_spline)
+ if (x < half) then
+ f = 2 * x**2
+ else
+ f = 1 - 2 * (1-x)**2
+ end if
+ end select
+ newval = oldval * f + goodval * (1 - f)
+ end if
+
+ end function smooth
+
+end subroutine NoExcision_OverwriteBSSN
diff --git a/src/reduce.F90 b/src/reduce.F90
new file mode 100644
index 0000000..ab7b70e
--- /dev/null
+++ b/src/reduce.F90
@@ -0,0 +1,97 @@
+! $Header$
+
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Functions.h"
+#include "cctk_Parameters.h"
+
+subroutine NoExcision_Reduce (cctk_iteration, cctk_lsh, rhs, x, y, z)
+ implicit none
+ DECLARE_CCTK_FUNCTIONS
+ DECLARE_CCTK_PARAMETERS
+
+ integer :: cctk_iteration
+ integer :: cctk_lsh(3)
+ CCTK_REAL, dimension(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3)) :: rhs, x, y, z
+
+ CCTK_REAL, parameter :: zero=0
+ CCTK_REAL, dimension(cctk_lsh(1),cctk_lsh(2),cctk_lsh(3)) :: dist2
+ CCTK_REAL :: cx, cy, cz, radx, rady, radz, width
+ integer :: n
+
+ integer, parameter :: sm_linear = 1
+ integer, parameter :: sm_spline = 2
+ integer :: sm_type
+
+ do n = 1, num_regions
+ if (reduce_rhs(n) /= 0) then
+
+ cx = centre_x(n)
+ cy = centre_y(n)
+ cz = centre_z(n)
+ if (CCTK_EQUALS(region_shape(n), "sphere")) then
+ radx = radius(n)
+ rady = radius(n)
+ radz = radius(n)
+ else if (CCTK_EQUALS(region_shape(n), "ellipsoid")) then
+ radx = radius_x(n)
+ rady = radius_y(n)
+ radz = radius_z(n)
+ else
+ call CCTK_WARN (0, "internal error")
+ end if
+
+ if (CCTK_EQUALS (smoothing_function(n), "linear")) then
+ sm_type = sm_linear
+ else if (CCTK_EQUALS (smoothing_function(n), "spline")) then
+ sm_type = sm_spline
+ else
+ call CCTK_WARN (0, "internal error")
+ end if
+ width = smoothing_zone_width(n)
+
+ dist2 = (x - cx)**2 + (y - cy)**2 + (z - cz)**2
+
+#warning "TODO: reduce not only the RHS, but also drive the variables towards Minkowski"
+ where (dist2 <= 1)
+ rhs = smooth (rhs, rhs * reduction_factor(n), dist2)
+ end where
+
+ end if
+ end do
+
+contains
+
+ elemental function smooth (oldval, goodval, dist2) result (newval)
+ CCTK_REAL :: newval
+ CCTK_REAL, intent(in) :: oldval
+ CCTK_REAL, intent(in) :: goodval
+ CCTK_REAL, intent(in) :: dist2
+
+ CCTK_REAL, parameter :: two=2, half=1/two
+ CCTK_REAL :: dist
+ CCTK_REAL :: x, f
+
+ if (dist2 <= (1 - width)**2) then
+ newval = goodval
+ else if (width == 0 .or. dist2 >= 1) then
+ newval = oldval
+ else
+ dist = sqrt(dist2)
+ x = 1 - (1 - dist) / width
+ select case (sm_type)
+ case (sm_linear)
+ f = x
+ case (sm_spline)
+ if (x < half) then
+ f = 2 * x**2
+ else
+ f = 1 - 2 * (1-x)**2
+ end if
+ end select
+ newval = oldval * f + goodval * (1 - f)
+ end if
+
+ end function smooth
+
+end subroutine NoExcision_Reduce
diff --git a/src/reduce.c b/src/reduce.c
new file mode 100644
index 0000000..0b44ca2
--- /dev/null
+++ b/src/reduce.c
@@ -0,0 +1,34 @@
+/* $Header$ */
+
+#include <assert.h>
+
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Parameters.h"
+
+void CCTK_FCALL
+CCTK_FNAME(NoExcision_Reduce) (int const * cctk_iteration,
+ int const * cctk_lsh,
+ CCTK_REAL * rhs,
+ CCTK_REAL const * x,
+ CCTK_REAL const * y,
+ CCTK_REAL const * z);
+
+void
+NoExcision_Reduce (CCTK_ARGUMENTS)
+{
+ DECLARE_CCTK_ARGUMENTS;
+ DECLARE_CCTK_PARAMETERS;
+
+ int var, rhs;
+ void * ptr;
+
+ for (var=0; var<CCTK_NumVars(); ++var) {
+ rhs = MoLQueryEvolvedRHS (var);
+ if (rhs >= 0) {
+ ptr = CCTK_VarDataPtrI (cctkGH, 0, rhs);
+ assert (ptr);
+ CCTK_FNAME(NoExcision_Reduce) (& cctk_iteration, cctk_lsh, ptr, x, y, z);
+ }
+ }
+}
diff --git a/src/smooth.F90 b/src/smooth.F90
new file mode 100644
index 0000000..d6df156
--- /dev/null
+++ b/src/smooth.F90
@@ -0,0 +1,150 @@
+! $Header$
+
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Functions.h"
+#include "cctk_Parameters.h"
+
+subroutine NoExcision_Smooth (CCTK_ARGUMENTS)
+ implicit none
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_FUNCTIONS
+ DECLARE_CCTK_PARAMETERS
+
+ CCTK_REAL, parameter :: zero=0
+ CCTK_REAL :: mask (cctk_lsh(1), cctk_lsh(2), cctk_lsh(3))
+ CCTK_REAL :: cx, cy, cz, radx, rady, radz
+ integer :: n
+ integer :: iter
+ integer :: ierr
+
+ do iter = 1, smoothing_iterations
+
+ do n = 1, num_regions
+
+ cx = centre_x(n)
+ cy = centre_y(n)
+ cz = centre_z(n)
+ if (CCTK_EQUALS(region_shape(n), "sphere")) then
+ radx = radius(n)
+ rady = radius(n)
+ radz = radius(n)
+ else if (CCTK_EQUALS(region_shape(n), "ellipsoid")) then
+ radx = radius_x(n)
+ rady = radius_y(n)
+ radz = radius_z(n)
+ else
+ call CCTK_WARN (0, "internal error")
+ end if
+
+ mask = 1 - sqrt (((x - cx) / radx)**2 + &
+ & ((y - cy) / rady)**2 + &
+ & ((z - cz) / radz)**2)
+ where (mask <= 0)
+ mask = 0 ! outside
+ else where (mask >= smoothing_zone_width(n))
+ mask = 1 ! far inside
+ elsewhere
+ mask = mask / smoothing_zone_width(n) ! a bit inside
+ end where
+
+ if (overwrite_geometry(n) /= 0) then
+
+ if (conformal_state >= 1) then
+ call smooth (psi)
+ end if
+ if (conformal_state >= 2) then
+ call smooth (psix)
+ call smooth (psiy)
+ call smooth (psiz)
+ end if
+ if (conformal_state >= 3) then
+ call smooth (psixx)
+ call smooth (psixy)
+ call smooth (psixz)
+ call smooth (psiyy)
+ call smooth (psiyz)
+ call smooth (psizz)
+ end if
+
+ call smooth (gxx)
+ call smooth (gxy)
+ call smooth (gxz)
+ call smooth (gyy)
+ call smooth (gyz)
+ call smooth (gzz)
+ call smooth (kxx)
+ call smooth (kxy)
+ call smooth (kxz)
+ call smooth (kyy)
+ call smooth (kyz)
+ call smooth (kzz)
+
+ end if
+
+ if (overwrite_lapse(n) /= 0) then
+
+ call smooth (alp)
+
+ end if
+
+ if (overwrite_shift(n) /= 0) then
+
+ if (shift_state /= 0) then
+ call smooth (betax)
+ call smooth (betay)
+ call smooth (betaz)
+ end if
+
+ end if
+
+ end do
+
+ if (overwrite_geometry(n) /= 0) then
+
+ if (conformal_state >= 1) then
+ call CCTK_SyncGroup (ierr, cctkGH, "StaticConformal::confac")
+ end if
+ if (conformal_state >= 2) then
+ call CCTK_SyncGroup (ierr, cctkGH, "StaticConformal::confac_1derivs")
+ end if
+ if (conformal_state >= 3) then
+ call CCTK_SyncGroup (ierr, cctkGH, "StaticConformal::confac_2derivs")
+ end if
+
+ call CCTK_SyncGroup (ierr, cctkGH, "ADMBase::metric")
+ call CCTK_SyncGroup (ierr, cctkGH, "ADMBase::curv")
+
+ end if
+
+ if (overwrite_lapse(n) /= 0) then
+
+ call CCTK_SyncGroup (ierr, cctkGH, "ADMBase::lapse")
+
+ end if
+
+ if (overwrite_shift(n) /= 0) then
+
+ if (shift_state /= 0) then
+ call CCTK_SyncGroup (ierr, cctkGH, "ADMBase::shift")
+ end if
+
+ end if
+
+ end do
+
+contains
+
+ subroutine smooth (val)
+ CCTK_REAL, intent(inout) :: val(:,:,:)
+
+ where (mask > 0)
+ val = (1 - mask * smoothing_factor) * val &
+ & + (mask * smoothing_factor / 6) &
+ & * (+ eoshift(val, +1, dim=1) + eoshift(val, -1, dim=1) &
+ & + eoshift(val, +1, dim=2) + eoshift(val, -1, dim=2) &
+ & + eoshift(val, +1, dim=3) + eoshift(val, -1, dim=3))
+ end where
+ end subroutine smooth
+
+end subroutine NoExcision_Smooth