1708 lines
51 KiB
C
1708 lines
51 KiB
C
|
|
#ifdef newc
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <fstream>
|
|
#include <cstdlib>
|
|
#include <cstdio>
|
|
#include <string>
|
|
#include <cmath>
|
|
#include <map>
|
|
using namespace std;
|
|
#else
|
|
#include <iostream.h>
|
|
#include <iomanip.h>
|
|
#include <fstream.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <map.h>
|
|
#endif
|
|
|
|
#include <mpi.h>
|
|
|
|
#include "macrodef.h"
|
|
#include "misc.h"
|
|
#include "cgh.h"
|
|
#include "Parallel.h"
|
|
#include "parameters.h"
|
|
|
|
//================================================================================================
|
|
|
|
// define cgh class
|
|
|
|
//================================================================================================
|
|
|
|
cgh::cgh(int ingfsi, int fngfsi, int Symmetry, char *filename, int checkrun,
|
|
monitor *ErrorMonitor) : ingfs(ingfsi), fngfs(fngfsi), trfls(0)
|
|
{
|
|
#if (PSTR == 1 || PSTR == 2 || PSTR == 3)
|
|
Commlev = 0;
|
|
start_rank = 0;
|
|
end_rank = 0;
|
|
#endif
|
|
|
|
if (!checkrun)
|
|
{
|
|
read_bbox(Symmetry, filename);
|
|
sethandle(ErrorMonitor);
|
|
for (int lev = 0; lev < levels; lev++)
|
|
PatL[lev] = construct_patchlist(lev, Symmetry);
|
|
}
|
|
}
|
|
|
|
//================================================================================================
|
|
|
|
|
|
|
|
//================================================================================================
|
|
|
|
// This member function is the destructor; it releases allocated resources and deletes variables
|
|
|
|
//================================================================================================
|
|
|
|
cgh::~cgh()
|
|
{
|
|
for (int lev = 0; lev < levels; lev++)
|
|
{
|
|
for (int grd = 0; grd < grids[lev]; grd++)
|
|
{
|
|
delete[] bbox[lev][grd];
|
|
delete[] shape[lev][grd];
|
|
delete[] handle[lev][grd];
|
|
}
|
|
delete[] bbox[lev];
|
|
delete[] shape[lev];
|
|
delete[] handle[lev];
|
|
Parallel::KillBlocks(PatL[lev]);
|
|
PatL[lev]->destroyList();
|
|
#if (RPB == 1)
|
|
Parallel::destroypsuList_bam(bdsul[lev]);
|
|
Parallel::destroypsuList_bam(rsul[lev]);
|
|
#endif
|
|
}
|
|
delete[] grids;
|
|
delete[] Lt;
|
|
delete[] bbox;
|
|
delete[] shape;
|
|
delete[] handle;
|
|
delete[] PatL;
|
|
#if (RPB == 1)
|
|
delete[] bdsul;
|
|
delete[] rsul;
|
|
#endif
|
|
|
|
#if (PSTR == 1 || PSTR == 2 || PSTR == 3)
|
|
for (int lev = 0; lev < levels; lev++)
|
|
{
|
|
MPI_Comm_free(&Commlev[lev]);
|
|
}
|
|
|
|
if (Commlev)
|
|
delete[] Commlev;
|
|
if (start_rank)
|
|
delete[] start_rank;
|
|
if (end_rank)
|
|
delete[] end_rank;
|
|
#endif
|
|
for (int lev = 0; lev < levels; lev++)
|
|
{
|
|
for (int ibh = 0; ibh < BH_num_in; ibh++)
|
|
delete[] Porgls[lev][ibh];
|
|
delete[] Porgls[lev];
|
|
}
|
|
delete[] Porgls;
|
|
}
|
|
|
|
//================================================================================================
|
|
|
|
|
|
//================================================================================================
|
|
|
|
// This member function constructs the computational grid
|
|
|
|
//================================================================================================
|
|
|
|
#if (PSTR == 0)
|
|
void cgh::compose_cgh(int nprocs)
|
|
{
|
|
for (int lev = 0; lev < levels; lev++)
|
|
{
|
|
checkPatchList(PatL[lev], false);
|
|
Parallel::distribute(PatL[lev], nprocs, ingfs, fngfs, false);
|
|
#if (RPB == 1)
|
|
// we need distributed box of PatL[lev] and PatL[lev-1]
|
|
if (lev > 0)
|
|
{
|
|
Parallel::Constr_pointstr_OutBdLow2Hi(PatL[lev], PatL[lev - 1], bdsul[lev]);
|
|
Parallel::Constr_pointstr_Restrict(PatL[lev], PatL[lev - 1], rsul[lev]);
|
|
}
|
|
else
|
|
{
|
|
bdsul[lev] = 0;
|
|
rsul[lev] = 0;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//================================================================================================
|
|
|
|
|
|
//================================================================================================
|
|
|
|
// This member function constructs the computational grid
|
|
// For the cases PSTR == 1 and PSTR == 2
|
|
|
|
//================================================================================================
|
|
|
|
#elif (PSTR == 1 || PSTR == 2)
|
|
void cgh::compose_cgh(int nprocs)
|
|
{
|
|
Commlev = new MPI_Comm[levels];
|
|
construct_mylev(nprocs);
|
|
for (int lev = 0; lev < levels; lev++)
|
|
{
|
|
MPI_Comm_split(MPI_COMM_WORLD, mylev, lev, &Commlev[lev]);
|
|
checkPatchList(PatL[lev], false);
|
|
Parallel::distribute(PatL[lev], end_rank[lev] - start_rank[lev] + 1, ingfs, fngfs, false, start_rank[lev], end_rank[lev]);
|
|
#if (RPB == 1)
|
|
#error "not support yet"
|
|
#endif
|
|
}
|
|
/* note different comm field has its own rank index
|
|
int myrank;
|
|
MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
|
|
if(myrank==nprocs-1)
|
|
{
|
|
cout<<"myrank = "<<myrank<<", mylev = "<<mylev<<endl;
|
|
MPI_Comm_rank(Commlev[levels-1],&myrank);
|
|
cout<<myrank<<" :)"<<endl;
|
|
}
|
|
*/
|
|
}
|
|
|
|
//================================================================================================
|
|
|
|
#if (PSTR == 1)
|
|
void cgh::construct_mylev(int nprocs)
|
|
{
|
|
if (nprocs < levels)
|
|
{
|
|
cout << "Too few procs to use parallel level methods!" << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
|
|
start_rank = new int[levels];
|
|
end_rank = new int[levels];
|
|
|
|
int myrank;
|
|
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
|
|
|
|
int mp;
|
|
mp = nprocs / levels;
|
|
|
|
start_rank[0] = 0;
|
|
end_rank[0] = mp - 1;
|
|
for (int lev = 1; lev < levels - 1; lev++)
|
|
{
|
|
start_rank[lev] = end_rank[lev - 1] + 1;
|
|
end_rank[lev] = end_rank[lev - 1] + mp;
|
|
}
|
|
start_rank[levels - 1] = end_rank[levels - 2] + 1;
|
|
end_rank[levels - 1] = nprocs - 1;
|
|
|
|
for (int lev = 0; lev < levels; lev++)
|
|
{
|
|
if (myrank >= start_rank[lev] && myrank <= end_rank[lev])
|
|
mylev = lev;
|
|
}
|
|
}
|
|
#elif (PSTR == 2)
|
|
void cgh::construct_mylev(int nprocs)
|
|
{
|
|
if (nprocs < levels)
|
|
{
|
|
cout << "Too few procs to use parallel level methods!" << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
|
|
start_rank = new int[levels];
|
|
end_rank = new int[levels];
|
|
|
|
int myrank;
|
|
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
|
|
|
|
int mp;
|
|
mp = nprocs / levels;
|
|
|
|
start_rank[levels - 1] = 0;
|
|
end_rank[levels - 1] = mp - 1;
|
|
for (int lev = levels - 2; lev > 0; lev--)
|
|
{
|
|
start_rank[lev] = end_rank[lev - 1] + 1;
|
|
end_rank[lev] = end_rank[lev - 1] + mp;
|
|
}
|
|
start_rank[0] = end_rank[1] + 1;
|
|
end_rank[0] = nprocs - 1;
|
|
|
|
for (int lev = levels - 1; lev >= 0; lev--)
|
|
{
|
|
if (myrank >= start_rank[lev] && myrank <= end_rank[lev])
|
|
mylev = lev;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#elif (PSTR == 3)
|
|
void cgh::construct_mylev(int nprocs)
|
|
{
|
|
if (nprocs <= 1)
|
|
{
|
|
cout << " cgh::construct_mylev requires at least 2 procs" << endl;
|
|
exit(0);
|
|
}
|
|
|
|
start_rank = new int[2];
|
|
end_rank = new int[2];
|
|
|
|
int myrank;
|
|
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
|
|
|
|
int mp;
|
|
mp = nprocs / 2;
|
|
|
|
// for other levels
|
|
for (int lev = 0; lev < levels - 1; lev++)
|
|
{
|
|
start_rank[lev] = 0;
|
|
end_rank[lev] = mp - 1;
|
|
}
|
|
// for finest level
|
|
start_rank[levels - 1] = end_rank[0] + 1;
|
|
end_rank[levels - 1] = nprocs - 1;
|
|
|
|
if (myrank >= start_rank[0] && myrank <= end_rank[0])
|
|
mylev = -1; // for other levels
|
|
else
|
|
mylev = 1; // for finest level
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
|
|
|
|
void cgh::compose_cgh(int nprocs)
|
|
{
|
|
Commlev = new MPI_Comm[levels];
|
|
construct_mylev(nprocs);
|
|
|
|
for (int lev = 0; lev < levels - 1; lev++)
|
|
{
|
|
MPI_Comm_split(MPI_COMM_WORLD, mylev, -1, &Commlev[lev]);
|
|
}
|
|
MPI_Comm_split(MPI_COMM_WORLD, mylev, 1, &Commlev[levels - 1]);
|
|
|
|
for (int lev = 0; lev < levels; lev++)
|
|
{
|
|
checkPatchList(PatL[lev], false);
|
|
Parallel::distribute(PatL[lev], end_rank[lev] - start_rank[lev] + 1, ingfs, fngfs, false, start_rank[lev], end_rank[lev]);
|
|
#if (RPB == 1)
|
|
#error "not support yet"
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
void cgh::sethandle(monitor *ErrorMonitor)
|
|
{
|
|
int BH_num;
|
|
Porgls = new double **[levels];
|
|
char filename[100];
|
|
{
|
|
map<string, string>::iterator iter = parameters::str_par.find("inputpar");
|
|
if (iter != parameters::str_par.end())
|
|
{
|
|
strcpy(filename, (iter->second).c_str());
|
|
}
|
|
else
|
|
{
|
|
cout << "Error inputpar" << endl;
|
|
exit(0);
|
|
}
|
|
}
|
|
// read parameter from file
|
|
{
|
|
const int LEN = 256;
|
|
char pline[LEN];
|
|
string str, sgrp, skey, sval;
|
|
int sind;
|
|
ifstream inf(filename, ifstream::in);
|
|
if (!inf.good() && ErrorMonitor && ErrorMonitor->outfile)
|
|
{
|
|
ErrorMonitor->outfile << "Can not open parameter file " << filename << " for inputing information of black holes" << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
|
|
for (int i = 1; inf.good(); i++)
|
|
{
|
|
inf.getline(pline, LEN);
|
|
str = pline;
|
|
|
|
int status = misc::parse_parts(str, sgrp, skey, sval, sind);
|
|
if (status == -1)
|
|
{
|
|
if (ErrorMonitor && ErrorMonitor->outfile)
|
|
ErrorMonitor->outfile << "error reading parameter file " << filename << " in line " << i << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
else if (status == 0)
|
|
continue;
|
|
|
|
if (sgrp == "BSSN" && skey == "BH_num")
|
|
BH_num = atoi(sval.c_str());
|
|
else if (sgrp == "cgh" && skey == "moving levels start from")
|
|
{
|
|
movls = atoi(sval.c_str());
|
|
movls = Mymin(movls, levels);
|
|
movls = Mymax(0, movls);
|
|
}
|
|
}
|
|
inf.close();
|
|
}
|
|
for (int lev = 0; lev < levels; lev++)
|
|
{
|
|
Porgls[lev] = new double *[BH_num];
|
|
for (int i = 0; i < BH_num; i++)
|
|
Porgls[lev][i] = new double[dim];
|
|
}
|
|
// read parameter from file
|
|
{
|
|
const int LEN = 256;
|
|
char pline[LEN];
|
|
string str, sgrp, skey, sval;
|
|
int sind;
|
|
ifstream inf(filename, ifstream::in);
|
|
if (!inf.good() && ErrorMonitor && ErrorMonitor->outfile)
|
|
{
|
|
ErrorMonitor->outfile << "Can not open parameter file " << filename
|
|
<< " for inputing information of black holes" << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
|
|
for (int i = 1; inf.good(); i++)
|
|
{
|
|
inf.getline(pline, LEN);
|
|
str = pline;
|
|
|
|
int status = misc::parse_parts(str, sgrp, skey, sval, sind);
|
|
if (status == -1)
|
|
{
|
|
if (ErrorMonitor && ErrorMonitor->outfile)
|
|
ErrorMonitor->outfile << "error reading parameter file " << filename << " in line " << i << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
else if (status == 0)
|
|
continue;
|
|
|
|
if (sgrp == "BSSN" && sind < BH_num)
|
|
{
|
|
if (skey == "Porgx")
|
|
{
|
|
for (int lev = 0; lev < levels; lev++)
|
|
Porgls[lev][sind][0] = atof(sval.c_str());
|
|
}
|
|
else if (skey == "Porgy")
|
|
{
|
|
for (int lev = 0; lev < levels; lev++)
|
|
Porgls[lev][sind][1] = atof(sval.c_str());
|
|
}
|
|
else if (skey == "Porgz")
|
|
{
|
|
for (int lev = 0; lev < levels; lev++)
|
|
Porgls[lev][sind][2] = atof(sval.c_str());
|
|
}
|
|
}
|
|
}
|
|
inf.close();
|
|
}
|
|
|
|
for (int lev = 0; lev < movls; lev++)
|
|
for (int grd = 0; grd < grids[lev]; grd++)
|
|
for (int i = 0; i < dim; i++)
|
|
handle[lev][grd][i] = 0;
|
|
|
|
if (movls < levels)
|
|
{
|
|
if (ErrorMonitor && ErrorMonitor->I_Print)
|
|
{
|
|
cout << endl;
|
|
cout << " moving levels are lev #" << movls << "--" << levels - 1 << endl;
|
|
cout << endl;
|
|
}
|
|
|
|
for (int lev = movls; lev < levels; lev++)
|
|
for (int grd = 0; grd < grids[lev]; grd++)
|
|
{
|
|
#if 0
|
|
int bht=0;
|
|
for(int bhi=0;bhi<BH_num;bhi++)
|
|
{
|
|
bool flag=false;
|
|
|
|
for(int i=0;i<dim;i++)
|
|
if(Porgls[0][bhi][i] < bbox[lev][grd][i] || Porgls[0][bhi][i] > bbox[lev][grd][i+dim]) {flag=true; break;}
|
|
if(flag) continue;
|
|
bht++;
|
|
if(bht==1) for(int i=0;i<dim;i++) handle[lev][grd][i]=Porgls[0][bhi][i];
|
|
else if(ErrorMonitor && ErrorMonitor->outfile)
|
|
{
|
|
ErrorMonitor->outfile<<"cgh::sethandle: lev#"<<lev<<" grd#"<<grd<<" has too many black holes"<<endl;
|
|
MPI_Abort(MPI_COMM_WORLD,1);
|
|
}
|
|
}
|
|
#else
|
|
double xxc[dim], dis0, dis1;
|
|
for (int i = 0; i < dim; i++)
|
|
xxc[i] = (bbox[lev][grd][i] + bbox[lev][grd][i + dim]) / 2;
|
|
int bht = 0;
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
if (bhi == 0)
|
|
{
|
|
dis0 = 0;
|
|
for (int i = 0; i < dim; i++)
|
|
dis0 += pow(Porgls[0][bhi][i] - xxc[i], 2);
|
|
dis0 = sqrt(dis0);
|
|
}
|
|
else
|
|
{
|
|
dis1 = 0;
|
|
for (int i = 0; i < dim; i++)
|
|
dis1 += pow(Porgls[0][bhi][i] - xxc[i], 2);
|
|
dis1 = sqrt(dis1);
|
|
if (dis0 > dis1)
|
|
{
|
|
bht = bhi;
|
|
dis0 = dis1;
|
|
} // chose nearest one
|
|
}
|
|
}
|
|
for (int i = 0; i < dim; i++)
|
|
handle[lev][grd][i] = Porgls[0][bht][i];
|
|
#endif
|
|
}
|
|
}
|
|
else if (ErrorMonitor && ErrorMonitor->I_Print)
|
|
{
|
|
if (levels > 1)
|
|
cout << "fixed mesh refinement!" << endl;
|
|
else
|
|
cout << "unigrid simulation!" << endl;
|
|
}
|
|
|
|
BH_num_in = BH_num;
|
|
}
|
|
void cgh::checkPatchList(MyList<Patch> *PatL, bool buflog)
|
|
{
|
|
while (PatL)
|
|
{
|
|
PatL->data->checkPatch(buflog);
|
|
PatL = PatL->next;
|
|
}
|
|
}
|
|
|
|
|
|
//================================================================================================
|
|
|
|
// This member function moves the grid
|
|
|
|
//================================================================================================
|
|
|
|
void cgh::Regrid(int Symmetry, int BH_num, double **Porgbr, double **Porg0,
|
|
MyList<var> *OldList, MyList<var> *StateList,
|
|
MyList<var> *FutureList, MyList<var> *tmList, bool BB,
|
|
monitor *ErrorMonitor)
|
|
{
|
|
// for moving part
|
|
if (movls < levels)
|
|
{
|
|
bool tot_flag = false;
|
|
bool *lev_flag;
|
|
double **tmpPorg;
|
|
tmpPorg = new double *[BH_num];
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
tmpPorg[bhi] = new double[dim];
|
|
for (int i = 0; i < dim; i++)
|
|
tmpPorg[bhi][i] = Porgbr[bhi][i];
|
|
}
|
|
lev_flag = new bool[levels - movls];
|
|
for (int lev = movls; lev < levels; lev++)
|
|
{
|
|
lev_flag[lev - movls] = false;
|
|
for (int grd = 0; grd < grids[lev]; grd++)
|
|
{
|
|
int flag;
|
|
int do_every = 2;
|
|
double dX = PatL[lev]->data->blb->data->getdX(0);
|
|
double dY = PatL[lev]->data->blb->data->getdX(1);
|
|
double dZ = PatL[lev]->data->blb->data->getdX(2);
|
|
double rr;
|
|
// make sure that the grid corresponds to the black hole
|
|
int bhi = 0;
|
|
for (bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
// because finner level may also change Porgbr, so we need factor 2
|
|
if (feq(Porgbr[bhi][0], handle[lev][grd][0], 2 * do_every * dX) &&
|
|
feq(Porgbr[bhi][1], handle[lev][grd][1], 2 * do_every * dY) &&
|
|
feq(Porgbr[bhi][2], handle[lev][grd][2], 2 * do_every * dZ))
|
|
break;
|
|
}
|
|
if (bhi == BH_num)
|
|
{
|
|
// if the box has already touched the original point
|
|
if (feq(0, bbox[lev][grd][0], dX / 2) &&
|
|
feq(0, bbox[lev][grd][1], dY / 2) &&
|
|
feq(0, bbox[lev][grd][2], dZ / 2))
|
|
break;
|
|
|
|
if (BH_num == 1)
|
|
{
|
|
bhi = 0;
|
|
break;
|
|
} // if only one black hole, it definitely match!
|
|
|
|
if (ErrorMonitor->outfile)
|
|
{
|
|
ErrorMonitor->outfile << "cgh::Regrid: no black hole matches with grid lev#" << lev << " grd#" << grd
|
|
<< " with handle (" << handle[lev][grd][0] << "," << handle[lev][grd][1] << "," << handle[lev][grd][2] << ")" << endl;
|
|
ErrorMonitor->outfile << "black holes' old positions:" << endl;
|
|
for (bhi = 0; bhi < BH_num; bhi++)
|
|
ErrorMonitor->outfile << "#" << bhi << ": (" << Porgbr[bhi][0] << "," << Porgbr[bhi][1] << "," << Porgbr[bhi][2] << ")" << endl;
|
|
ErrorMonitor->outfile << "tolerance:" << endl;
|
|
ErrorMonitor->outfile << "(" << 2 * do_every * dX << "," << 2 * do_every * dY << "," << 2 * do_every * dZ << ")" << endl;
|
|
ErrorMonitor->outfile << "box lower boundary: (" << bbox[lev][grd][0] << "," << bbox[lev][grd][1] << "," << bbox[lev][grd][2] << ")" << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
|
|
delete[] lev_flag;
|
|
for (bhi = 0; bhi < BH_num; bhi++)
|
|
delete[] tmpPorg[bhi];
|
|
delete[] tmpPorg;
|
|
return;
|
|
}
|
|
// x direction
|
|
rr = (Porg0[bhi][0] - handle[lev][grd][0]) / dX;
|
|
if (rr > 0)
|
|
flag = int(rr + 0.5) / do_every;
|
|
else
|
|
flag = int(rr - 0.5) / do_every;
|
|
flag = flag * do_every;
|
|
rr = bbox[lev][grd][0] + flag * dX;
|
|
// pay attention to the symmetric case
|
|
if (Symmetry == 2 && rr < 0)
|
|
rr = -bbox[lev][grd][0];
|
|
else
|
|
rr = flag * dX;
|
|
|
|
if (fabs(rr) > dX / 2)
|
|
{
|
|
lev_flag[lev - movls] = tot_flag = true;
|
|
bbox[lev][grd][0] = bbox[lev][grd][0] + rr;
|
|
bbox[lev][grd][3] = bbox[lev][grd][3] + rr;
|
|
handle[lev][grd][0] += rr;
|
|
tmpPorg[bhi][0] = Porg0[bhi][0];
|
|
}
|
|
|
|
// y direction
|
|
rr = (Porg0[bhi][1] - handle[lev][grd][1]) / dY;
|
|
if (rr > 0)
|
|
flag = int(rr + 0.5) / do_every;
|
|
else
|
|
flag = int(rr - 0.5) / do_every;
|
|
flag = flag * do_every;
|
|
rr = bbox[lev][grd][1] + flag * dY;
|
|
// pay attention to the symmetric case
|
|
if (Symmetry == 2 && rr < 0)
|
|
rr = -bbox[lev][grd][1];
|
|
else
|
|
rr = flag * dY;
|
|
|
|
if (fabs(rr) > dY / 2)
|
|
{
|
|
lev_flag[lev - movls] = tot_flag = true;
|
|
bbox[lev][grd][1] = bbox[lev][grd][1] + rr;
|
|
bbox[lev][grd][4] = bbox[lev][grd][4] + rr;
|
|
handle[lev][grd][1] += rr;
|
|
tmpPorg[bhi][1] = Porg0[bhi][1];
|
|
}
|
|
|
|
// z direction
|
|
rr = (Porg0[bhi][2] - handle[lev][grd][2]) / dZ;
|
|
if (rr > 0)
|
|
flag = int(rr + 0.5) / do_every;
|
|
else
|
|
flag = int(rr - 0.5) / do_every;
|
|
flag = flag * do_every;
|
|
rr = bbox[lev][grd][2] + flag * dZ;
|
|
// pay attention to the symmetric case
|
|
if (Symmetry > 0 && rr < 0)
|
|
rr = -bbox[lev][grd][1];
|
|
else
|
|
rr = flag * dZ;
|
|
|
|
if (fabs(rr) > dZ / 2)
|
|
{
|
|
lev_flag[lev - movls] = tot_flag = true;
|
|
bbox[lev][grd][2] = bbox[lev][grd][2] + rr;
|
|
bbox[lev][grd][5] = bbox[lev][grd][5] + rr;
|
|
handle[lev][grd][2] += rr;
|
|
tmpPorg[bhi][2] = Porg0[bhi][2];
|
|
}
|
|
}
|
|
// if(ErrorMonitor->outfile && lev_flag[lev-movls]) cout<<"lev#"<<lev<<"'s boxes moved"<<endl;
|
|
}
|
|
|
|
if (tot_flag)
|
|
{
|
|
int nprocs;
|
|
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
|
|
recompose_cgh(nprocs, lev_flag, OldList, StateList, FutureList, tmList, Symmetry, BB);
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
for (int i = 0; i < dim; i++)
|
|
Porgbr[bhi][i] = tmpPorg[bhi][i];
|
|
}
|
|
}
|
|
|
|
delete[] lev_flag;
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
delete[] tmpPorg[bhi];
|
|
delete[] tmpPorg;
|
|
}
|
|
}
|
|
|
|
//================================================================================================
|
|
|
|
#if (PSTR == 1 || PSTR == 2 || PSTR == 3)
|
|
#warning "Regrid is not implimented yet"
|
|
void cgh::Regrid_fake(int Symmetry, int BH_num, double **Porgbr, double **Porg0,
|
|
MyList<var> *OldList, MyList<var> *StateList,
|
|
MyList<var> *FutureList, MyList<var> *tmList, bool BB,
|
|
monitor *ErrorMonitor)
|
|
{
|
|
// for moving part
|
|
if (movls < levels)
|
|
{
|
|
bool tot_flag = false;
|
|
bool *lev_flag;
|
|
double **tmpPorg;
|
|
tmpPorg = new double *[BH_num];
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
tmpPorg[bhi] = new double[dim];
|
|
for (int i = 0; i < dim; i++)
|
|
tmpPorg[bhi][i] = Porgbr[bhi][i];
|
|
}
|
|
lev_flag = new bool[levels - movls];
|
|
for (int lev = movls; lev < levels; lev++)
|
|
{
|
|
lev_flag[lev - movls] = false;
|
|
for (int grd = 0; grd < grids[lev]; grd++)
|
|
{
|
|
int flag;
|
|
int do_every = 2;
|
|
double dX = PatL[lev]->data->blb->data->getdX(0);
|
|
double dY = PatL[lev]->data->blb->data->getdX(1);
|
|
double dZ = PatL[lev]->data->blb->data->getdX(2);
|
|
double rr;
|
|
// make sure that the grid corresponds to the black hole
|
|
int bhi = 0;
|
|
for (bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
// because finner level may also change Porgbr, so we need factor 2
|
|
if (feq(Porgbr[bhi][0], handle[lev][grd][0], 2 * do_every * dX) &&
|
|
feq(Porgbr[bhi][1], handle[lev][grd][1], 2 * do_every * dY) &&
|
|
feq(Porgbr[bhi][2], handle[lev][grd][2], 2 * do_every * dZ))
|
|
break;
|
|
}
|
|
if (bhi == BH_num)
|
|
{
|
|
// if the box has already touched the original point
|
|
if (feq(0, bbox[lev][grd][0], dX / 2) &&
|
|
feq(0, bbox[lev][grd][1], dY / 2) &&
|
|
feq(0, bbox[lev][grd][2], dZ / 2))
|
|
break;
|
|
|
|
if (BH_num == 1)
|
|
{
|
|
bhi = 0;
|
|
break;
|
|
} // if only one black hole, it definitely match!
|
|
|
|
if (ErrorMonitor->outfile)
|
|
{
|
|
ErrorMonitor->outfile << "cgh::Regrid: no black hole matches with grid lev#" << lev << " grd#" << grd
|
|
<< " with handle (" << handle[lev][grd][0] << "," << handle[lev][grd][1] << "," << handle[lev][grd][2] << ")" << endl;
|
|
ErrorMonitor->outfile << "black holes' old positions:" << endl;
|
|
for (bhi = 0; bhi < BH_num; bhi++)
|
|
ErrorMonitor->outfile << "#" << bhi << ": (" << Porgbr[bhi][0] << "," << Porgbr[bhi][1] << "," << Porgbr[bhi][2] << ")" << endl;
|
|
ErrorMonitor->outfile << "tolerance:" << endl;
|
|
ErrorMonitor->outfile << "(" << 2 * do_every * dX << "," << 2 * do_every * dY << "," << 2 * do_every * dZ << ")" << endl;
|
|
ErrorMonitor->outfile << "box lower boundary: (" << bbox[lev][grd][0] << "," << bbox[lev][grd][1] << "," << bbox[lev][grd][2] << ")" << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
|
|
delete[] lev_flag;
|
|
for (bhi = 0; bhi < BH_num; bhi++)
|
|
delete[] tmpPorg[bhi];
|
|
delete[] tmpPorg;
|
|
return;
|
|
}
|
|
// x direction
|
|
rr = (Porg0[bhi][0] - handle[lev][grd][0]) / dX;
|
|
if (rr > 0)
|
|
flag = int(rr + 0.5) / do_every;
|
|
else
|
|
flag = int(rr - 0.5) / do_every;
|
|
flag = flag * do_every;
|
|
rr = bbox[lev][grd][0] + flag * dX;
|
|
// pay attention to the symmetric case
|
|
if (Symmetry == 2 && rr < 0)
|
|
rr = -bbox[lev][grd][0];
|
|
else
|
|
rr = flag * dX;
|
|
|
|
if (fabs(rr) > dX / 2)
|
|
{
|
|
lev_flag[lev - movls] = tot_flag = true;
|
|
bbox[lev][grd][0] = bbox[lev][grd][0] + rr;
|
|
bbox[lev][grd][3] = bbox[lev][grd][3] + rr;
|
|
handle[lev][grd][0] += rr;
|
|
tmpPorg[bhi][0] = Porg0[bhi][0];
|
|
}
|
|
|
|
// y direction
|
|
rr = (Porg0[bhi][1] - handle[lev][grd][1]) / dY;
|
|
if (rr > 0)
|
|
flag = int(rr + 0.5) / do_every;
|
|
else
|
|
flag = int(rr - 0.5) / do_every;
|
|
flag = flag * do_every;
|
|
rr = bbox[lev][grd][1] + flag * dY;
|
|
// pay attention to the symmetric case
|
|
if (Symmetry == 2 && rr < 0)
|
|
rr = -bbox[lev][grd][1];
|
|
else
|
|
rr = flag * dY;
|
|
|
|
if (fabs(rr) > dY / 2)
|
|
{
|
|
lev_flag[lev - movls] = tot_flag = true;
|
|
bbox[lev][grd][1] = bbox[lev][grd][1] + rr;
|
|
bbox[lev][grd][4] = bbox[lev][grd][4] + rr;
|
|
handle[lev][grd][1] += rr;
|
|
tmpPorg[bhi][1] = Porg0[bhi][1];
|
|
}
|
|
|
|
// z direction
|
|
rr = (Porg0[bhi][2] - handle[lev][grd][2]) / dZ;
|
|
if (rr > 0)
|
|
flag = int(rr + 0.5) / do_every;
|
|
else
|
|
flag = int(rr - 0.5) / do_every;
|
|
flag = flag * do_every;
|
|
rr = bbox[lev][grd][2] + flag * dZ;
|
|
// pay attention to the symmetric case
|
|
if (Symmetry > 0 && rr < 0)
|
|
rr = -bbox[lev][grd][1];
|
|
else
|
|
rr = flag * dZ;
|
|
|
|
if (fabs(rr) > dZ / 2)
|
|
{
|
|
lev_flag[lev - movls] = tot_flag = true;
|
|
bbox[lev][grd][2] = bbox[lev][grd][2] + rr;
|
|
bbox[lev][grd][5] = bbox[lev][grd][5] + rr;
|
|
handle[lev][grd][2] += rr;
|
|
tmpPorg[bhi][2] = Porg0[bhi][2];
|
|
}
|
|
}
|
|
// if(ErrorMonitor->outfile && lev_flag[lev-movls]) cout<<"lev#"<<lev<<"'s boxes moved"<<endl;
|
|
}
|
|
|
|
if (tot_flag)
|
|
{
|
|
int nprocs;
|
|
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
|
|
recompose_cgh_fake(nprocs, lev_flag, OldList, StateList, FutureList, tmList, Symmetry, BB);
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
for (int i = 0; i < dim; i++)
|
|
Porgbr[bhi][i] = tmpPorg[bhi][i];
|
|
}
|
|
}
|
|
|
|
delete[] lev_flag;
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
delete[] tmpPorg[bhi];
|
|
delete[] tmpPorg;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
//================================================================================================
|
|
|
|
// This member function rebuilds the grid (regrid)
|
|
|
|
//================================================================================================
|
|
|
|
#if (PSTR == 0)
|
|
void cgh::recompose_cgh(int nprocs, bool *lev_flag,
|
|
MyList<var> *OldList, MyList<var> *StateList,
|
|
MyList<var> *FutureList, MyList<var> *tmList,
|
|
int Symmetry, bool BB)
|
|
{
|
|
for (int lev = movls; lev < levels; lev++)
|
|
if (lev_flag[lev - movls])
|
|
{
|
|
MyList<Patch> *tmPat = 0;
|
|
tmPat = construct_patchlist(lev, Symmetry);
|
|
// tmPat construction completes
|
|
Parallel::distribute(tmPat, nprocs, ingfs, fngfs, false);
|
|
// checkPatchList(tmPat,true);
|
|
bool CC = (lev > trfls);
|
|
Parallel::fill_level_data(tmPat, PatL[lev], PatL[lev - 1], OldList, StateList, FutureList, tmList, Symmetry, BB, CC);
|
|
|
|
Parallel::KillBlocks(PatL[lev]);
|
|
PatL[lev]->destroyList();
|
|
PatL[lev] = tmPat;
|
|
#if (RPB == 1)
|
|
Parallel::destroypsuList_bam(bdsul[lev]);
|
|
Parallel::destroypsuList_bam(rsul[lev]);
|
|
Parallel::Constr_pointstr_OutBdLow2Hi(PatL[lev], PatL[lev - 1], bdsul[lev]);
|
|
Parallel::Constr_pointstr_Restrict(PatL[lev], PatL[lev - 1], rsul[lev]);
|
|
#endif
|
|
}
|
|
}
|
|
#elif (PSTR == 1 || PSTR == 2 || PSTR == 3)
|
|
#warning "recompose_cgh is not implimented yet"
|
|
void cgh::recompose_cgh(int nprocs, bool *lev_flag,
|
|
MyList<var> *OldList, MyList<var> *StateList,
|
|
MyList<var> *FutureList, MyList<var> *tmList,
|
|
int Symmetry, bool BB)
|
|
{
|
|
for (int lev = movls; lev < levels; lev++)
|
|
if (lev_flag[lev - movls])
|
|
{
|
|
MyList<Patch> *tmPat = 0;
|
|
tmPat = construct_patchlist(lev, Symmetry);
|
|
// tmPat construction completes
|
|
Parallel::distribute(tmPat, end_rank[lev] - start_rank[lev] + 1, ingfs, fngfs, false, start_rank[lev], end_rank[lev]);
|
|
// checkPatchList(tmPat,true);
|
|
bool CC = (lev > trfls);
|
|
Parallel::fill_level_data(tmPat, PatL[lev], PatL[lev - 1], OldList, StateList, FutureList, tmList, Symmetry, BB, CC);
|
|
|
|
Parallel::KillBlocks(PatL[lev]);
|
|
PatL[lev]->destroyList();
|
|
PatL[lev] = tmPat;
|
|
#if (RPB == 1)
|
|
#error "not support yet"
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//================================================================================================
|
|
|
|
void cgh::recompose_cgh_fake(int nprocs, bool *lev_flag,
|
|
MyList<var> *OldList, MyList<var> *StateList,
|
|
MyList<var> *FutureList, MyList<var> *tmList,
|
|
int Symmetry, bool BB)
|
|
{
|
|
for (int lev = movls; lev < levels; lev++)
|
|
if (lev_flag[lev - movls] && lev != mylev)
|
|
{
|
|
MyList<Patch> *tmPat = 0;
|
|
tmPat = construct_patchlist(lev, Symmetry);
|
|
// tmPat construction completes
|
|
Parallel::distribute(tmPat, end_rank[lev] - start_rank[lev] + 1, ingfs, fngfs, false, start_rank[lev], end_rank[lev]);
|
|
|
|
Parallel::KillBlocks(PatL[lev]);
|
|
PatL[lev]->destroyList();
|
|
PatL[lev] = tmPat;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//================================================================================================
|
|
|
|
// This member function reads grid information from input files
|
|
|
|
//================================================================================================
|
|
|
|
void cgh::read_bbox(int Symmetry, char *filename)
|
|
{
|
|
int myrank;
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
|
|
// read parameter from file
|
|
{
|
|
const int LEN = 256;
|
|
char pline[LEN];
|
|
string str, sgrp, skey, sval;
|
|
int sind1, sind2, sind3;
|
|
ifstream inf(filename, ifstream::in);
|
|
if (!inf.good() && myrank == 0)
|
|
{
|
|
cout << "cgh::cgh: Can not open parameter file " << filename << " for inputing information of black holes" << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
|
|
for (int i = 1; inf.good(); i++)
|
|
{
|
|
inf.getline(pline, LEN);
|
|
str = pline;
|
|
|
|
int status = misc::parse_parts(str, sgrp, skey, sval, sind1);
|
|
if (status == -1)
|
|
{
|
|
cout << "error reading parameter file " << filename << " in line " << i << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
else if (status == 0)
|
|
continue;
|
|
|
|
if (sgrp == "cgh" && skey == "levels")
|
|
{
|
|
levels = atoi(sval.c_str());
|
|
break;
|
|
}
|
|
}
|
|
inf.close();
|
|
}
|
|
|
|
grids = new int[levels];
|
|
shape = new int **[levels];
|
|
handle = new double **[levels];
|
|
bbox = new double **[levels];
|
|
PatL = new MyList<Patch> *[levels];
|
|
Lt = new double[levels];
|
|
#if (RPB == 1)
|
|
bdsul = new MyList<Parallel::pointstru_bam> *[levels];
|
|
rsul = new MyList<Parallel::pointstru_bam> *[levels];
|
|
#endif
|
|
// read parameter from file
|
|
{
|
|
const int LEN = 256;
|
|
char pline[LEN];
|
|
string str, sgrp, skey, sval;
|
|
int sind1, sind2, sind3;
|
|
ifstream inf(filename, ifstream::in);
|
|
if (!inf.good() && myrank == 0)
|
|
{
|
|
cout << "cgh::cgh: Can not open parameter file " << filename << " for inputing information of black holes" << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
|
|
for (int i = 1; inf.good(); i++)
|
|
{
|
|
inf.getline(pline, LEN);
|
|
str = pline;
|
|
|
|
int status = misc::parse_parts(str, sgrp, skey, sval, sind1, sind2, sind3);
|
|
if (status == -1)
|
|
{
|
|
cout << "error reading parameter file " << filename << " in line " << i << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
else if (status == 0)
|
|
continue;
|
|
|
|
if (sgrp == "cgh" && skey == "grids" && sind1 < levels)
|
|
grids[sind1] = atoi(sval.c_str());
|
|
}
|
|
inf.close();
|
|
}
|
|
|
|
for (int sind1 = 0; sind1 < levels; sind1++)
|
|
{
|
|
shape[sind1] = new int *[grids[sind1]];
|
|
handle[sind1] = new double *[grids[sind1]];
|
|
bbox[sind1] = new double *[grids[sind1]];
|
|
for (int sind2 = 0; sind2 < grids[sind1]; sind2++)
|
|
{
|
|
shape[sind1][sind2] = new int[dim];
|
|
handle[sind1][sind2] = new double[dim];
|
|
bbox[sind1][sind2] = new double[2 * dim];
|
|
}
|
|
}
|
|
// read parameter from file
|
|
{
|
|
const int LEN = 256;
|
|
char pline[LEN];
|
|
string str, sgrp, skey, sval;
|
|
int sind1, sind2, sind3;
|
|
ifstream inf(filename, ifstream::in);
|
|
if (!inf.good() && myrank == 0)
|
|
{
|
|
cout << "cgh::cgh: Can not open parameter file " << filename << " for inputing information of black holes" << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
|
|
for (int i = 1; inf.good(); i++)
|
|
{
|
|
inf.getline(pline, LEN);
|
|
str = pline;
|
|
|
|
int status = misc::parse_parts(str, sgrp, skey, sval, sind1, sind2, sind3);
|
|
|
|
if (status == -1)
|
|
{
|
|
cout << "error reading parameter file " << filename << " in line " << i << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
else if (status == 0)
|
|
continue;
|
|
|
|
if (sgrp == "cgh" && sind1 < levels && sind2 < grids[sind1])
|
|
{
|
|
if (skey == "bbox")
|
|
bbox[sind1][sind2][sind3] = atof(sval.c_str());
|
|
else if (skey == "shape")
|
|
shape[sind1][sind2][sind3] = atoi(sval.c_str());
|
|
}
|
|
}
|
|
inf.close();
|
|
}
|
|
// we always assume the input parameter is in cell center style
|
|
#ifdef Vertex
|
|
#ifdef Cell
|
|
#error Both Cell and Vertex are defined
|
|
#endif
|
|
for (int lev = 0; lev < levels; lev++)
|
|
for (int grd = 0; grd < grids[lev]; grd++)
|
|
{
|
|
for (int i = 0; i < dim; i++)
|
|
{
|
|
|
|
shape[lev][grd][i] = shape[lev][grd][i] + 1;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
{
|
|
|
|
// boxes align check
|
|
double DH0[dim];
|
|
for (int i = 0; i < dim; i++)
|
|
#ifdef Vertex
|
|
#ifdef Cell
|
|
#error Both Cell and Vertex are defined
|
|
#endif
|
|
DH0[i] = (bbox[0][0][i + dim] - bbox[0][0][i]) / (shape[0][0][i] - 1);
|
|
#else
|
|
#ifdef Cell
|
|
DH0[i] = (bbox[0][0][i + dim] - bbox[0][0][i]) / shape[0][0][i];
|
|
#else
|
|
#error Not define Vertex nor Cell
|
|
#endif
|
|
#endif
|
|
for (int lev = 0; lev < levels; lev++)
|
|
for (int grd = 0; grd < grids[lev]; grd++)
|
|
Parallel::aligncheck(bbox[0][0], bbox[lev][grd], lev, DH0, shape[lev][grd]);
|
|
|
|
#if 0 // we do not need it here, because we do it in construct_patchlist
|
|
// extend buffer points for shell overlap
|
|
#ifdef WithShell
|
|
for(int i=0;i<dim;i++)
|
|
{
|
|
shape[0][0][i] += buffer_width;
|
|
bbox[0][0][i+dim] += DH0[i]*buffer_width;
|
|
}
|
|
if(Symmetry < 2 )
|
|
{
|
|
shape[0][0][0] += buffer_width;
|
|
bbox[0][0][0] -= DH0[0]*buffer_width;
|
|
shape[0][0][1] += buffer_width;
|
|
bbox[0][0][1] -= DH0[1]*buffer_width;
|
|
if(Symmetry < 1)
|
|
{
|
|
shape[0][0][2] += buffer_width;
|
|
bbox[0][0][2] -= DH0[2]*buffer_width;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
// print information of cgh
|
|
if (myrank == 0)
|
|
{
|
|
cout << endl;
|
|
cout << " cgh has levels: " << levels << endl;
|
|
cout << endl;
|
|
for (int lev = 0; lev < levels; lev++)
|
|
{
|
|
cout << " level #" << lev << " has boxes: " << grids[lev] << endl;
|
|
for (int grd = 0; grd < grids[lev]; grd++)
|
|
{
|
|
cout << " #" << grd << " box is" << " (" << bbox[lev][grd][0] << ":" << bbox[lev][grd][3]
|
|
<< "," << bbox[lev][grd][1] << ":" << bbox[lev][grd][4]
|
|
<< "," << bbox[lev][grd][2] << ":" << bbox[lev][grd][5]
|
|
<< ")." << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//================================================================================================
|
|
|
|
|
|
//================================================================================================
|
|
|
|
// This member function generates required grid information
|
|
|
|
//================================================================================================
|
|
|
|
MyList<Patch> *cgh::construct_patchlist(int lev, int Symmetry)
|
|
{
|
|
// Construct Patches
|
|
MyList<Patch> *tmPat = 0;
|
|
// construct box list
|
|
MyList<Parallel::gridseg> *boxes = 0, *gs;
|
|
|
|
/*
|
|
int myrank;
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
|
|
if (myrank == 0)
|
|
{
|
|
cout << " construct patchlist: " << " level = " << lev << ", grids in this level = " << grids[lev] << endl;
|
|
}
|
|
*/
|
|
|
|
for (int grd = 0; grd < grids[lev]; grd++)
|
|
{
|
|
if (boxes)
|
|
{
|
|
gs->next = new MyList<Parallel::gridseg>;
|
|
gs = gs->next;
|
|
gs->data = new Parallel::gridseg;
|
|
}
|
|
else
|
|
{
|
|
boxes = gs = new MyList<Parallel::gridseg>;
|
|
gs->data = new Parallel::gridseg;
|
|
}
|
|
for (int i = 0; i < dim; i++)
|
|
{
|
|
gs->data->llb[i] = bbox[lev][grd][i];
|
|
gs->data->uub[i] = bbox[lev][grd][dim + i];
|
|
gs->data->shape[i] = shape[lev][grd][i];
|
|
}
|
|
gs->data->Bg = 0;
|
|
gs->next = 0;
|
|
}
|
|
|
|
// Merge grid boxes (merging more than three boxes may cause bugs)
|
|
// Parallel::merge_gsl(boxes, ratio);
|
|
if (grids[lev] < 3)
|
|
{
|
|
Parallel::merge_gsl(boxes, ratio);
|
|
}
|
|
|
|
// When grid boxes overlap, re-split the boxes
|
|
// Parallel::cut_gsl(boxes);
|
|
if (grids[lev] < 3)
|
|
{
|
|
Parallel::cut_gsl(boxes);
|
|
}
|
|
|
|
// After splitting, add new ghost regions?
|
|
// Parallel::add_ghost_touch(boxes);
|
|
if (grids[lev] < 3)
|
|
{
|
|
Parallel::add_ghost_touch(boxes);
|
|
}
|
|
|
|
MyList<Patch> *gp;
|
|
gs = boxes;
|
|
while (gs)
|
|
{
|
|
double tbb[2 * dim];
|
|
if (tmPat)
|
|
{
|
|
gp->next = new MyList<Patch>;
|
|
gp = gp->next;
|
|
for (int i = 0; i < dim; i++)
|
|
{
|
|
tbb[i] = gs->data->llb[i];
|
|
tbb[dim + i] = gs->data->uub[i];
|
|
}
|
|
#ifdef WithShell
|
|
gp->data = new Patch(3, gs->data->shape, tbb, lev, true, Symmetry);
|
|
#else
|
|
gp->data = new Patch(3, gs->data->shape, tbb, lev, (lev > 0), Symmetry);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
tmPat = gp = new MyList<Patch>;
|
|
for (int i = 0; i < dim; i++)
|
|
{
|
|
tbb[i] = gs->data->llb[i];
|
|
tbb[dim + i] = gs->data->uub[i];
|
|
}
|
|
#ifdef WithShell
|
|
gp->data = new Patch(3, gs->data->shape, tbb, lev, true, Symmetry);
|
|
#else
|
|
gp->data = new Patch(3, gs->data->shape, tbb, lev, (lev > 0), Symmetry);
|
|
#endif
|
|
}
|
|
gp->next = 0;
|
|
|
|
gs = gs->next;
|
|
}
|
|
|
|
boxes->destroyList();
|
|
|
|
return tmPat;
|
|
}
|
|
|
|
//================================================================================================
|
|
|
|
|
|
bool cgh::Interp_One_Point(MyList<var> *VarList,
|
|
double *XX, /*input global Cartesian coordinate*/
|
|
double *Shellf, int Symmetry)
|
|
{
|
|
int lev = levels - 1;
|
|
while (lev >= 0)
|
|
{
|
|
MyList<Patch> *Pp = PatL[lev];
|
|
while (Pp)
|
|
{
|
|
#if (PSTR == 0)
|
|
if (Pp->data->Interp_ONE_Point(VarList, XX, Shellf, Symmetry))
|
|
return true;
|
|
#elif (PSTR == 1 || PSTR == 2 || PSTR == 3)
|
|
if (Pp->data->Interp_ONE_Point(VarList, XX, Shellf, Symmetry, Commlev[lev]))
|
|
return true;
|
|
#endif
|
|
Pp = Pp->next;
|
|
}
|
|
lev--;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void cgh::Regrid_Onelevel(int lev, int Symmetry, int BH_num, double **Porgbr, double **Porg0,
|
|
MyList<var> *OldList, MyList<var> *StateList,
|
|
MyList<var> *FutureList, MyList<var> *tmList, bool BB,
|
|
monitor *ErrorMonitor)
|
|
{
|
|
if (lev < movls)
|
|
return;
|
|
|
|
#if (0)
|
|
// #if (PSTR == 1 || PSTR == 2)
|
|
MyList<Patch> *Pp = PatL[lev];
|
|
while (Pp)
|
|
{
|
|
Pp->data->checkPatch(0, start_rank[mylev]);
|
|
Pp = Pp->next;
|
|
}
|
|
int myrank;
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
|
|
if (myrank == start_rank[mylev])
|
|
{
|
|
cout << "out_rank = " << myrank << endl;
|
|
for (int grd = 0; grd < grids[lev]; grd++)
|
|
{
|
|
cout << handle[lev][grd][0] << "," << handle[lev][grd][1] << "," << handle[lev][grd][2] << endl;
|
|
}
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
cout << Porgls[lev][bhi][0] << "," << Porgls[lev][bhi][1] << "," << Porgls[lev][bhi][2] << endl;
|
|
cout << Porg0[bhi][0] << "," << Porg0[bhi][1] << "," << Porg0[bhi][2] << endl;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// misc::tillherecheck(Commlev[lev],start_rank[lev],"start Regrid_Onelevel");
|
|
// for moving part
|
|
bool tot_flag = false;
|
|
double **tmpPorg;
|
|
tmpPorg = new double *[BH_num];
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
tmpPorg[bhi] = new double[dim];
|
|
for (int i = 0; i < dim; i++)
|
|
tmpPorg[bhi][i] = Porgls[lev][bhi][i];
|
|
}
|
|
|
|
for (int grd = 0; grd < grids[lev]; grd++)
|
|
{
|
|
int flag;
|
|
int do_every = 2;
|
|
double dX = PatL[lev]->data->blb->data->getdX(0);
|
|
double dY = PatL[lev]->data->blb->data->getdX(1);
|
|
double dZ = PatL[lev]->data->blb->data->getdX(2);
|
|
double rr;
|
|
// make sure that the grid corresponds to the black hole
|
|
int bhi = 0;
|
|
for (bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
// because finner level may also change Porgbr, so we need factor 2
|
|
// now I used Porgls
|
|
if (feq(Porgls[lev][bhi][0], handle[lev][grd][0], 2 * do_every * dX) &&
|
|
feq(Porgls[lev][bhi][1], handle[lev][grd][1], 2 * do_every * dY) &&
|
|
feq(Porgls[lev][bhi][2], handle[lev][grd][2], 2 * do_every * dZ))
|
|
break;
|
|
}
|
|
if (bhi == BH_num)
|
|
{
|
|
// if the box has already touched the original point
|
|
if (feq(0, bbox[lev][grd][0], dX / 2) &&
|
|
feq(0, bbox[lev][grd][1], dY / 2) &&
|
|
feq(0, bbox[lev][grd][2], dZ / 2))
|
|
break;
|
|
|
|
if (BH_num == 1)
|
|
{
|
|
bhi = 0;
|
|
break;
|
|
} // if only one black hole, it definitely match!
|
|
|
|
if (ErrorMonitor->outfile)
|
|
{
|
|
ErrorMonitor->outfile << "cgh::Regrid: no black hole matches with grid lev#" << lev << " grd#" << grd
|
|
<< " with handle (" << handle[lev][grd][0] << "," << handle[lev][grd][1] << "," << handle[lev][grd][2] << ")" << endl;
|
|
ErrorMonitor->outfile << "black holes' old positions:" << endl;
|
|
for (bhi = 0; bhi < BH_num; bhi++)
|
|
ErrorMonitor->outfile << "#" << bhi << ": (" << Porgls[lev][bhi][0] << "," << Porgls[lev][bhi][1] << ","
|
|
<< Porgls[lev][bhi][2] << ")" << endl;
|
|
ErrorMonitor->outfile << "tolerance:" << endl;
|
|
ErrorMonitor->outfile << "(" << 2 * do_every * dX << "," << 2 * do_every * dY << "," << 2 * do_every * dZ << ")" << endl;
|
|
ErrorMonitor->outfile << "box lower boundary: (" << bbox[lev][grd][0] << "," << bbox[lev][grd][1] << "," << bbox[lev][grd][2] << ")" << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
|
|
for (bhi = 0; bhi < BH_num; bhi++)
|
|
delete[] tmpPorg[bhi];
|
|
delete[] tmpPorg;
|
|
return;
|
|
}
|
|
// x direction
|
|
rr = (Porg0[bhi][0] - handle[lev][grd][0]) / dX;
|
|
if (rr > 0)
|
|
flag = int(rr + 0.5) / do_every;
|
|
else
|
|
flag = int(rr - 0.5) / do_every;
|
|
flag = flag * do_every;
|
|
rr = bbox[lev][grd][0] + flag * dX;
|
|
// pay attention to the symmetric case
|
|
if (Symmetry == 2 && rr < 0)
|
|
rr = -bbox[lev][grd][0];
|
|
else
|
|
rr = flag * dX;
|
|
|
|
if (fabs(rr) > dX / 2)
|
|
{
|
|
tot_flag = true;
|
|
bbox[lev][grd][0] = bbox[lev][grd][0] + rr;
|
|
bbox[lev][grd][3] = bbox[lev][grd][3] + rr;
|
|
handle[lev][grd][0] += rr;
|
|
tmpPorg[bhi][0] = Porg0[bhi][0];
|
|
}
|
|
|
|
// y direction
|
|
rr = (Porg0[bhi][1] - handle[lev][grd][1]) / dY;
|
|
if (rr > 0)
|
|
flag = int(rr + 0.5) / do_every;
|
|
else
|
|
flag = int(rr - 0.5) / do_every;
|
|
flag = flag * do_every;
|
|
rr = bbox[lev][grd][1] + flag * dY;
|
|
// pay attention to the symmetric case
|
|
if (Symmetry == 2 && rr < 0)
|
|
rr = -bbox[lev][grd][1];
|
|
else
|
|
rr = flag * dY;
|
|
|
|
if (fabs(rr) > dY / 2)
|
|
{
|
|
tot_flag = true;
|
|
bbox[lev][grd][1] = bbox[lev][grd][1] + rr;
|
|
bbox[lev][grd][4] = bbox[lev][grd][4] + rr;
|
|
handle[lev][grd][1] += rr;
|
|
tmpPorg[bhi][1] = Porg0[bhi][1];
|
|
}
|
|
|
|
// z direction
|
|
rr = (Porg0[bhi][2] - handle[lev][grd][2]) / dZ;
|
|
if (rr > 0)
|
|
flag = int(rr + 0.5) / do_every;
|
|
else
|
|
flag = int(rr - 0.5) / do_every;
|
|
flag = flag * do_every;
|
|
rr = bbox[lev][grd][2] + flag * dZ;
|
|
// pay attention to the symmetric case
|
|
if (Symmetry > 0 && rr < 0)
|
|
rr = -bbox[lev][grd][1];
|
|
else
|
|
rr = flag * dZ;
|
|
|
|
if (fabs(rr) > dZ / 2)
|
|
{
|
|
tot_flag = true;
|
|
bbox[lev][grd][2] = bbox[lev][grd][2] + rr;
|
|
bbox[lev][grd][5] = bbox[lev][grd][5] + rr;
|
|
handle[lev][grd][2] += rr;
|
|
tmpPorg[bhi][2] = Porg0[bhi][2];
|
|
}
|
|
}
|
|
|
|
// misc::tillherecheck(Commlev[lev],start_rank[lev],"after tot_flag check");
|
|
|
|
if (tot_flag)
|
|
{
|
|
int nprocs;
|
|
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
|
|
|
|
// misc::tillherecheck(Commlev[lev],start_rank[lev],"before recompose_cgh_Onelevel");
|
|
|
|
recompose_cgh_Onelevel(nprocs, lev, OldList, StateList, FutureList, tmList, Symmetry, BB);
|
|
|
|
// misc::tillherecheck(Commlev[lev],start_rank[lev],"after recompose_cgh_Onelevel");
|
|
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
for (int i = 0; i < dim; i++)
|
|
Porgls[lev][bhi][i] = tmpPorg[bhi][i];
|
|
}
|
|
|
|
#if (PSTR == 1 || PSTR == 2)
|
|
// MyList<Patch> *Pp=PatL[lev];
|
|
// while(Pp)
|
|
// {
|
|
// Pp->data->checkPatch(0,start_rank[mylev]);
|
|
// Pp=Pp->next;
|
|
// }
|
|
#endif
|
|
}
|
|
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
delete[] tmpPorg[bhi];
|
|
delete[] tmpPorg;
|
|
}
|
|
|
|
|
|
#if (PSTR == 0)
|
|
void cgh::recompose_cgh_Onelevel(int nprocs, int lev,
|
|
MyList<var> *OldList, MyList<var> *StateList,
|
|
MyList<var> *FutureList, MyList<var> *tmList,
|
|
int Symmetry, bool BB)
|
|
{
|
|
MyList<Patch> *tmPat = 0;
|
|
tmPat = construct_patchlist(lev, Symmetry);
|
|
// tmPat construction completes
|
|
Parallel::distribute(tmPat, nprocs, ingfs, fngfs, false);
|
|
// checkPatchList(tmPat,true);
|
|
bool CC = (lev > trfls);
|
|
Parallel::fill_level_data(tmPat, PatL[lev], PatL[lev - 1], OldList, StateList, FutureList, tmList, Symmetry, BB, CC);
|
|
|
|
Parallel::KillBlocks(PatL[lev]);
|
|
PatL[lev]->destroyList();
|
|
PatL[lev] = tmPat;
|
|
}
|
|
#elif (PSTR == 1 || PSTR == 2 || PSTR == 3)
|
|
#warning "recompose_cgh_Onelevel is not implimented yet"
|
|
void cgh::recompose_cgh_Onelevel(int nprocs, int lev,
|
|
MyList<var> *OldList, MyList<var> *StateList,
|
|
MyList<var> *FutureList, MyList<var> *tmList,
|
|
int Symmetry, bool BB)
|
|
{
|
|
MyList<Patch> *tmPat = 0;
|
|
misc::tillherecheck(Commlev[lev], start_rank[lev], "before construct_patchlist");
|
|
tmPat = construct_patchlist(lev, Symmetry);
|
|
misc::tillherecheck(Commlev[lev], start_rank[lev], "after construct_patchlist");
|
|
// tmPat construction completes
|
|
Parallel::distribute(tmPat, end_rank[lev] - start_rank[lev] + 1, ingfs, fngfs, false, start_rank[lev], end_rank[lev]);
|
|
misc::tillherecheck(Commlev[lev], start_rank[lev], "after distribute");
|
|
// checkPatchList(tmPat,true);
|
|
bool CC = (lev > trfls);
|
|
Parallel::fill_level_data(tmPat, PatL[lev], PatL[lev - 1], OldList, StateList, FutureList, tmList, Symmetry, BB, CC);
|
|
misc::tillherecheck(Commlev[lev], start_rank[lev], "after fill_level_data");
|
|
|
|
Parallel::KillBlocks(PatL[lev]);
|
|
PatL[lev]->destroyList();
|
|
PatL[lev] = tmPat;
|
|
}
|
|
|
|
|
|
// the input lev is lower level for regrid
|
|
void cgh::Regrid_Onelevel_aux(int lev, int Symmetry, int BH_num, double **Porgbr, double **Porg0,
|
|
MyList<var> *OldList, MyList<var> *StateList,
|
|
MyList<var> *FutureList, MyList<var> *tmList, bool BB,
|
|
monitor *ErrorMonitor)
|
|
{
|
|
lev++;
|
|
if (lev < movls)
|
|
return;
|
|
|
|
// for moving part
|
|
bool tot_flag = false;
|
|
double **tmpPorg;
|
|
tmpPorg = new double *[BH_num];
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
tmpPorg[bhi] = new double[dim];
|
|
for (int i = 0; i < dim; i++)
|
|
tmpPorg[bhi][i] = Porgbr[bhi][i];
|
|
}
|
|
|
|
for (int grd = 0; grd < grids[lev]; grd++)
|
|
{
|
|
int flag;
|
|
int do_every = 2;
|
|
double dX = PatL[lev]->data->blb->data->getdX(0);
|
|
double dY = PatL[lev]->data->blb->data->getdX(1);
|
|
double dZ = PatL[lev]->data->blb->data->getdX(2);
|
|
double rr;
|
|
// make sure that the grid corresponds to the black hole
|
|
int bhi = 0;
|
|
for (bhi = 0; bhi < BH_num; bhi++)
|
|
{
|
|
// because finner level may also change Porgbr, so we need factor 2
|
|
if (feq(Porgbr[bhi][0], handle[lev][grd][0], 2 * do_every * dX) &&
|
|
feq(Porgbr[bhi][1], handle[lev][grd][1], 2 * do_every * dY) &&
|
|
feq(Porgbr[bhi][2], handle[lev][grd][2], 2 * do_every * dZ))
|
|
break;
|
|
}
|
|
if (bhi == BH_num)
|
|
{
|
|
// if the box has already touched the original point
|
|
if (feq(0, bbox[lev][grd][0], dX / 2) &&
|
|
feq(0, bbox[lev][grd][1], dY / 2) &&
|
|
feq(0, bbox[lev][grd][2], dZ / 2))
|
|
break;
|
|
|
|
if (BH_num == 1)
|
|
{
|
|
bhi = 0;
|
|
break;
|
|
} // if only one black hole, it definitely match!
|
|
|
|
if (ErrorMonitor->outfile)
|
|
{
|
|
ErrorMonitor->outfile << "cgh::Regrid: no black hole matches with grid lev#" << lev << " grd#" << grd
|
|
<< " with handle (" << handle[lev][grd][0] << "," << handle[lev][grd][1] << "," << handle[lev][grd][2] << ")" << endl;
|
|
ErrorMonitor->outfile << "black holes' old positions:" << endl;
|
|
for (bhi = 0; bhi < BH_num; bhi++)
|
|
ErrorMonitor->outfile << "#" << bhi << ": (" << Porgbr[bhi][0] << "," << Porgbr[bhi][1] << "," << Porgbr[bhi][2] << ")" << endl;
|
|
ErrorMonitor->outfile << "tolerance:" << endl;
|
|
ErrorMonitor->outfile << "(" << 2 * do_every * dX << "," << 2 * do_every * dY << "," << 2 * do_every * dZ << ")" << endl;
|
|
ErrorMonitor->outfile << "box lower boundary: (" << bbox[lev][grd][0] << "," << bbox[lev][grd][1] << "," << bbox[lev][grd][2] << ")" << endl;
|
|
MPI_Abort(MPI_COMM_WORLD, 1);
|
|
}
|
|
|
|
for (bhi = 0; bhi < BH_num; bhi++)
|
|
delete[] tmpPorg[bhi];
|
|
delete[] tmpPorg;
|
|
return;
|
|
}
|
|
// x direction
|
|
rr = (Porg0[bhi][0] - handle[lev][grd][0]) / dX;
|
|
if (rr > 0)
|
|
flag = int(rr + 0.5) / do_every;
|
|
else
|
|
flag = int(rr - 0.5) / do_every;
|
|
flag = flag * do_every;
|
|
rr = bbox[lev][grd][0] + flag * dX;
|
|
// pay attention to the symmetric case
|
|
if (Symmetry == 2 && rr < 0)
|
|
rr = -bbox[lev][grd][0];
|
|
else
|
|
rr = flag * dX;
|
|
|
|
if (fabs(rr) > dX / 2)
|
|
{
|
|
tot_flag = true;
|
|
bbox[lev][grd][0] = bbox[lev][grd][0] + rr;
|
|
bbox[lev][grd][3] = bbox[lev][grd][3] + rr;
|
|
handle[lev][grd][0] += rr;
|
|
tmpPorg[bhi][0] = Porg0[bhi][0];
|
|
}
|
|
|
|
// y direction
|
|
rr = (Porg0[bhi][1] - handle[lev][grd][1]) / dY;
|
|
if (rr > 0)
|
|
flag = int(rr + 0.5) / do_every;
|
|
else
|
|
flag = int(rr - 0.5) / do_every;
|
|
flag = flag * do_every;
|
|
rr = bbox[lev][grd][1] + flag * dY;
|
|
// pay attention to the symmetric case
|
|
if (Symmetry == 2 && rr < 0)
|
|
rr = -bbox[lev][grd][1];
|
|
else
|
|
rr = flag * dY;
|
|
|
|
if (fabs(rr) > dY / 2)
|
|
{
|
|
tot_flag = true;
|
|
bbox[lev][grd][1] = bbox[lev][grd][1] + rr;
|
|
bbox[lev][grd][4] = bbox[lev][grd][4] + rr;
|
|
handle[lev][grd][1] += rr;
|
|
tmpPorg[bhi][1] = Porg0[bhi][1];
|
|
}
|
|
|
|
// z direction
|
|
rr = (Porg0[bhi][2] - handle[lev][grd][2]) / dZ;
|
|
if (rr > 0)
|
|
flag = int(rr + 0.5) / do_every;
|
|
else
|
|
flag = int(rr - 0.5) / do_every;
|
|
flag = flag * do_every;
|
|
rr = bbox[lev][grd][2] + flag * dZ;
|
|
// pay attention to the symmetric case
|
|
if (Symmetry > 0 && rr < 0)
|
|
rr = -bbox[lev][grd][1];
|
|
else
|
|
rr = flag * dZ;
|
|
|
|
if (fabs(rr) > dZ / 2)
|
|
{
|
|
tot_flag = true;
|
|
bbox[lev][grd][2] = bbox[lev][grd][2] + rr;
|
|
bbox[lev][grd][5] = bbox[lev][grd][5] + rr;
|
|
handle[lev][grd][2] += rr;
|
|
tmpPorg[bhi][2] = Porg0[bhi][2];
|
|
}
|
|
}
|
|
|
|
if (tot_flag)
|
|
{
|
|
int nprocs;
|
|
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
|
|
recompose_cgh_Onelevel(nprocs, lev, OldList, StateList, FutureList, tmList, Symmetry, BB);
|
|
}
|
|
|
|
for (int bhi = 0; bhi < BH_num; bhi++)
|
|
delete[] tmpPorg[bhi];
|
|
delete[] tmpPorg;
|
|
}
|
|
#endif
|
|
|
|
|
|
void cgh::settrfls(const int lev)
|
|
{
|
|
trfls = lev;
|
|
}
|