asc26 amss-ncku initialized
This commit is contained in:
604
AMSS_NCKU_source/ghost_zone.C
Normal file
604
AMSS_NCKU_source/ghost_zone.C
Normal file
@@ -0,0 +1,604 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "cctk.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "stdc.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "array.h"
|
||||
#include "cpm_map.h"
|
||||
#include "linear_map.h"
|
||||
|
||||
#include "coords.h"
|
||||
#include "tgrid.h"
|
||||
#include "fd_grid.h"
|
||||
#include "patch.h"
|
||||
#include "patch_edge.h"
|
||||
#include "patch_interp.h"
|
||||
#include "ghost_zone.h"
|
||||
|
||||
namespace AHFinderDirect
|
||||
{
|
||||
using jtutil::error_exit;
|
||||
|
||||
//******************************************************************************
|
||||
//******************************************************************************
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// These functions verify (assert()) that a ghost zone is indeed of
|
||||
// the specified type, then static_cast to the appropriate derived class.
|
||||
//
|
||||
|
||||
const symmetry_ghost_zone &ghost_zone::cast_to_symmetry_ghost_zone()
|
||||
const
|
||||
{
|
||||
assert(is_symmetry());
|
||||
return static_cast<const symmetry_ghost_zone &>(*this);
|
||||
}
|
||||
|
||||
symmetry_ghost_zone &ghost_zone::cast_to_symmetry_ghost_zone()
|
||||
{
|
||||
assert(is_symmetry());
|
||||
return static_cast<symmetry_ghost_zone &>(*this);
|
||||
}
|
||||
|
||||
//**************************************
|
||||
|
||||
const interpatch_ghost_zone &ghost_zone::cast_to_interpatch_ghost_zone()
|
||||
const
|
||||
{
|
||||
assert(is_interpatch());
|
||||
return static_cast<const interpatch_ghost_zone &>(*this);
|
||||
}
|
||||
|
||||
interpatch_ghost_zone &ghost_zone::cast_to_interpatch_ghost_zone()
|
||||
{
|
||||
assert(is_interpatch());
|
||||
return static_cast<interpatch_ghost_zone &>(*this);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
//******************************************************************************
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// This function constructs a mirror-symmetry ghost zone object
|
||||
//
|
||||
symmetry_ghost_zone::symmetry_ghost_zone(const patch_edge &my_edge_in)
|
||||
: ghost_zone(my_edge_in,
|
||||
my_edge_in, // other edge == my edge
|
||||
ghost_zone_is_symmetry)
|
||||
{
|
||||
// iperp_map: i --> (i of ghost zone) - i
|
||||
iperp_map_ = new jtutil::cpm_map<fp>(min_iperp(), max_iperp(),
|
||||
my_edge_in.fp_grid_outer_iperp());
|
||||
|
||||
// ipar_map_: identity map
|
||||
ipar_map_ = new jtutil::cpm_map<fp>(extreme_min_ipar(), extreme_max_ipar());
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// This function constructs a periodic-symmetry ghost zone object.
|
||||
//
|
||||
symmetry_ghost_zone::symmetry_ghost_zone(const patch_edge &my_edge_in, const patch_edge &other_edge_in,
|
||||
int my_edge_sample_ipar, int other_edge_sample_ipar,
|
||||
bool ipar_map_is_plus)
|
||||
: ghost_zone(my_edge_in,
|
||||
other_edge_in,
|
||||
ghost_zone_is_symmetry)
|
||||
{
|
||||
//
|
||||
// perpendicular map
|
||||
//
|
||||
const fp fp_my_period_plane_iperp = my_edge().fp_grid_outer_iperp();
|
||||
const fp fp_other_period_plane_iperp = other_edge().fp_grid_outer_iperp();
|
||||
|
||||
// iperp mapping must be outside --> inside
|
||||
// i.e. if both edges have iperp as the same min/max "direction",
|
||||
// then the mapping is iperp increasing --> iperp decreasing
|
||||
// (i.e. the map's sign is -1)
|
||||
const bool is_iperp_map_plus = !(my_edge().is_min() == other_edge().is_min());
|
||||
iperp_map_ = new jtutil::cpm_map<fp>(min_iperp(), max_iperp(),
|
||||
fp_my_period_plane_iperp,
|
||||
fp_other_period_plane_iperp,
|
||||
is_iperp_map_plus);
|
||||
|
||||
//
|
||||
// parallel map
|
||||
//
|
||||
ipar_map_ = new jtutil::cpm_map<fp>(extreme_min_ipar(), extreme_max_ipar(),
|
||||
my_edge_sample_ipar, other_edge_sample_ipar,
|
||||
ipar_map_is_plus);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// This function destroys a symmetry_ghost_zone object.
|
||||
//
|
||||
symmetry_ghost_zone::~symmetry_ghost_zone()
|
||||
{
|
||||
delete ipar_map_;
|
||||
delete iperp_map_;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// This function "synchronizes" a ghost zone, i.e. it updates the
|
||||
// ghost-zone values of the specified gridfns via the appropriate
|
||||
// symmetry operations.The flags specify which part(s) of the ghost zone
|
||||
// we want.
|
||||
//
|
||||
void symmetry_ghost_zone::synchronize(int ghosted_min_gfn, int ghosted_max_gfn,
|
||||
bool want_corners /* = true */,
|
||||
bool want_noncorner /* = true */)
|
||||
{
|
||||
// printf("*Sync sym ghost zone in %s patch\n", my_patch().name());
|
||||
|
||||
for (int gfn = ghosted_min_gfn; gfn <= ghosted_max_gfn; ++gfn)
|
||||
{
|
||||
for (int iperp = min_iperp(); iperp <= max_iperp(); ++iperp)
|
||||
{
|
||||
for (int ipar = min_ipar(iperp); ipar <= max_ipar(iperp); ++ipar)
|
||||
{
|
||||
// do we want to do this point?
|
||||
if (!my_edge().ipar_is_in_selected_part(want_corners, want_noncorner,
|
||||
ipar))
|
||||
then continue; // *** LOOP CONTROL ***
|
||||
|
||||
const int sym_iperp = iperp_map_of_iperp(iperp);
|
||||
const int sym_ipar = ipar_map_of_ipar(ipar);
|
||||
const int sym_irho = other_edge()
|
||||
.irho_of_iperp_ipar(sym_iperp, sym_ipar);
|
||||
const int sym_isigma = other_edge()
|
||||
.isigma_of_iperp_ipar(sym_iperp, sym_ipar);
|
||||
const fp sym_gridfn = other_patch()
|
||||
.ghosted_gridfn(gfn, sym_irho, sym_isigma);
|
||||
|
||||
const int irho = my_edge().irho_of_iperp_ipar(iperp, ipar);
|
||||
const int isigma = my_edge().isigma_of_iperp_ipar(iperp, ipar);
|
||||
my_patch().ghosted_gridfn(gfn, irho, isigma) = sym_gridfn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
//******************************************************************************
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// This function constructs an interpatch_ghost_zone object.
|
||||
//
|
||||
interpatch_ghost_zone::interpatch_ghost_zone(const patch_edge &my_edge_in,
|
||||
const patch_edge &other_edge_in,
|
||||
int patch_overlap_width)
|
||||
: ghost_zone(my_edge_in,
|
||||
other_edge_in,
|
||||
ghost_zone_is_interpatch),
|
||||
// remaining pointers are all set up properly by finish_setup()
|
||||
other_patch_interp_(NULL),
|
||||
other_iperp_(NULL),
|
||||
min_ipar_used_(NULL), max_ipar_used_(NULL),
|
||||
other_par_(NULL),
|
||||
interp_result_buffer_(NULL),
|
||||
Jacobian_y_ipar_posn_(NULL), Jacobian_buffer_(NULL) // no comma
|
||||
{
|
||||
//
|
||||
// verify that we have the expected relationships between
|
||||
// this and the other patch's (mu,nu,phi) coordinates:
|
||||
//
|
||||
|
||||
// perp coordinate is common to us and the other patch, so
|
||||
// ghost zone must be min in one patch, max in the other
|
||||
if (my_edge().is_min() == other_edge().is_min())
|
||||
then error_exit(ERROR_EXIT,
|
||||
"***** interpatch_ghost_zone::interpatch_ghost_zone:\n"
|
||||
" my_patch().name()=\"%s\" my_edge().name()=%s\n"
|
||||
" other_patch().name()=\"%s\" other_edge().name()=%s\n"
|
||||
" ghost zone must be min in one patch, max in the other!\n",
|
||||
my_patch().name(), my_edge().name(),
|
||||
other_patch().name(), other_edge().name()); /*NOTREACHED*/
|
||||
|
||||
// coord in common between the two patches must be perp coord in both patches
|
||||
// and this patch's tau coordinate must be other edge's parallel coordinate
|
||||
const local_coords::coords_set common_coords_set = local_coords::coords_set_not(my_patch().coords_set_rho_sigma() ^
|
||||
other_patch().coords_set_rho_sigma());
|
||||
if (!((common_coords_set == my_edge().coords_set_perp()) && (common_coords_set == other_edge().coords_set_perp()) && (my_patch().coords_set_tau() == other_edge().coords_set_par())))
|
||||
then error_exit(PANIC_EXIT,
|
||||
"***** interpatch_ghost_zone::interpatch_ghost_zone:\n"
|
||||
" (rho,sigma,tau) coordinates don't match up properly\n"
|
||||
" between this patch/edge and the other patch/edge!\n"
|
||||
" my_patch().name()=\"%s\" my_edge().name()=%s\n"
|
||||
" other_patch().name()=\"%s\" other_edge().name()=%s\n"
|
||||
" my_patch().coords_set_{rho,sigma,tau}={%s,%s,%s}\n"
|
||||
" my_edge().coords_set_{perp,par}={%s,%s}\n"
|
||||
" other_patch().coords_set_{rho,sigma,tau}={%s,%s,%s}\n"
|
||||
" other_edge().coords_set_{perp,par}={%s,%s}\n",
|
||||
my_patch().name(), my_edge().name(),
|
||||
other_patch().name(), other_edge().name(),
|
||||
local_coords::name_of_coords_set(my_patch().coords_set_rho()),
|
||||
local_coords::name_of_coords_set(my_patch().coords_set_sigma()),
|
||||
local_coords::name_of_coords_set(my_patch().coords_set_tau()),
|
||||
local_coords::name_of_coords_set(my_edge().coords_set_perp()),
|
||||
local_coords::name_of_coords_set(my_edge().coords_set_par()),
|
||||
local_coords::name_of_coords_set(other_patch().coords_set_rho()),
|
||||
local_coords::name_of_coords_set(other_patch().coords_set_sigma()),
|
||||
local_coords::name_of_coords_set(other_patch().coords_set_tau()),
|
||||
local_coords::name_of_coords_set(other_edge().coords_set_perp()),
|
||||
local_coords::name_of_coords_set(other_edge().coords_set_par()));
|
||||
/*NOTREACHED*/
|
||||
|
||||
// perp coordinate must match (mod 2*pi) across the two patches
|
||||
// after taking into account any overlap
|
||||
// ... eg patch_overlap_width = 3 would be
|
||||
// p p p p p
|
||||
// q q q q q
|
||||
// so the overlap would be (patch_overlap_width-1) * delta
|
||||
const fp other_overlap = (patch_overlap_width - 1) * other_edge().perp_map().delta_fp();
|
||||
const fp other_outer_perp_minus_overlap // move back inwards into other patch
|
||||
// by overlap distance, to get a value
|
||||
// that should match our own
|
||||
// grid_outer_perp() value
|
||||
= other_edge().grid_outer_perp() + (other_edge().is_min() ? +other_overlap : -other_overlap);
|
||||
if (!local_coords::fuzzy_EQ_ang(my_edge().grid_outer_perp(),
|
||||
other_outer_perp_minus_overlap))
|
||||
then error_exit(ERROR_EXIT,
|
||||
"***** interpatch_ghost_zone::interpatch_ghost_zone:\n"
|
||||
" my_patch().name()=\"%s\" my_edge().name()=%s\n"
|
||||
" other_patch().name()=\"%s\" other_edge().name()=%s\n"
|
||||
" perp coordinate doesn't match (mod 2*pi) across the two patches!\n"
|
||||
" my_edge().grid_outer_perp()=%g <--(compare this)\n"
|
||||
" patch_overlap_width=%d other_overlap=%g\n"
|
||||
" other_edge.grid_outer_perp()=%g\n"
|
||||
" other_outer_perp_minus_overlap=%g <--(against this)\n",
|
||||
my_patch().name(), my_edge().name(),
|
||||
other_patch().name(), other_edge().name(),
|
||||
double(my_edge().grid_outer_perp()),
|
||||
patch_overlap_width, double(other_overlap),
|
||||
double(other_edge().grid_outer_perp()),
|
||||
double(other_outer_perp_minus_overlap)); /*NOTREACHED*/
|
||||
|
||||
//
|
||||
// set up the iperp interpatch coordinate mapping
|
||||
// (gives other patch's iperp coordinate for interpolation)
|
||||
//
|
||||
|
||||
// compute the iperp --> other_iperp mapping for a sample point;
|
||||
// ... if the ghost zone is empty, then the sample point will necessarily
|
||||
// be out-of-range in the ghost zone, so we use the *unchecked*
|
||||
// conversions to avoid errors in this case
|
||||
// ... we do the computation using the fact that perp is the same
|
||||
// coordinate in both patches (modulo 2*pi radians = 360 degrees)
|
||||
const int sample_iperp = outer_iperp();
|
||||
const fp sample_perp = my_edge().perp_map().fp_of_int_unchecked(sample_iperp);
|
||||
// unchecked conversion here!
|
||||
const fp other_sample_perp = other_patch()
|
||||
.modulo_reduce_ang(other_edge().perp_is_rho(),
|
||||
sample_perp);
|
||||
const fp fp_other_sample_iperp = other_edge()
|
||||
.fp_iperp_of_perp(other_sample_perp);
|
||||
|
||||
// verify that this is fuzzily a grid point
|
||||
if (!jtutil::fuzzy<fp>::is_integer(fp_other_sample_iperp))
|
||||
then error_exit(ERROR_EXIT,
|
||||
"***** interpatch_ghost_zone::interpatch_ghost_zone:\n"
|
||||
" my_patch().name()=\"%s\" my_edge().name()=%s\n"
|
||||
" other_patch().name()=\"%s\" other_edge().name()=%s\n"
|
||||
" sample_iperp=%d sample_perp=%g\n"
|
||||
" other_sample_perp=%g fp_other_sample_iperp=%g\n"
|
||||
" ==> fp_other_sample_iperp isn't fuzzily an integer!\n"
|
||||
" ==> patches aren't commensurate in the perpendicular coordinate!\n",
|
||||
my_patch().name(), my_edge().name(),
|
||||
other_patch().name(), other_edge().name(),
|
||||
sample_iperp, double(sample_perp),
|
||||
double(other_sample_perp),
|
||||
double(fp_other_sample_iperp)); /*NOTREACHED*/
|
||||
const int other_sample_iperp = jtutil::round<fp>::to_integer(fp_other_sample_iperp);
|
||||
|
||||
// compute the +/- sign (direction) of the iperp --> other_iperp mapping
|
||||
//
|
||||
// Since perp is the same in both patches (mod 2*pi radians = 360 degrees),
|
||||
// the overall +/- sign is just the product of the signs of the two individual
|
||||
// iperp <--> perp mappings.
|
||||
//
|
||||
// ... signs encoded as (floating-point) +/- 1.0
|
||||
const double iperp_map_sign_pm1 = jtutil::signum(my_edge().perp_map().delta_fp()) * jtutil::signum(other_edge().perp_map().delta_fp());
|
||||
// ... signs encoded as is_plus bool flag
|
||||
const bool is_iperp_map_plus = (iperp_map_sign_pm1 > 0.0);
|
||||
|
||||
// now we finally know enough to set up the other_iperp(iperp)
|
||||
// coordinate mapping
|
||||
other_iperp_ = new jtutil::cpm_map<fp>(min_iperp(), max_iperp(),
|
||||
sample_iperp, other_sample_iperp,
|
||||
is_iperp_map_plus);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// this function destroys an interpatch_ghost_zone object.
|
||||
//
|
||||
interpatch_ghost_zone::~interpatch_ghost_zone()
|
||||
{
|
||||
delete Jacobian_buffer_;
|
||||
delete Jacobian_y_ipar_posn_;
|
||||
delete interp_result_buffer_;
|
||||
delete other_par_;
|
||||
delete max_ipar_used_;
|
||||
delete min_ipar_used_;
|
||||
delete other_iperp_;
|
||||
delete other_patch_interp_;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// These functions compute the [min,max] ipar of the ghost zone for
|
||||
// a given iperp, taking into account how we treat the corners
|
||||
// (cf. the example in the header comments in "ghost_zone.hh"):
|
||||
//
|
||||
// If an adjacent ghost zone is symmetry,
|
||||
// we do not include that corner;
|
||||
// If an adjacent ghost zone is interpatch,
|
||||
// we include up to the diagonal line, and if we are a rho ghost zone,
|
||||
// then also the diagonal line itself. E.g. For the example in the
|
||||
// header comments "ghost_zone.hh", the +x ghost zone includes (6,6),
|
||||
// (7,6), and (7,7), while the +y ghost zone includes (6,7)
|
||||
//
|
||||
// ... in the following 2 functions,
|
||||
// the iabs() term includes the diagonal,
|
||||
// so we must remove the diagonal for !is_rho,
|
||||
// i.e. add 1 to min_ipar and subtract 1 from max_ipar
|
||||
//
|
||||
int interpatch_ghost_zone::min_ipar(int iperp) const
|
||||
{
|
||||
return min_par_adjacent_ghost_zone().is_symmetry()
|
||||
? my_edge().min_ipar_without_corners()
|
||||
: my_edge().min_ipar_without_corners() - iabs(iperp - my_edge().nominal_grid_outer_iperp()) + (is_rho() ? 0 : 1);
|
||||
}
|
||||
|
||||
int interpatch_ghost_zone::max_ipar(int iperp) const
|
||||
{
|
||||
return max_par_adjacent_ghost_zone().is_symmetry()
|
||||
? my_edge().max_ipar_without_corners()
|
||||
: my_edge().max_ipar_without_corners() + iabs(iperp - my_edge().nominal_grid_outer_iperp()) - (is_rho() ? 0 : 1);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// This function finishes the construction/setup of an interpatch_ghost_zone
|
||||
// object. It
|
||||
// - sets up the par coordinate mapping information
|
||||
// - sets up the interpatch interpolator data pointer and result arrays
|
||||
// - constructs the patch_interp object to interpolate from the *other* patch
|
||||
//
|
||||
// We use our ipar as the patch_interp's parindex.
|
||||
//
|
||||
void interpatch_ghost_zone::finish_setup(int interp_handle,
|
||||
int interp_par_table_handle)
|
||||
{
|
||||
min_other_iperp_ = min(other_iperp(min_iperp()),
|
||||
other_iperp(max_iperp()));
|
||||
max_other_iperp_ = max(other_iperp(min_iperp()),
|
||||
other_iperp(max_iperp()));
|
||||
|
||||
//
|
||||
// set up arrays giving actual [min,max] ipar that we'll use
|
||||
// at each other_iperp (later on we will pass these arrays to the
|
||||
// other patch's patch_interp object, with ipar being parindex there
|
||||
//
|
||||
min_ipar_used_ = new jtutil::array1d<int>(min_other_iperp_, max_other_iperp_);
|
||||
max_ipar_used_ = new jtutil::array1d<int>(min_other_iperp_, max_other_iperp_);
|
||||
{
|
||||
for (int iperp = min_iperp(); iperp <= max_iperp(); ++iperp)
|
||||
{
|
||||
(*min_ipar_used_)(other_iperp(iperp)) = min_ipar(iperp);
|
||||
(*max_ipar_used_)(other_iperp(iperp)) = max_ipar(iperp);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// set up array giving other patch's par coordinate for interpolation
|
||||
//
|
||||
|
||||
other_par_ = new jtutil::array2d<fp>(min_other_iperp_, max_other_iperp_,
|
||||
extreme_min_ipar(), extreme_max_ipar());
|
||||
|
||||
{
|
||||
for (int iperp = min_iperp(); iperp <= max_iperp(); ++iperp)
|
||||
{
|
||||
for (int ipar = min_ipar(iperp); ipar <= max_ipar(iperp); ++ipar)
|
||||
{
|
||||
// compute the other_par corresponding to (iperp,ipar)
|
||||
// ... here we use the fact (which we verified in our constructor)
|
||||
// that other edge's parallel coordinate == our tau coordinate
|
||||
// (at least modulo 2*pi radians = 360 degrees)
|
||||
const fp perp = my_edge().perp_of_iperp(iperp);
|
||||
const fp par = my_edge().par_of_ipar(ipar);
|
||||
|
||||
const fp rho = my_edge().rho_of_perp_par(perp, par);
|
||||
const fp sigma = my_edge().sigma_of_perp_par(perp, par);
|
||||
|
||||
const fp tau = my_patch().tau_of_rho_sigma(rho, sigma);
|
||||
const fp other_par = other_patch()
|
||||
.modulo_reduce_ang(other_edge().par_is_rho(), tau);
|
||||
|
||||
(*other_par_)(other_iperp(iperp), ipar) = other_par;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// set up interpolation result buffer
|
||||
//
|
||||
interp_result_buffer_ = new jtutil::array3d<fp>(my_patch().ghosted_min_gfn(),
|
||||
my_patch().ghosted_max_gfn(),
|
||||
min_other_iperp_, max_other_iperp_,
|
||||
extreme_min_ipar(), extreme_max_ipar());
|
||||
|
||||
//
|
||||
// construct the patch_interp object to interpolate from the *other* patch
|
||||
// ... the patch_interp should use gridfn data from it's (the other patch's)
|
||||
// min/max par ghost zones if those (adjacent) adjacent ghost zones
|
||||
// are symmetry, but not if they're interpatch,
|
||||
// cf the header comments in "ghost_zone.hh"
|
||||
//
|
||||
const ghost_zone &other_ghost_zone = other_patch()
|
||||
.ghost_zone_on_edge(other_edge());
|
||||
const bool ok_to_use_min_par_ghost_zone = other_ghost_zone.min_par_adjacent_ghost_zone()
|
||||
.is_symmetry()
|
||||
? true
|
||||
: false;
|
||||
const bool ok_to_use_max_par_ghost_zone = other_ghost_zone.max_par_adjacent_ghost_zone()
|
||||
.is_symmetry()
|
||||
? true
|
||||
: false;
|
||||
other_patch_interp_ = new patch_interp(other_edge(),
|
||||
min_other_iperp_, max_other_iperp_,
|
||||
*min_ipar_used_, *max_ipar_used_,
|
||||
*other_par_,
|
||||
ok_to_use_min_par_ghost_zone,
|
||||
ok_to_use_max_par_ghost_zone,
|
||||
interp_handle, interp_par_table_handle);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// This function asserts() that
|
||||
// - we have a patch_interp object
|
||||
// - our and the patch_interp object's notions of the "other patch" agree
|
||||
// - the other patch has an interpatch ghost zone on this edge
|
||||
// - the other patch's interpatch ghost zone on this edge,
|
||||
// points back to our patch
|
||||
//
|
||||
void interpatch_ghost_zone::assert_fully_setup() const
|
||||
{
|
||||
assert(other_patch_interp_ != NULL);
|
||||
assert(other_patch() == other_patch_interp_->my_patch());
|
||||
assert(other_patch()
|
||||
.ghost_zone_on_edge(other_edge())
|
||||
.is_interpatch());
|
||||
assert(my_patch() == other_patch()
|
||||
.ghost_zone_on_edge(other_edge())
|
||||
.other_patch());
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// This function "synchronizes" a ghost zone, i.e. it updates the
|
||||
// ghost-zone values of the specified gridfns via the appropriate
|
||||
// interpatch interpolations.
|
||||
//
|
||||
// The flags specify which part(s) of the ghost zone we want, but
|
||||
// the present implementation only supports the case where all the
|
||||
// flags are true , i.e. we want the entire ghost zone.
|
||||
//
|
||||
void interpatch_ghost_zone::synchronize(int ghosted_min_gfn, int ghosted_max_gfn,
|
||||
bool want_corners /* = true */,
|
||||
bool want_noncorner /* = true */)
|
||||
{
|
||||
#ifdef DEBUG_AHFD
|
||||
printf("*Sync interpatch ghost zone in %s\n", my_patch().name());
|
||||
#endif
|
||||
|
||||
// make sure the caller wants the entire ghost zone
|
||||
if (!(want_corners && want_noncorner))
|
||||
then error_exit(ERROR_EXIT,
|
||||
"***** interpatch_ghost_zone::synchronize():\n"
|
||||
" we only support operating on the *entire* ghost zone,\n"
|
||||
" but we were passed flags specifying a proper subset!\n"
|
||||
" want_corners=(int)%d want_noncorner=(int)%d\n",
|
||||
want_corners, want_noncorner); /*NOTREACHED*/
|
||||
|
||||
//
|
||||
// move from 'Compute_Jacobian' below
|
||||
//
|
||||
assert(other_patch_interp_ != NULL);
|
||||
other_patch_interp_->molecule_minmax_ipar_m(Jacobian_min_y_ipar_m_,
|
||||
Jacobian_max_y_ipar_m_);
|
||||
#ifdef DEBUG_AHFD
|
||||
printf("%d %d %d %d %d %d \n", Jacobian_min_y_ipar_m_, Jacobian_max_y_ipar_m_,
|
||||
min_other_iperp_, max_other_iperp_, extreme_min_ipar(), extreme_max_ipar());
|
||||
getchar();
|
||||
#endif
|
||||
|
||||
// /*
|
||||
if (Jacobian_y_ipar_posn_ == NULL)
|
||||
Jacobian_y_ipar_posn_ = new jtutil::array2d<CCTK_INT>(min_other_iperp_, max_other_iperp_,
|
||||
extreme_min_ipar(), extreme_max_ipar());
|
||||
if (Jacobian_buffer_ == NULL)
|
||||
Jacobian_buffer_ = new jtutil::array3d<fp>(min_other_iperp_, max_other_iperp_,
|
||||
extreme_min_ipar(), extreme_max_ipar(),
|
||||
Jacobian_min_y_ipar_m_, Jacobian_max_y_ipar_m_);
|
||||
|
||||
// do the interpolation into our result buffer
|
||||
other_patch_interp_->interpolate(ghosted_min_gfn, ghosted_max_gfn,
|
||||
*interp_result_buffer_, //);
|
||||
*Jacobian_y_ipar_posn_,
|
||||
*Jacobian_buffer_);
|
||||
|
||||
// other_patch_interp_->molecule_posn(*Jacobian_y_ipar_posn_);
|
||||
|
||||
// store the results back into our gridfns
|
||||
for (int gfn = ghosted_min_gfn; gfn <= ghosted_max_gfn; ++gfn)
|
||||
{
|
||||
for (int iperp = min_iperp(); iperp <= max_iperp(); ++iperp)
|
||||
{
|
||||
const int oiperp = other_iperp(iperp);
|
||||
|
||||
for (int ipar = min_ipar(iperp); ipar <= max_ipar(iperp); ++ipar)
|
||||
{
|
||||
int irho = my_edge().irho_of_iperp_ipar(iperp, ipar);
|
||||
int isigma = my_edge().isigma_of_iperp_ipar(iperp, ipar);
|
||||
my_patch().ghosted_gridfn(gfn, irho, isigma) = (*interp_result_buffer_)(gfn, oiperp, ipar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
||||
//
|
||||
// This function allocates the internal buffers for the Jacobian, and
|
||||
// computes that Jacobian
|
||||
// partial synchronize gridfn(ghosted_gfn, iperp, ipar)
|
||||
// ------------------------------------------------------------
|
||||
// partial other patch gridfn(ghosted_gfn, oiperp, posn+ipar_m)
|
||||
// where
|
||||
// oiperp = Jacobian_oiperp(iperp)
|
||||
// posn = Jacobian_oipar_posn(iperp, ipar)
|
||||
// into the internal buffers.
|
||||
//
|
||||
void interpatch_ghost_zone::compute_Jacobian(int ghosted_min_gfn, int ghosted_max_gfn,
|
||||
bool want_corners /* = true */,
|
||||
bool want_noncorner /* = true */)
|
||||
const
|
||||
{
|
||||
// make sure the caller wants the entire ghost zone
|
||||
if (!(want_corners && want_noncorner))
|
||||
then error_exit(ERROR_EXIT,
|
||||
"***** interpatch_ghost_zone::compute_Jacobian():\n"
|
||||
" we only support operating on the *entire* ghost zone,\n"
|
||||
" but we were passed flags specifying a proper subset!\n"
|
||||
" want_corners=(int)%d want_noncorner=(int)%d\n",
|
||||
want_corners, want_noncorner); /*NOTREACHED*/
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
//******************************************************************************
|
||||
//******************************************************************************
|
||||
|
||||
} // namespace AHFinderDirect
|
||||
Reference in New Issue
Block a user