From d0996756f16854156bbc5ea455da5de98f1ead30 Mon Sep 17 00:00:00 2001 From: reisswig Date: Fri, 2 Nov 2007 17:57:09 +0000 Subject: new setup.cc git-svn-id: http://svn.cactuscode.org/arrangements/CactusNumerical/SphericalSurface/trunk@29 40f6ab95-0e4f-0410-8daa-ee8d7420be1d --- src/setup.cc | 451 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 451 insertions(+) create mode 100644 src/setup.cc diff --git a/src/setup.cc b/src/setup.cc new file mode 100644 index 0000000..f7aa0be --- /dev/null +++ b/src/setup.cc @@ -0,0 +1,451 @@ +/* $Header$ */ + +#include +#include + +#include "cctk.h" +#include "cctk_Arguments.h" +#include "cctk_Parameters.h" + +#include "mpi.h" +#include + +#include "carpet.hh" + + +//#define DEBUG + + +#define round(x) (x<0?ceil((x)-0.5):floor((x)+0.5)) + +#define INITIAL_VAL 10000 + + +//TODO: overlap with finer levels still seems to be incorrect! + + +extern "C" void SphericalSurface_Setup (CCTK_ARGUMENTS) +{ + DECLARE_CCTK_ARGUMENTS; + DECLARE_CCTK_PARAMETERS; + + CCTK_REAL const pi = 3.1415926535897932384626433832795028841971693993751; + + int group; + cGroup groupinfo; + cGroupDynamicData groupdata; + + int n; + int ierr; + + + + if (nsurfaces == 0) return; + + + + group = CCTK_GroupIndex ("SphericalSurface::sf_radius"); + assert (group>=0); + ierr = CCTK_GroupData (group, &groupinfo); + assert (!ierr); + ierr = CCTK_GroupDynamicData (cctkGH, group, &groupdata); + assert (!ierr); + + + + for (n=0; n= ntheta[n]); + assert (groupdata.gsh[1] >= nphi[n]); + + assert (ntheta[n] >= 3*nghoststheta[n] && ntheta[n] <= maxntheta); + assert (nphi[n] >= 3*nghostsphi[n] && nphi[n] <= maxnphi); + + + + /* copy parameters into grid functions */ + sf_ntheta[n] = ntheta[n]; + sf_nphi[n] = nphi[n]; + sf_nghoststheta[n] = nghoststheta[n]; + sf_nghostsphi[n] = nghostsphi[n]; + } + else + { + // we already have an approximate delta-spacing calculated in "SetupRes" + // based on that, we calculate the number of necessary gridpoints... + + double theta_range = pi; + double phi_range = 2*pi; + + if (symmetric_x[n]) + phi_range /= 2; + + if (symmetric_y[n]) + phi_range /= 2; + + if (symmetric_z[n]) + theta_range /= 2; + + sf_ntheta[n] = round(theta_range/sf_delta_theta_estimate[n]) + 2*nghoststheta[n]; + sf_nphi[n] = round(phi_range/sf_delta_phi_estimate[n]) + 2*nghostsphi[n]; + + // ...make number of theta-gridpoints odd... + if (sf_ntheta[n] % 2 != 1) + sf_ntheta[n] += 1; + + // ... and make inner phi-gridpoints devidable by 4 since some thorns require that (eg IsolatedHorizon) + sf_nphi[n] += 4 - (sf_nphi[n]-2*nghostsphi[n]) % 4 + 2*nghostsphi[n]; + + // consistency check + assert (sf_ntheta[n] >= 3*nghoststheta[n] && sf_ntheta[n] <= maxntheta); + assert (sf_nphi[n] >= 3*nghostsphi[n] && sf_nphi[n] <= maxnphi); + + // check, if there are enough maxntheta,maxnphi gridpoints to remove symmetries + // (some thorns require that) + if (symmetric_z[n]) + { + if (2*(sf_ntheta[n]-2*nghoststheta[n])+2*nghoststheta[n] > maxntheta) + CCTK_WARN(0, "maxntheta is not big enough to remove z-symmetry (some thorns may require that)!"); + } + + if (symmetric_x[n]) + { + if (symmetric_y[n]) + { + if (4*(sf_nphi[n]-2*nghostsphi[n])+2*nghostsphi[n] > maxnphi) + { + CCTK_WARN(0, "maxnphi is not big enough to remove x-symmetry and y-symmetry (some thorns may require that)!"); + } + } + else + { + if (2*(sf_nphi[n]-2*nghostsphi[n])+2*nghostsphi[n] > maxnphi) + { + CCTK_WARN(0, "maxnphi is not big enough to remove x-symmetry and y-symmetry (some thorns may require that)!"); + } + } + } + else + { + if (symmetric_y[n]) + { + if (2*(sf_nphi[n]-2*nghostsphi[n])+2*nghostsphi[n] > maxnphi) + { + CCTK_WARN(0, "maxnphi is not big enough to remove x-symmetry and y-symmetry (some thorns may require that)!"); + } + } + } + + + sf_nghoststheta[n] = nghoststheta[n]; + sf_nghostsphi[n] = nghostsphi[n]; + + if (verbose) + { + printf("SphericalSurface[%d]: setting sf_ntheta = %d\n", n, sf_ntheta[n]); + printf("SphericalSurface[%d]: setting sf_nphi = %d\n", n, sf_nphi[n]); + } + } + + if (verbose) + { + printf("SphericalSurface[%d]: finest refinement-level that fully contains this surface: sf_maxreflevel = %d\n", n, sf_maxreflevel[n]); + printf("SphericalSurface[%d]: finest refinement-level that overlaps with this surface : sf_minreflevel = %d\n", n, sf_minreflevel[n]); + } + + /* coordinates in the theta direction */ + /* avoid_sf_origin_theta = 1 */ + if (symmetric_z[n]) { + + /* upper hemisphere: z>=0, theta in (0, pi/2) */ + sf_delta_theta[n] = pi/2 / (sf_ntheta[n] - 2*nghoststheta[n] - 0.5); + sf_origin_theta[n] = - (nghoststheta[n] - 0.5) * sf_delta_theta[n]; + + } else { + + /* both hemispheres: theta in (0, pi) */ + sf_delta_theta[n] = pi / (sf_ntheta[n] - 2*nghoststheta[n]); + sf_origin_theta[n] = - (nghoststheta[n] - 0.5) * sf_delta_theta[n]; + + } + + + + /* coordinates in the phi direction */ + /* avoid_sf_origin_phi = 0 */ + if (symmetric_x[n]) { + if (symmetric_y[n]) { + + /* one quadrant: x>=0, y>=0, phi in [0, pi/2] */ + assert (sf_nphi[n] - 2*nghostsphi[n] >= 1); + sf_delta_phi[n] = pi/2 / (sf_nphi[n] - 2*nghostsphi[n] - 1); + sf_origin_phi[n] = - nghostsphi[n] * sf_delta_phi[n]; + + } else { + + /* two quadrants: x>=0, phi in [-pi/2, pi/2] */ + assert (sf_nphi[n] - 2*nghostsphi[n] >= 2); + sf_delta_phi[n] = pi / (sf_nphi[n] - 2*nghostsphi[n] - 1); + sf_origin_phi[n] = - pi/2 - nghostsphi[n] * sf_delta_phi[n]; + + } + } else { + if (symmetric_y[n]) { + + /* two quadrants: y>=0, phi in [0, pi] */ + assert (sf_nphi[n] - 2*nghostsphi[n] >= 2); + sf_delta_phi[n] = pi / (sf_nphi[n] - 2*nghostsphi[n] - 1); + sf_origin_phi[n] = - nghostsphi[n] * sf_delta_phi[n]; + + } else { + + /* all quadrants: phi in [0, 2pi) */ + assert (sf_nphi[n] - 2*nghostsphi[n] >= 4); + sf_delta_phi[n] = 2*pi / (sf_nphi[n] - 2*nghostsphi[n]); + sf_origin_phi[n] = - nghostsphi[n] * sf_delta_phi[n]; + + } + } + +#ifdef DEBUG + printf("SphericalSurface[%d]: sf_delta_theta = %.6f, sf_delta_phi = %.6f\n", n, sf_delta_theta[n], sf_delta_phi[n]); +#endif + + /* mark surface as uninitialised */ + sf_active[n] = 0; + sf_valid[n] = 0; + + } /* for n */ +} + + + +extern "C" void SphericalSurface_SetupRes (CCTK_ARGUMENTS) +{ + DECLARE_CCTK_ARGUMENTS; + DECLARE_CCTK_PARAMETERS; + + static int first_call = 1; + int n; + + //printf("test\n"); + + for (n=0; n= dist && // Cart. grid and SphericalSurface overlap + cart_radius+dist > my_radius && // Cart. grid patch is not fully contained in this SphericalSurface + -cart_radius+dist < my_radius) // Cart. grid patch is not outside of the spherical shell + is_overlapping = 1; + + // get resolution + if (is_overlapping) + { + if (CCTK_Equals(auto_res_grid[n], "overlap")) + { + sf_delta_theta_estimate[n] = auto_res_ratio[n] / my_radius * sqrt(CCTK_DELTA_SPACE(0)*CCTK_DELTA_SPACE(0) + + CCTK_DELTA_SPACE(1)*CCTK_DELTA_SPACE(1) + + CCTK_DELTA_SPACE(2)*CCTK_DELTA_SPACE(2)); + + sf_delta_phi_estimate[n] = auto_res_ratio[n] / my_radius * sqrt(CCTK_DELTA_SPACE(0)*CCTK_DELTA_SPACE(0) + + CCTK_DELTA_SPACE(1)*CCTK_DELTA_SPACE(1) + + CCTK_DELTA_SPACE(2)*CCTK_DELTA_SPACE(2)); + } + + // store reflevel + sf_minreflevel[n] = Carpet::reflevel; + } + else if (first_call) + { + // set to very high value initially (otherwise would be zero + // and reported as minimum value in following MPI communication) + sf_delta_theta_estimate[n] = 10000; + sf_delta_phi_estimate[n] = 10000; + } + + if (CCTK_Equals(auto_res_grid[n], "overlap")) + { + // find minimum value of "sf_delta_phi/theta" over all processors + double dummy = 0; + MPI_Allreduce(&sf_delta_theta_estimate[n], &dummy, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); + sf_delta_theta_estimate[n] = dummy; + + dummy = 0; + MPI_Allreduce(&sf_delta_phi_estimate[n], &dummy, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); + sf_delta_phi_estimate[n] = dummy; + } + + // find maximum value of "sf_minreflevel" over all processors + int idummy; + MPI_Allreduce(&sf_minreflevel[n], &idummy, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD); + sf_minreflevel[n] = idummy; + + + + // find reflevel that completely contains this surface + // FIXME: This algorithm does not take into account multiple + // disconnected refinement regions. + + + //safety margin of 6 points around sphere + CCTK_INT np = 6; + + CCTK_REAL max_radius = my_radius + ( sqrt( np*np*CCTK_DELTA_SPACE(0)*CCTK_DELTA_SPACE(0) + + np*np*CCTK_DELTA_SPACE(1)*CCTK_DELTA_SPACE(1) + + np*np*CCTK_DELTA_SPACE(2)*CCTK_DELTA_SPACE(2) ) ); + +#ifdef DEBUG + /*printf("SphericalSurface: calculated max_radius = %.12f\n", max_radius); + printf("SphericalSurface: buffer_radius = %.12f\n", sqrt( np*np*CCTK_DELTA_SPACE(0)*CCTK_DELTA_SPACE(0) + + np*np*CCTK_DELTA_SPACE(1)*CCTK_DELTA_SPACE(1) + + np*np*CCTK_DELTA_SPACE(2)*CCTK_DELTA_SPACE(2) ));*/ +#endif + + + unsigned long k[8]; + + k[0] = CCTK_GFINDEX3D(cctkGH, 0, 0, 0); + k[1] = CCTK_GFINDEX3D(cctkGH, cctk_lsh[0]-1, 0, 0); + k[2] = CCTK_GFINDEX3D(cctkGH, 0, cctk_lsh[1]-1, 0); + k[3] = CCTK_GFINDEX3D(cctkGH, cctk_lsh[0]-1, cctk_lsh[1]-1, 0); + k[4] = CCTK_GFINDEX3D(cctkGH, 0, 0, cctk_lsh[2]-1); + k[5] = CCTK_GFINDEX3D(cctkGH, cctk_lsh[0]-1, 0, cctk_lsh[2]-1); + k[6] = CCTK_GFINDEX3D(cctkGH, 0, cctk_lsh[1]-1, cctk_lsh[2]-1); + k[7] = CCTK_GFINDEX3D(cctkGH, cctk_lsh[0]-1, cctk_lsh[1]-1, cctk_lsh[2]-1); + + int i; + int is_contained = 0; + for (i=0; i < 8; i++) + { + if (max_radius < sqrt(x[k[i]]*x[k[i]] + y[k[i]]*y[k[i]] + z[k[i]]*z[k[i]])) + is_contained = 1; + } + + int max_rl = 0; + if (is_contained) + { + if (CCTK_Equals(auto_res_grid[n], "fully contained")) + { + sf_delta_theta_estimate[n] = auto_res_ratio[n] / my_radius * sqrt(CCTK_DELTA_SPACE(0)*CCTK_DELTA_SPACE(0) + + CCTK_DELTA_SPACE(1)*CCTK_DELTA_SPACE(1) + + CCTK_DELTA_SPACE(2)*CCTK_DELTA_SPACE(2)); + + sf_delta_phi_estimate[n] = auto_res_ratio[n] / my_radius * sqrt(CCTK_DELTA_SPACE(0)*CCTK_DELTA_SPACE(0) + + CCTK_DELTA_SPACE(1)*CCTK_DELTA_SPACE(1) + + CCTK_DELTA_SPACE(2)*CCTK_DELTA_SPACE(2)); + } + + max_rl = Carpet::reflevel; //(int) floor(log((double) (cctk_levfac[0])/log(2.0))+0.5)+1; + } + else if (first_call) + { + // set to zero initially + sf_delta_theta_estimate[n] = 0; + sf_delta_phi_estimate[n] = 0; + } + + + // find minimum value of "sf_maxreflevel" over all processors + MPI_Allreduce(&max_rl, &idummy, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD); + if (idummy != 0 || first_call) + sf_maxreflevel[n] = idummy; + + // this condition can become true because of this approximate algorithm + // which does not take into account disconnected ref. regions + if (sf_maxreflevel[n] > sf_minreflevel[n]) + sf_maxreflevel[n] = sf_minreflevel[n]; // can still be incorrect! + + + if (CCTK_Equals(auto_res_grid[n], "fully contained")) + { + // find maximum value of "sf_delta_phi/theta" over all processors + double dummy = 0; + MPI_Allreduce(&sf_delta_theta_estimate[n], &dummy, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); + sf_delta_theta_estimate[n] = dummy; + + dummy = 0; + MPI_Allreduce(&sf_delta_phi_estimate[n], &dummy, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); + sf_delta_phi_estimate[n] = dummy; + } + +#ifdef DEBUG + printf("SphericalSurface: sf_maxreflevel[%d] = %d, sf_minreflevel[%d] = %d \n", n, sf_maxreflevel[n], n, sf_minreflevel[n]); + printf("SphericalSurface: sf_delta_theta[%d] = %.6f, sf_delta_phi[%d] = %.6f, \n", n, sf_delta_theta_estimate[n], n, sf_delta_phi_estimate[n]); +#endif + + } + + first_call = 0; + +} + -- cgit v1.2.3