aboutsummaryrefslogtreecommitdiff
path: root/src/GRHydro_Reconstruct.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/GRHydro_Reconstruct.cc')
-rw-r--r--src/GRHydro_Reconstruct.cc504
1 files changed, 504 insertions, 0 deletions
diff --git a/src/GRHydro_Reconstruct.cc b/src/GRHydro_Reconstruct.cc
new file mode 100644
index 0000000..4d2974d
--- /dev/null
+++ b/src/GRHydro_Reconstruct.cc
@@ -0,0 +1,504 @@
+ /*@@
+ @file GRHydro_Reconstruct.cc
+ @date Thu Dec 2013
+ @author Christian Reisswig
+ @desc
+ Wrapper routine to perform the reconstruction.using tmeplate metaprogramming
+ @enddesc
+ @@*/
+
+#include <iostream>
+#include <cassert>
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Parameters.h"
+#include "cctk_Functions.h"
+
+// for calling Fortran scheduled routines from C
+#include "cctki_FortranWrappers.h"
+
+#include "SpaceMask.h"
+
+#include "GRHydro_Functions.h"
+
+#include "GRHydro_Reconstruct_drv_cxx.hh"
+#include "GRHydro_WENOReconstruct.hh"
+#include "GRHydro_TrivialReconstruct.hh"
+#include "GRHydro_TVDReconstruct.hh"
+#include "GRHydro_MP5Reconstruct.hh"
+
+#define velx (&vup[0])
+#define vely (&vup[N])
+#define velz (&vup[2*N])
+
+#define Bvecx (&Bprim[0])
+#define Bvecy (&Bprim[N])
+#define Bvecz (&Bprim[2*N])
+
+/*
+ External routines
+*/
+extern "C"
+CCTK_INT GRHydro_UseGeneralCoordinates(const cGH * cctkGH);
+
+/*
+ This is needed right now because we want to also call this from Fotran
+*/
+extern "C"
+void CCTK_FCALL CCTK_FNAME(GRHydro_PPMReconstruct_drv_opt)(cGH const * const restrict & restrict cctkGH);
+
+extern "C"
+void CCTK_FCALL CCTK_FNAME(primitive2conservativeM)(cGH const * const restrict & restrict cctkGH);
+
+
+/**
+ This class selects a reconstruction variant.
+*/
+template <class RECONSTRUCT>
+struct reconstruct
+{
+ static inline void select(const bool do_mhd,
+ const bool do_Ye,
+ const bool do_temp,
+ const bool reconstruct_Wv,
+ const bool clean_divergence,
+ cGH const * const restrict & restrict cctkGH)
+ {
+ if (!do_mhd && !do_Ye && !do_temp && reconstruct_Wv)
+ GRHydro_Reconstruct_drv_cxx <false, false, false, true, false, RECONSTRUCT > (cctkGH);
+ else if (do_mhd && !do_Ye && !do_temp && reconstruct_Wv && !clean_divergence)
+ GRHydro_Reconstruct_drv_cxx <true, false, false, true, false, RECONSTRUCT > (cctkGH);
+ else if (do_mhd && do_Ye && do_temp && reconstruct_Wv && !clean_divergence)
+ GRHydro_Reconstruct_drv_cxx <true, true, true, true, false, RECONSTRUCT > (cctkGH);
+ else if (do_mhd && !do_Ye && !do_temp && reconstruct_Wv && clean_divergence)
+ GRHydro_Reconstruct_drv_cxx <true, false, false, true, true, RECONSTRUCT > (cctkGH);
+ else if (do_mhd && do_Ye && do_temp && reconstruct_Wv && clean_divergence)
+ GRHydro_Reconstruct_drv_cxx <true, true, true, true, true, RECONSTRUCT > (cctkGH);
+ else if (!do_mhd && do_Ye && do_temp && reconstruct_Wv)
+ GRHydro_Reconstruct_drv_cxx <false, true, true, true, false, RECONSTRUCT > (cctkGH);
+ else if (!do_mhd && !do_Ye && !do_temp && !reconstruct_Wv)
+ GRHydro_Reconstruct_drv_cxx <false, false, false, false, false, RECONSTRUCT > (cctkGH);
+ else if (do_mhd && !do_Ye && !do_temp && !reconstruct_Wv && !clean_divergence)
+ GRHydro_Reconstruct_drv_cxx <true, false, false, false, false, RECONSTRUCT > (cctkGH);
+ else if (do_mhd && do_Ye && do_temp && !reconstruct_Wv && !clean_divergence)
+ GRHydro_Reconstruct_drv_cxx <true, true, true, false, false, RECONSTRUCT > (cctkGH);
+ else if (do_mhd && !do_Ye && !do_temp && !reconstruct_Wv && clean_divergence)
+ GRHydro_Reconstruct_drv_cxx <true, false, false, false, true, RECONSTRUCT > (cctkGH);
+ else if (do_mhd && do_Ye && do_temp && !reconstruct_Wv && clean_divergence)
+ GRHydro_Reconstruct_drv_cxx <true, true, true, false, true, RECONSTRUCT > (cctkGH);
+ else if (!do_mhd && do_Ye && do_temp && !reconstruct_Wv)
+ GRHydro_Reconstruct_drv_cxx <false, true, true, false, false, RECONSTRUCT > (cctkGH);
+ else
+ assert(0&&"Unsupported template arguments");
+ }
+};
+
+
+/**
+ This is a new template metaprogramming way of calling various reconstruction methods.
+ It tries to avoid duplicated code as much as possible
+*/
+
+extern "C" void Reconstruction_cxx(CCTK_ARGUMENTS)
+{
+ DECLARE_CCTK_ARGUMENTS;
+ DECLARE_CCTK_PARAMETERS;
+
+ const bool do_mhd = CCTK_EQUALS(Bvec_evolution_method, "GRHydro");
+ const bool do_Ye = CCTK_EQUALS(Y_e_evolution_method, "GRHydro");
+ const bool do_temp = CCTK_EQUALS(temperature_evolution_method, "GRHydro");
+ const bool do_clean_divergence = clean_divergence;
+
+ /*
+ Set up multipatch stuff
+ */
+
+ const CCTK_REAL * restrict vup;
+ const CCTK_REAL * restrict Bprim;
+
+ //Multipatch related pointers
+ if(GRHydro_UseGeneralCoordinates(cctkGH)) {
+ vup=lvel;
+ Bprim=lBvec;
+ } else {
+ vup=vel;
+ Bprim=Bvec;
+ }
+
+ const int nx=cctk_lsh[0];
+ const int ny=cctk_lsh[1];
+ const int nz=cctk_lsh[2];
+
+ const int N = nx*ny*nz;
+
+ int type_bits;
+ int not_trivial;
+ int trivial;
+
+ if (*flux_direction == 1) {
+ type_bits = SpaceMask_GetTypeBits("Hydro_RiemannProblemX");
+ not_trivial = SpaceMask_GetStateBits("Hydro_RiemannProblemX","not_trivial");
+ trivial = SpaceMask_GetStateBits("Hydro_RiemannProblemX","trivial");
+ } else if (*flux_direction == 2) {
+ type_bits = SpaceMask_GetTypeBits("Hydro_RiemannProblemY");
+ not_trivial = SpaceMask_GetStateBits("Hydro_RiemannProblemY","not_trivial");
+ trivial = SpaceMask_GetStateBits("Hydro_RiemannProblemY","trivial");
+ } else if (*flux_direction == 3) {
+ type_bits = SpaceMask_GetTypeBits("Hydro_RiemannProblemZ");
+ not_trivial = SpaceMask_GetStateBits("Hydro_RiemannProblemZ","not_trivial");
+ trivial = SpaceMask_GetStateBits("Hydro_RiemannProblemZ","trivial");
+ }
+
+ CCTK_REAL local_min_tracer = 1e42;
+ if (evolve_tracer) {
+ if (use_min_tracer)
+ local_min_tracer = min_tracer;
+ else
+ local_min_tracer = 0.0;
+ }
+
+ /*
+ First initialize all variables by first order trivial reconstruction!
+ */
+
+
+ if (!do_mhd && !do_Ye && !do_temp)
+ GRHydro_Reconstruct_drv_cxx <false, false, false, false, false, GRHydro_TrivialReconstruct1d > (cctkGH);
+ else if (do_mhd && !do_Ye && !do_temp && !clean_divergence)
+ GRHydro_Reconstruct_drv_cxx <true, false, false, false, false, GRHydro_TrivialReconstruct1d > (cctkGH);
+ else if (do_mhd && !do_Ye && !do_temp && clean_divergence)
+ GRHydro_Reconstruct_drv_cxx <true, false, false, false, true, GRHydro_TrivialReconstruct1d > (cctkGH);
+ else if (do_mhd && do_Ye && do_temp && !clean_divergence)
+ GRHydro_Reconstruct_drv_cxx <true, true, true, false, false, GRHydro_TrivialReconstruct1d > (cctkGH);
+ else if (do_mhd && do_Ye && do_temp && clean_divergence)
+ GRHydro_Reconstruct_drv_cxx <true, true, true, false, true, GRHydro_TrivialReconstruct1d > (cctkGH);
+ else if (!do_mhd && do_Ye && do_temp)
+ GRHydro_Reconstruct_drv_cxx <false, true, true, false, false, GRHydro_TrivialReconstruct1d > (cctkGH);
+ else
+ CCTK_ERROR("Don't know how to initialize reconstructed variables");
+
+
+ /*
+ Now do the real reconstruction!
+ */
+
+ if (CCTK_EQUALS(recon_method,"tvd")) {
+ // this handles MHD and non-MHD
+
+ if (CCTK_EQUALS(tvd_limiter, "minmod")) {
+
+ reconstruct<GRHydro_TVDReconstruct1d<0> >::select(do_mhd, do_Ye, do_temp, reconstruct_Wv, clean_divergence, cctkGH);
+
+ } else if (CCTK_EQUALS(tvd_limiter, "vanleerMC2")) {
+
+ reconstruct<GRHydro_TVDReconstruct1d<1> >::select(do_mhd, do_Ye, do_temp, reconstruct_Wv, clean_divergence, cctkGH);
+
+ } else if (CCTK_EQUALS(tvd_limiter, "superbee")) {
+
+ reconstruct<GRHydro_TVDReconstruct1d<2> >::select(do_mhd, do_Ye, do_temp, reconstruct_Wv, clean_divergence, cctkGH);
+
+ } else {
+ CCTK_ERROR("TVD limiter not recognized!");
+ }
+
+ } else if (CCTK_EQUALS(recon_method,"ppm")) {
+ // PPM is special. It cannot reconstruct individual functions.
+ // Rather, all function are reconstructed at once!
+ // Hence we have a specialized calling function.
+
+ CCTK_FNAME(GRHydro_PPMReconstruct_drv_opt)(cctkGH);
+
+ } else if (CCTK_EQUALS(recon_method,"eno")) {
+ // this handles MHD and non-MHD
+
+ // TODO!!
+ CCTK_ERROR("Sorry. Eno reconstruction not yet implemented!");
+
+ } else if (CCTK_EQUALS(recon_method,"weno")) {
+ // this handles MHD and non-MHD
+
+ if (weno_adaptive_epsilon) {
+
+ reconstruct<GRHydro_WENOReconstruct1d_cxx<false, true> >::select(do_mhd, do_Ye, do_temp, reconstruct_Wv, clean_divergence, cctkGH);
+
+ } else {
+
+ reconstruct<GRHydro_WENOReconstruct1d_cxx<false, false> >::select(do_mhd, do_Ye, do_temp, reconstruct_Wv, clean_divergence, cctkGH);
+
+ }
+
+ } else if (CCTK_EQUALS(recon_method, "weno-z")) {
+
+ reconstruct<GRHydro_WENOReconstruct1d_cxx<true, false> >::select(do_mhd, do_Ye, do_temp, reconstruct_Wv, clean_divergence, cctkGH);
+
+ } else if (CCTK_EQUALS(recon_method,"mp5")) {
+ // this handles MHD and non-MHD
+
+ if (mp5_adaptive_eps)
+ reconstruct<GRHydro_MP5Reconstruct1d_cxx<true> >::select(do_mhd, do_Ye, do_temp, reconstruct_Wv, clean_divergence, cctkGH);
+ else
+ reconstruct<GRHydro_MP5Reconstruct1d_cxx<false> >::select(do_mhd, do_Ye, do_temp, reconstruct_Wv, clean_divergence, cctkGH);
+
+ } else
+ CCTK_ERROR("Reconstruction method not recognized!");
+
+
+ /*
+ Here goes the excision treatment.
+ If any of the points in the reconstruction stencil is excised,
+ we switch to trivial reconstruction.
+ If the current point itself is excised, we mark the Riemann problem as "trivial".
+ If the current point is just one point away from an excision boundary, we use the current cell values
+ to provide an "extrapolated" guess for the reconstructed state at the excision boundary
+ */
+ if (GRHydro_enable_internal_excision) {
+
+ #pragma omp parallel for
+ for (int k=GRHydro_stencil-1; k < cctk_lsh[2] - GRHydro_stencil+1+transport_constraints*(1-*zoffset); ++k)
+ for (int j=GRHydro_stencil-1; j < cctk_lsh[1] - GRHydro_stencil+1+transport_constraints*(1-*yoffset); ++j)
+ for (int i=GRHydro_stencil-1; i < cctk_lsh[0] - GRHydro_stencil+1+transport_constraints*(1-*xoffset); ++i) {
+
+ const int ijk = CCTK_GFINDEX3D(cctkGH, i, j, k);
+ const int ijk_m = CCTK_GFINDEX3D(cctkGH, i-*xoffset, j-*yoffset, k-*zoffset);
+ const int ijk_p = CCTK_GFINDEX3D(cctkGH, i+*xoffset, j+*yoffset, k+*zoffset);
+
+ bool excise = false;
+ bool first_order = false;
+ bool extrapolate = false;
+ int extrap_ijk = 0;
+
+ // Whenever we modify the previously reconstructed value,
+ // we need to change the trivial flag!
+ bool change_riemann_trivial_flag = false;
+
+ // for an excised point in the reconstruction stencil radius of the current point, we need to switch down to first order
+ for (int l=-(GRHydro_stencil-1); l < GRHydro_stencil-1; ++l) {
+ const int ijk_l = CCTK_GFINDEX3D(cctkGH, i+*xoffset*l, j+*yoffset*l, k+*zoffset*l);
+ if (hydro_excision_mask[ijk_l]) {
+ first_order = true;
+ break;
+ }
+ }
+
+ // if the current point is excised, then we will mark the Riemann problem as trivial.
+ if (hydro_excision_mask[ijk])
+ excise = true;
+
+ if (!excise && hydro_excision_mask[ijk_m]) {
+ extrapolate = true;
+ extrap_ijk = ijk_m;
+ }
+
+ if (!excise && hydro_excision_mask[ijk_p]) {
+ extrapolate = true;
+ extrap_ijk = ijk_p;
+ }
+
+ if (first_order)
+ {
+ rhominus[ijk] = rho[ijk];
+ rhoplus[ijk] = rho[ijk];
+
+ epsminus[ijk] = eps[ijk];
+ epsplus[ijk] = eps[ijk];
+
+ velxminus[ijk] = velx[ijk];
+ velxplus[ijk] = velx[ijk];
+ velyminus[ijk] = vely[ijk];
+ velyplus[ijk] = vely[ijk];
+ velzminus[ijk] = velz[ijk];
+ velzplus[ijk] = velz[ijk];
+
+ if (do_Ye) {
+ Y_e_plus[ijk] = Y_e[ijk];
+ Y_e_minus[ijk] = Y_e[ijk];
+ }
+ if (do_temp) {
+ tempminus[ijk] = temperature[ijk];
+ tempplus[ijk] = temperature[ijk];
+ }
+ if (do_mhd) {
+ Bvecxminus[ijk] = Bvecx[ijk];
+ Bvecxplus[ijk] = Bvecx[ijk];
+ Bvecyminus[ijk] = Bvecy[ijk];
+ Bvecyplus[ijk] = Bvecy[ijk];
+ Bveczminus[ijk] = Bvecz[ijk];
+ Bveczplus[ijk] = Bvecz[ijk];
+ if (do_clean_divergence) {
+ psidcminus[ijk] = psidc[ijk];
+ psidcplus[ijk] = psidc[ijk];
+ }
+ }
+ if (evolve_tracer) {
+ for (int l=0; l < number_of_tracers; ++l) {
+ tracerminus[ijk + l*N] = tracer[ijk + l*N];
+ tracerplus[ijk + l*N] = tracer[ijk + l*N];
+ }
+ }
+
+ // Riemann problem might not be trivial anymore!
+ change_riemann_trivial_flag = true;
+ }
+
+ if (extrapolate)
+ {
+ rhominus[extrap_ijk] = rho[ijk];
+ rhoplus[extrap_ijk] = rho[ijk];
+
+ epsminus[extrap_ijk] = eps[ijk];
+ epsplus[extrap_ijk] = eps[ijk];
+
+ velxminus[extrap_ijk] = velx[ijk];
+ velxplus[extrap_ijk] = velx[ijk];
+ velyminus[extrap_ijk] = vely[ijk];
+ velyplus[extrap_ijk] = vely[ijk];
+ velzminus[extrap_ijk] = velz[ijk];
+ velzplus[extrap_ijk] = velz[ijk];
+
+ if (do_Ye) {
+ Y_e_plus[extrap_ijk] = Y_e[ijk];
+ Y_e_minus[extrap_ijk] = Y_e[ijk];
+ }
+ if (do_temp) {
+ tempminus[extrap_ijk] = temperature[ijk];
+ tempplus[extrap_ijk] = temperature[ijk];
+ }
+ if (do_mhd) {
+ Bvecxminus[extrap_ijk] = Bvecx[ijk];
+ Bvecxplus[extrap_ijk] = Bvecx[ijk];
+ Bvecyminus[extrap_ijk] = Bvecy[ijk];
+ Bvecyplus[extrap_ijk] = Bvecy[ijk];
+ Bveczminus[extrap_ijk] = Bvecz[ijk];
+ Bveczplus[extrap_ijk] = Bvecz[ijk];
+ if (do_clean_divergence) {
+ psidcminus[extrap_ijk] = psidc[ijk];
+ psidcplus[extrap_ijk] = psidc[ijk];
+ }
+ }
+ if (evolve_tracer) {
+ for (int l=0; l < number_of_tracers; ++l) {
+ tracerminus[extrap_ijk + l*N] = tracer[ijk + l*N];
+ tracerplus[extrap_ijk + l*N] = tracer[ijk + l*N];
+ }
+ }
+
+ // Riemann problem might not be trivial anymore!
+ change_riemann_trivial_flag = true;
+ }
+
+ if (change_riemann_trivial_flag && !excise) {
+ SpaceMask_SetStateBits(space_mask, ijk_m, type_bits, not_trivial);
+ SpaceMask_SetStateBits(space_mask, ijk, type_bits, not_trivial);
+ } else if (excise) {
+ SpaceMask_SetStateBits(space_mask, ijk_m, type_bits, trivial);
+ SpaceMask_SetStateBits(space_mask, ijk, type_bits, trivial);
+ }
+ }
+
+
+ }
+
+
+ /*
+ Here goes the atmosphere treatment!
+ */
+ #pragma omp parallel for
+ for (int k=GRHydro_stencil-1; k < cctk_lsh[2] - GRHydro_stencil+1+transport_constraints*(1-*zoffset); ++k)
+ for (int j=GRHydro_stencil-1; j < cctk_lsh[1] - GRHydro_stencil+1+transport_constraints*(1-*yoffset); ++j)
+ for (int i=GRHydro_stencil-1; i < cctk_lsh[0] - GRHydro_stencil+1+transport_constraints*(1-*xoffset); ++i) {
+ const int ijk = CCTK_GFINDEX3D(cctkGH, i, j, k);
+ const int ijk_m = CCTK_GFINDEX3D(cctkGH, i-*xoffset, j-*yoffset, k-*zoffset);
+
+ // Whenever we modify a previously reconstructed value,
+ // we need to change the trivial flag!
+ bool change_riemann_trivial_flag = false;
+
+ if (rhominus[ijk] < *GRHydro_rho_min || rhoplus[ijk] < *GRHydro_rho_min)
+ {
+ rhominus[ijk] = rho[ijk];
+ rhoplus[ijk] = rho[ijk];
+
+ epsminus[ijk] = eps[ijk];
+ epsplus[ijk] = eps[ijk];
+
+ velxminus[ijk] = velx[ijk];
+ velxplus[ijk] = velx[ijk];
+ velyminus[ijk] = vely[ijk];
+ velyplus[ijk] = vely[ijk];
+ velzminus[ijk] = velz[ijk];
+ velzplus[ijk] = velz[ijk];
+ // TODO: add reconstruct_Wv treatment
+
+ if (do_Ye) {
+ Y_e_plus[ijk] = Y_e[ijk];
+ Y_e_minus[ijk] = Y_e[ijk];
+ }
+ if (do_temp) {
+ tempminus[ijk] = temperature[ijk];
+ tempplus[ijk] = temperature[ijk];
+ }
+ if (do_mhd) {
+ Bvecxminus[ijk] = Bvecx[ijk];
+ Bvecxplus[ijk] = Bvecx[ijk];
+ Bvecyminus[ijk] = Bvecy[ijk];
+ Bvecyplus[ijk] = Bvecy[ijk];
+ Bveczminus[ijk] = Bvecz[ijk];
+ Bveczplus[ijk] = Bvecz[ijk];
+ if (do_clean_divergence) {
+ psidcminus[ijk] = psidc[ijk];
+ psidcplus[ijk] = psidc[ijk];
+ }
+ }
+ if (evolve_tracer) {
+ for (int l=0; l < number_of_tracers; ++l) {
+ if (tracerminus[ijk + l*N] < local_min_tracer || tracerplus[ijk + l*N] < local_min_tracer) {
+ tracerminus[ijk + l*N] = tracer[ijk + l*N];
+ tracerplus[ijk + l*N] = tracer[ijk + l*N];
+ }
+ }
+ }
+
+ change_riemann_trivial_flag = true;
+ }
+
+ if (!do_temp) {
+ if (epsplus[ijk] < 0.0) {
+ epsplus[ijk] = eps[ijk];
+ change_riemann_trivial_flag = true;
+ }
+ if (epsminus[ijk] < 0.0) {
+ epsminus[ijk] = eps[ijk];
+ change_riemann_trivial_flag = true;
+ }
+ }
+
+ if (change_riemann_trivial_flag) {
+ // Riemann problem might not be trivial anymore!
+ SpaceMask_SetStateBits(space_mask, ijk_m, type_bits, not_trivial);
+ SpaceMask_SetStateBits(space_mask, ijk, type_bits, not_trivial);
+ }
+ }
+
+
+ /*
+ Here goes the prim2con call for reconstructed variables!
+ */
+
+ if (CCTK_EQUALS(recon_vars, "primitive") || CCTK_EQUALS(recon_method, "ppm")) {
+ if (do_mhd) {
+ // the alternatives to avoid using internals of Cactus are currently
+ // to move this whole block into schedule.ccl or to construct a struct
+ // cFunction and call CallScheduledFunction
+ int (*wrapper)(void*,void*) = CCTKi_FortranWrapper(CCTK_THORNSTRING);
+ wrapper(cctkGH, (void*)CCTK_FNAME(primitive2conservativeM));
+ } else {
+ Primitive2ConservativeC(CCTK_PASS_CTOC);
+ }
+ } else if (CCTK_EQUALS(recon_vars,"conservative")) {
+ CCTK_ERROR("Conservative reconstruction currently not supported!");
+ } else
+ CCTK_ERROR("Variable type to reconstruct not recognized.");
+
+
+}
+