Compare commits
4 Commits
chb-parall
...
yx-prolong
| Author | SHA1 | Date | |
|---|---|---|---|
| 12e1f63d50 | |||
| 47f91ff46f | |||
|
|
672b7ebee2 | ||
|
|
63bf180159 |
@@ -7,7 +7,6 @@
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <new>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
||||
#include "misc.h"
|
||||
@@ -18,168 +17,6 @@ using namespace std;
|
||||
#include "interp_lb_profile.h"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
struct InterpBlockView
|
||||
{
|
||||
Block *bp;
|
||||
double llb[dim];
|
||||
double uub[dim];
|
||||
};
|
||||
|
||||
struct BlockBinIndex
|
||||
{
|
||||
int bins[dim];
|
||||
double lo[dim];
|
||||
double inv[dim];
|
||||
vector<InterpBlockView> views;
|
||||
vector<vector<int>> bin_to_blocks;
|
||||
bool valid;
|
||||
|
||||
BlockBinIndex() : valid(false)
|
||||
{
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
bins[i] = 1;
|
||||
lo[i] = 0.0;
|
||||
inv[i] = 0.0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline int clamp_int(int v, int lo, int hi)
|
||||
{
|
||||
return (v < lo) ? lo : ((v > hi) ? hi : v);
|
||||
}
|
||||
|
||||
inline int coord_to_bin(double x, double lo, double inv, int nb)
|
||||
{
|
||||
if (nb <= 1 || inv <= 0.0)
|
||||
return 0;
|
||||
int b = int(floor((x - lo) * inv));
|
||||
return clamp_int(b, 0, nb - 1);
|
||||
}
|
||||
|
||||
inline int bin_loc(const BlockBinIndex &index, int b0, int b1, int b2)
|
||||
{
|
||||
return b0 + index.bins[0] * (b1 + index.bins[1] * b2);
|
||||
}
|
||||
|
||||
inline bool point_in_block_view(const InterpBlockView &view, const double *pox, const double *DH)
|
||||
{
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
if (pox[i] - view.llb[i] < -DH[i] / 2 || pox[i] - view.uub[i] > DH[i] / 2)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void build_block_bin_index(Patch *patch, const double *DH, BlockBinIndex &index)
|
||||
{
|
||||
index = BlockBinIndex();
|
||||
|
||||
MyList<Block> *Bp = patch->blb;
|
||||
while (Bp)
|
||||
{
|
||||
Block *BP = Bp->data;
|
||||
InterpBlockView view;
|
||||
view.bp = BP;
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
#ifdef Vertex
|
||||
#ifdef Cell
|
||||
#error Both Cell and Vertex are defined
|
||||
#endif
|
||||
view.llb[i] = (feq(BP->bbox[i], patch->bbox[i], DH[i] / 2)) ? BP->bbox[i] + patch->lli[i] * DH[i] : BP->bbox[i] + (ghost_width - 0.5) * DH[i];
|
||||
view.uub[i] = (feq(BP->bbox[dim + i], patch->bbox[dim + i], DH[i] / 2)) ? BP->bbox[dim + i] - patch->uui[i] * DH[i] : BP->bbox[dim + i] - (ghost_width - 0.5) * DH[i];
|
||||
#else
|
||||
#ifdef Cell
|
||||
view.llb[i] = (feq(BP->bbox[i], patch->bbox[i], DH[i] / 2)) ? BP->bbox[i] + patch->lli[i] * DH[i] : BP->bbox[i] + ghost_width * DH[i];
|
||||
view.uub[i] = (feq(BP->bbox[dim + i], patch->bbox[dim + i], DH[i] / 2)) ? BP->bbox[dim + i] - patch->uui[i] * DH[i] : BP->bbox[dim + i] - ghost_width * DH[i];
|
||||
#else
|
||||
#error Not define Vertex nor Cell
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
index.views.push_back(view);
|
||||
if (Bp == patch->ble)
|
||||
break;
|
||||
Bp = Bp->next;
|
||||
}
|
||||
|
||||
const int nblocks = int(index.views.size());
|
||||
if (nblocks <= 0)
|
||||
return;
|
||||
|
||||
int bins_1d = int(ceil(pow(double(nblocks), 1.0 / 3.0)));
|
||||
bins_1d = clamp_int(bins_1d, 1, 32);
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
index.bins[i] = bins_1d;
|
||||
index.lo[i] = patch->bbox[i] + patch->lli[i] * DH[i];
|
||||
const double hi = patch->bbox[dim + i] - patch->uui[i] * DH[i];
|
||||
if (hi > index.lo[i] && bins_1d > 1)
|
||||
index.inv[i] = bins_1d / (hi - index.lo[i]);
|
||||
else
|
||||
index.inv[i] = 0.0;
|
||||
}
|
||||
|
||||
index.bin_to_blocks.resize(index.bins[0] * index.bins[1] * index.bins[2]);
|
||||
|
||||
for (int bi = 0; bi < nblocks; bi++)
|
||||
{
|
||||
const InterpBlockView &view = index.views[bi];
|
||||
int bmin[dim], bmax[dim];
|
||||
for (int d = 0; d < dim; d++)
|
||||
{
|
||||
const double low = view.llb[d] - DH[d] / 2;
|
||||
const double up = view.uub[d] + DH[d] / 2;
|
||||
bmin[d] = coord_to_bin(low, index.lo[d], index.inv[d], index.bins[d]);
|
||||
bmax[d] = coord_to_bin(up, index.lo[d], index.inv[d], index.bins[d]);
|
||||
if (bmax[d] < bmin[d])
|
||||
{
|
||||
int t = bmin[d];
|
||||
bmin[d] = bmax[d];
|
||||
bmax[d] = t;
|
||||
}
|
||||
}
|
||||
|
||||
for (int bz = bmin[2]; bz <= bmax[2]; bz++)
|
||||
for (int by = bmin[1]; by <= bmax[1]; by++)
|
||||
for (int bx = bmin[0]; bx <= bmax[0]; bx++)
|
||||
index.bin_to_blocks[bin_loc(index, bx, by, bz)].push_back(bi);
|
||||
}
|
||||
|
||||
index.valid = true;
|
||||
}
|
||||
|
||||
int find_block_index_for_point(const BlockBinIndex &index, const double *pox, const double *DH)
|
||||
{
|
||||
if (!index.valid)
|
||||
return -1;
|
||||
|
||||
const int bx = coord_to_bin(pox[0], index.lo[0], index.inv[0], index.bins[0]);
|
||||
const int by = coord_to_bin(pox[1], index.lo[1], index.inv[1], index.bins[1]);
|
||||
const int bz = coord_to_bin(pox[2], index.lo[2], index.inv[2], index.bins[2]);
|
||||
const vector<int> &cand = index.bin_to_blocks[bin_loc(index, bx, by, bz)];
|
||||
|
||||
for (size_t ci = 0; ci < cand.size(); ci++)
|
||||
{
|
||||
const int bi = cand[ci];
|
||||
if (point_in_block_view(index.views[bi], pox, DH))
|
||||
return bi;
|
||||
}
|
||||
|
||||
// Fallback to full scan for numerical edge cases around bin boundaries.
|
||||
for (size_t bi = 0; bi < index.views.size(); bi++)
|
||||
if (point_in_block_view(index.views[bi], pox, DH))
|
||||
return int(bi);
|
||||
|
||||
return -1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Patch::Patch(int DIM, int *shapei, double *bboxi, int levi, bool buflog, int Symmetry) : lev(levi)
|
||||
{
|
||||
|
||||
@@ -530,11 +367,9 @@ void Patch::Interp_Points(MyList<var> *VarList,
|
||||
for (int j = 0; j < NN; j++)
|
||||
owner_rank[j] = -1;
|
||||
|
||||
double DH[dim];
|
||||
double DH[dim], llb[dim], uub[dim];
|
||||
for (int i = 0; i < dim; i++)
|
||||
DH[i] = getdX(i);
|
||||
BlockBinIndex block_index;
|
||||
build_block_bin_index(this, DH, block_index);
|
||||
|
||||
for (int j = 0; j < NN; j++) // run along points
|
||||
{
|
||||
@@ -557,10 +392,39 @@ void Patch::Interp_Points(MyList<var> *VarList,
|
||||
}
|
||||
}
|
||||
|
||||
const int block_i = find_block_index_for_point(block_index, pox, DH);
|
||||
if (block_i >= 0)
|
||||
MyList<Block> *Bp = blb;
|
||||
bool notfind = true;
|
||||
while (notfind && Bp) // run along Blocks
|
||||
{
|
||||
Block *BP = block_index.views[block_i].bp;
|
||||
Block *BP = Bp->data;
|
||||
|
||||
bool flag = true;
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
#ifdef Vertex
|
||||
#ifdef Cell
|
||||
#error Both Cell and Vertex are defined
|
||||
#endif
|
||||
llb[i] = (feq(BP->bbox[i], bbox[i], DH[i] / 2)) ? BP->bbox[i] + lli[i] * DH[i] : BP->bbox[i] + (ghost_width - 0.5) * DH[i];
|
||||
uub[i] = (feq(BP->bbox[dim + i], bbox[dim + i], DH[i] / 2)) ? BP->bbox[dim + i] - uui[i] * DH[i] : BP->bbox[dim + i] - (ghost_width - 0.5) * DH[i];
|
||||
#else
|
||||
#ifdef Cell
|
||||
llb[i] = (feq(BP->bbox[i], bbox[i], DH[i] / 2)) ? BP->bbox[i] + lli[i] * DH[i] : BP->bbox[i] + ghost_width * DH[i];
|
||||
uub[i] = (feq(BP->bbox[dim + i], bbox[dim + i], DH[i] / 2)) ? BP->bbox[dim + i] - uui[i] * DH[i] : BP->bbox[dim + i] - ghost_width * DH[i];
|
||||
#else
|
||||
#error Not define Vertex nor Cell
|
||||
#endif
|
||||
#endif
|
||||
if (XX[i][j] - llb[i] < -DH[i] / 2 || XX[i][j] - uub[i] > DH[i] / 2)
|
||||
{
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
notfind = false;
|
||||
owner_rank[j] = BP->rank;
|
||||
if (myrank == BP->rank)
|
||||
{
|
||||
@@ -576,6 +440,10 @@ void Patch::Interp_Points(MyList<var> *VarList,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Bp == ble)
|
||||
break;
|
||||
Bp = Bp->next;
|
||||
}
|
||||
}
|
||||
|
||||
// Replace MPI_Allreduce with per-owner MPI_Bcast:
|
||||
@@ -667,11 +535,9 @@ void Patch::Interp_Points(MyList<var> *VarList,
|
||||
for (int j = 0; j < NN; j++)
|
||||
owner_rank[j] = -1;
|
||||
|
||||
double DH[dim];
|
||||
double DH[dim], llb[dim], uub[dim];
|
||||
for (int i = 0; i < dim; i++)
|
||||
DH[i] = getdX(i);
|
||||
BlockBinIndex block_index;
|
||||
build_block_bin_index(this, DH, block_index);
|
||||
|
||||
// --- Interpolation phase (identical to original) ---
|
||||
for (int j = 0; j < NN; j++)
|
||||
@@ -695,10 +561,39 @@ void Patch::Interp_Points(MyList<var> *VarList,
|
||||
}
|
||||
}
|
||||
|
||||
const int block_i = find_block_index_for_point(block_index, pox, DH);
|
||||
if (block_i >= 0)
|
||||
MyList<Block> *Bp = blb;
|
||||
bool notfind = true;
|
||||
while (notfind && Bp)
|
||||
{
|
||||
Block *BP = block_index.views[block_i].bp;
|
||||
Block *BP = Bp->data;
|
||||
|
||||
bool flag = true;
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
#ifdef Vertex
|
||||
#ifdef Cell
|
||||
#error Both Cell and Vertex are defined
|
||||
#endif
|
||||
llb[i] = (feq(BP->bbox[i], bbox[i], DH[i] / 2)) ? BP->bbox[i] + lli[i] * DH[i] : BP->bbox[i] + (ghost_width - 0.5) * DH[i];
|
||||
uub[i] = (feq(BP->bbox[dim + i], bbox[dim + i], DH[i] / 2)) ? BP->bbox[dim + i] - uui[i] * DH[i] : BP->bbox[dim + i] - (ghost_width - 0.5) * DH[i];
|
||||
#else
|
||||
#ifdef Cell
|
||||
llb[i] = (feq(BP->bbox[i], bbox[i], DH[i] / 2)) ? BP->bbox[i] + lli[i] * DH[i] : BP->bbox[i] + ghost_width * DH[i];
|
||||
uub[i] = (feq(BP->bbox[dim + i], bbox[dim + i], DH[i] / 2)) ? BP->bbox[dim + i] - uui[i] * DH[i] : BP->bbox[dim + i] - ghost_width * DH[i];
|
||||
#else
|
||||
#error Not define Vertex nor Cell
|
||||
#endif
|
||||
#endif
|
||||
if (XX[i][j] - llb[i] < -DH[i] / 2 || XX[i][j] - uub[i] > DH[i] / 2)
|
||||
{
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
notfind = false;
|
||||
owner_rank[j] = BP->rank;
|
||||
if (myrank == BP->rank)
|
||||
{
|
||||
@@ -713,6 +608,10 @@ void Patch::Interp_Points(MyList<var> *VarList,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Bp == ble)
|
||||
break;
|
||||
Bp = Bp->next;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INTERP_LB_PROFILE
|
||||
@@ -934,11 +833,9 @@ void Patch::Interp_Points(MyList<var> *VarList,
|
||||
MPI_Comm_group(MPI_COMM_WORLD, &world_group);
|
||||
MPI_Comm_group(Comm_here, &local_group);
|
||||
|
||||
double DH[dim];
|
||||
double DH[dim], llb[dim], uub[dim];
|
||||
for (int i = 0; i < dim; i++)
|
||||
DH[i] = getdX(i);
|
||||
BlockBinIndex block_index;
|
||||
build_block_bin_index(this, DH, block_index);
|
||||
|
||||
for (int j = 0; j < NN; j++) // run along points
|
||||
{
|
||||
@@ -961,10 +858,39 @@ void Patch::Interp_Points(MyList<var> *VarList,
|
||||
}
|
||||
}
|
||||
|
||||
const int block_i = find_block_index_for_point(block_index, pox, DH);
|
||||
if (block_i >= 0)
|
||||
MyList<Block> *Bp = blb;
|
||||
bool notfind = true;
|
||||
while (notfind && Bp) // run along Blocks
|
||||
{
|
||||
Block *BP = block_index.views[block_i].bp;
|
||||
Block *BP = Bp->data;
|
||||
|
||||
bool flag = true;
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
#ifdef Vertex
|
||||
#ifdef Cell
|
||||
#error Both Cell and Vertex are defined
|
||||
#endif
|
||||
llb[i] = (feq(BP->bbox[i], bbox[i], DH[i] / 2)) ? BP->bbox[i] + lli[i] * DH[i] : BP->bbox[i] + (ghost_width - 0.5) * DH[i];
|
||||
uub[i] = (feq(BP->bbox[dim + i], bbox[dim + i], DH[i] / 2)) ? BP->bbox[dim + i] - uui[i] * DH[i] : BP->bbox[dim + i] - (ghost_width - 0.5) * DH[i];
|
||||
#else
|
||||
#ifdef Cell
|
||||
llb[i] = (feq(BP->bbox[i], bbox[i], DH[i] / 2)) ? BP->bbox[i] + lli[i] * DH[i] : BP->bbox[i] + ghost_width * DH[i];
|
||||
uub[i] = (feq(BP->bbox[dim + i], bbox[dim + i], DH[i] / 2)) ? BP->bbox[dim + i] - uui[i] * DH[i] : BP->bbox[dim + i] - ghost_width * DH[i];
|
||||
#else
|
||||
#error Not define Vertex nor Cell
|
||||
#endif
|
||||
#endif
|
||||
if (XX[i][j] - llb[i] < -DH[i] / 2 || XX[i][j] - uub[i] > DH[i] / 2)
|
||||
{
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag)
|
||||
{
|
||||
notfind = false;
|
||||
owner_rank[j] = BP->rank;
|
||||
if (myrank == BP->rank)
|
||||
{
|
||||
@@ -980,6 +906,10 @@ void Patch::Interp_Points(MyList<var> *VarList,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Bp == ble)
|
||||
break;
|
||||
Bp = Bp->next;
|
||||
}
|
||||
}
|
||||
|
||||
// Collect unique global owner ranks and translate to local ranks in Comm_here
|
||||
|
||||
@@ -3893,105 +3893,66 @@ void Parallel::transfer(MyList<Parallel::gridseg> **src, MyList<Parallel::gridse
|
||||
|
||||
int node;
|
||||
|
||||
MPI_Request *reqs = new MPI_Request[2 * cpusize];
|
||||
MPI_Status *stats = new MPI_Status[2 * cpusize];
|
||||
int *req_node = new int[2 * cpusize];
|
||||
int *req_is_recv = new int[2 * cpusize];
|
||||
int *completed = new int[2 * cpusize];
|
||||
MPI_Request *reqs;
|
||||
MPI_Status *stats;
|
||||
reqs = new MPI_Request[2 * cpusize];
|
||||
stats = new MPI_Status[2 * cpusize];
|
||||
int req_no = 0;
|
||||
int pending_recv = 0;
|
||||
|
||||
double **send_data = new double *[cpusize];
|
||||
double **rec_data = new double *[cpusize];
|
||||
int *send_lengths = new int[cpusize];
|
||||
int *recv_lengths = new int[cpusize];
|
||||
double **send_data, **rec_data;
|
||||
send_data = new double *[cpusize];
|
||||
rec_data = new double *[cpusize];
|
||||
int length;
|
||||
|
||||
for (node = 0; node < cpusize; node++)
|
||||
{
|
||||
send_data[node] = rec_data[node] = 0;
|
||||
send_lengths[node] = recv_lengths[node] = 0;
|
||||
}
|
||||
|
||||
// Post receives first so peers can progress rendezvous early.
|
||||
for (node = 0; node < cpusize; node++)
|
||||
if (node == myrank)
|
||||
{
|
||||
if (node == myrank) continue;
|
||||
|
||||
recv_lengths[node] = data_packer(0, src[node], dst[node], node, UNPACK, VarList1, VarList2, Symmetry);
|
||||
if (recv_lengths[node] > 0)
|
||||
if (length = data_packer(0, src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry))
|
||||
{
|
||||
rec_data[node] = new double[recv_lengths[node]];
|
||||
rec_data[node] = new double[length];
|
||||
if (!rec_data[node])
|
||||
{
|
||||
cout << "out of memory when new in short transfer, place 1" << endl;
|
||||
MPI_Abort(MPI_COMM_WORLD, 1);
|
||||
}
|
||||
MPI_Irecv((void *)rec_data[node], recv_lengths[node], MPI_DOUBLE, node, 1, MPI_COMM_WORLD, reqs + req_no);
|
||||
req_node[req_no] = node;
|
||||
req_is_recv[req_no] = 1;
|
||||
req_no++;
|
||||
pending_recv++;
|
||||
data_packer(rec_data[node], src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
}
|
||||
}
|
||||
|
||||
// Local transfer on this rank.
|
||||
recv_lengths[myrank] = data_packer(0, src[myrank], dst[myrank], myrank, PACK, VarList1, VarList2, Symmetry);
|
||||
if (recv_lengths[myrank] > 0)
|
||||
else
|
||||
{
|
||||
rec_data[myrank] = new double[recv_lengths[myrank]];
|
||||
if (!rec_data[myrank])
|
||||
// send from this cpu to cpu#node
|
||||
if (length = data_packer(0, src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry))
|
||||
{
|
||||
send_data[node] = new double[length];
|
||||
if (!send_data[node])
|
||||
{
|
||||
cout << "out of memory when new in short transfer, place 2" << endl;
|
||||
MPI_Abort(MPI_COMM_WORLD, 1);
|
||||
}
|
||||
data_packer(rec_data[myrank], src[myrank], dst[myrank], myrank, PACK, VarList1, VarList2, Symmetry);
|
||||
data_packer(send_data[node], src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
MPI_Isend((void *)send_data[node], length, MPI_DOUBLE, node, 1, MPI_COMM_WORLD, reqs + req_no++);
|
||||
}
|
||||
|
||||
// Pack and post sends.
|
||||
for (node = 0; node < cpusize; node++)
|
||||
// receive from cpu#node to this cpu
|
||||
if (length = data_packer(0, src[node], dst[node], node, UNPACK, VarList1, VarList2, Symmetry))
|
||||
{
|
||||
if (node == myrank) continue;
|
||||
|
||||
send_lengths[node] = data_packer(0, src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
if (send_lengths[node] > 0)
|
||||
{
|
||||
send_data[node] = new double[send_lengths[node]];
|
||||
if (!send_data[node])
|
||||
rec_data[node] = new double[length];
|
||||
if (!rec_data[node])
|
||||
{
|
||||
cout << "out of memory when new in short transfer, place 3" << endl;
|
||||
MPI_Abort(MPI_COMM_WORLD, 1);
|
||||
}
|
||||
data_packer(send_data[node], src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
MPI_Isend((void *)send_data[node], send_lengths[node], MPI_DOUBLE, node, 1, MPI_COMM_WORLD, reqs + req_no);
|
||||
req_node[req_no] = node;
|
||||
req_is_recv[req_no] = 0;
|
||||
req_no++;
|
||||
MPI_Irecv((void *)rec_data[node], length, MPI_DOUBLE, node, 1, MPI_COMM_WORLD, reqs + req_no++);
|
||||
}
|
||||
}
|
||||
}
|
||||
// wait for all requests to complete
|
||||
MPI_Waitall(req_no, reqs, stats);
|
||||
|
||||
// Unpack as soon as receive completes to reduce pure wait time.
|
||||
while (pending_recv > 0)
|
||||
{
|
||||
int outcount = 0;
|
||||
MPI_Waitsome(req_no, reqs, &outcount, completed, stats);
|
||||
if (outcount == MPI_UNDEFINED) break;
|
||||
|
||||
for (int i = 0; i < outcount; i++)
|
||||
{
|
||||
int idx = completed[i];
|
||||
if (idx >= 0 && req_is_recv[idx])
|
||||
{
|
||||
int recv_node = req_node[idx];
|
||||
data_packer(rec_data[recv_node], src[recv_node], dst[recv_node], recv_node, UNPACK, VarList1, VarList2, Symmetry);
|
||||
pending_recv--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (req_no > 0) MPI_Waitall(req_no, reqs, stats);
|
||||
|
||||
if (rec_data[myrank])
|
||||
data_packer(rec_data[myrank], src[myrank], dst[myrank], myrank, UNPACK, VarList1, VarList2, Symmetry);
|
||||
for (node = 0; node < cpusize; node++)
|
||||
if (rec_data[node])
|
||||
data_packer(rec_data[node], src[node], dst[node], node, UNPACK, VarList1, VarList2, Symmetry);
|
||||
|
||||
for (node = 0; node < cpusize; node++)
|
||||
{
|
||||
@@ -4003,13 +3964,8 @@ void Parallel::transfer(MyList<Parallel::gridseg> **src, MyList<Parallel::gridse
|
||||
|
||||
delete[] reqs;
|
||||
delete[] stats;
|
||||
delete[] req_node;
|
||||
delete[] req_is_recv;
|
||||
delete[] completed;
|
||||
delete[] send_data;
|
||||
delete[] rec_data;
|
||||
delete[] send_lengths;
|
||||
delete[] recv_lengths;
|
||||
}
|
||||
//
|
||||
void Parallel::transfermix(MyList<Parallel::gridseg> **src, MyList<Parallel::gridseg> **dst,
|
||||
@@ -4022,105 +3978,66 @@ void Parallel::transfermix(MyList<Parallel::gridseg> **src, MyList<Parallel::gri
|
||||
|
||||
int node;
|
||||
|
||||
MPI_Request *reqs = new MPI_Request[2 * cpusize];
|
||||
MPI_Status *stats = new MPI_Status[2 * cpusize];
|
||||
int *req_node = new int[2 * cpusize];
|
||||
int *req_is_recv = new int[2 * cpusize];
|
||||
int *completed = new int[2 * cpusize];
|
||||
MPI_Request *reqs;
|
||||
MPI_Status *stats;
|
||||
reqs = new MPI_Request[2 * cpusize];
|
||||
stats = new MPI_Status[2 * cpusize];
|
||||
int req_no = 0;
|
||||
int pending_recv = 0;
|
||||
|
||||
double **send_data = new double *[cpusize];
|
||||
double **rec_data = new double *[cpusize];
|
||||
int *send_lengths = new int[cpusize];
|
||||
int *recv_lengths = new int[cpusize];
|
||||
double **send_data, **rec_data;
|
||||
send_data = new double *[cpusize];
|
||||
rec_data = new double *[cpusize];
|
||||
int length;
|
||||
|
||||
for (node = 0; node < cpusize; node++)
|
||||
{
|
||||
send_data[node] = rec_data[node] = 0;
|
||||
send_lengths[node] = recv_lengths[node] = 0;
|
||||
}
|
||||
|
||||
// Post receives first so peers can progress rendezvous early.
|
||||
for (node = 0; node < cpusize; node++)
|
||||
if (node == myrank)
|
||||
{
|
||||
if (node == myrank) continue;
|
||||
|
||||
recv_lengths[node] = data_packermix(0, src[node], dst[node], node, UNPACK, VarList1, VarList2, Symmetry);
|
||||
if (recv_lengths[node] > 0)
|
||||
if (length = data_packermix(0, src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry))
|
||||
{
|
||||
rec_data[node] = new double[recv_lengths[node]];
|
||||
rec_data[node] = new double[length];
|
||||
if (!rec_data[node])
|
||||
{
|
||||
cout << "out of memory when new in short transfer, place 1" << endl;
|
||||
MPI_Abort(MPI_COMM_WORLD, 1);
|
||||
}
|
||||
MPI_Irecv((void *)rec_data[node], recv_lengths[node], MPI_DOUBLE, node, 1, MPI_COMM_WORLD, reqs + req_no);
|
||||
req_node[req_no] = node;
|
||||
req_is_recv[req_no] = 1;
|
||||
req_no++;
|
||||
pending_recv++;
|
||||
data_packermix(rec_data[node], src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
}
|
||||
}
|
||||
|
||||
// Local transfer on this rank.
|
||||
recv_lengths[myrank] = data_packermix(0, src[myrank], dst[myrank], myrank, PACK, VarList1, VarList2, Symmetry);
|
||||
if (recv_lengths[myrank] > 0)
|
||||
else
|
||||
{
|
||||
rec_data[myrank] = new double[recv_lengths[myrank]];
|
||||
if (!rec_data[myrank])
|
||||
// send from this cpu to cpu#node
|
||||
if (length = data_packermix(0, src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry))
|
||||
{
|
||||
send_data[node] = new double[length];
|
||||
if (!send_data[node])
|
||||
{
|
||||
cout << "out of memory when new in short transfer, place 2" << endl;
|
||||
MPI_Abort(MPI_COMM_WORLD, 1);
|
||||
}
|
||||
data_packermix(rec_data[myrank], src[myrank], dst[myrank], myrank, PACK, VarList1, VarList2, Symmetry);
|
||||
data_packermix(send_data[node], src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
MPI_Isend((void *)send_data[node], length, MPI_DOUBLE, node, 1, MPI_COMM_WORLD, reqs + req_no++);
|
||||
}
|
||||
|
||||
// Pack and post sends.
|
||||
for (node = 0; node < cpusize; node++)
|
||||
// receive from cpu#node to this cpu
|
||||
if (length = data_packermix(0, src[node], dst[node], node, UNPACK, VarList1, VarList2, Symmetry))
|
||||
{
|
||||
if (node == myrank) continue;
|
||||
|
||||
send_lengths[node] = data_packermix(0, src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
if (send_lengths[node] > 0)
|
||||
{
|
||||
send_data[node] = new double[send_lengths[node]];
|
||||
if (!send_data[node])
|
||||
rec_data[node] = new double[length];
|
||||
if (!rec_data[node])
|
||||
{
|
||||
cout << "out of memory when new in short transfer, place 3" << endl;
|
||||
MPI_Abort(MPI_COMM_WORLD, 1);
|
||||
}
|
||||
data_packermix(send_data[node], src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
MPI_Isend((void *)send_data[node], send_lengths[node], MPI_DOUBLE, node, 1, MPI_COMM_WORLD, reqs + req_no);
|
||||
req_node[req_no] = node;
|
||||
req_is_recv[req_no] = 0;
|
||||
req_no++;
|
||||
MPI_Irecv((void *)rec_data[node], length, MPI_DOUBLE, node, 1, MPI_COMM_WORLD, reqs + req_no++);
|
||||
}
|
||||
}
|
||||
}
|
||||
// wait for all requests to complete
|
||||
MPI_Waitall(req_no, reqs, stats);
|
||||
|
||||
// Unpack as soon as receive completes to reduce pure wait time.
|
||||
while (pending_recv > 0)
|
||||
{
|
||||
int outcount = 0;
|
||||
MPI_Waitsome(req_no, reqs, &outcount, completed, stats);
|
||||
if (outcount == MPI_UNDEFINED) break;
|
||||
|
||||
for (int i = 0; i < outcount; i++)
|
||||
{
|
||||
int idx = completed[i];
|
||||
if (idx >= 0 && req_is_recv[idx])
|
||||
{
|
||||
int recv_node = req_node[idx];
|
||||
data_packermix(rec_data[recv_node], src[recv_node], dst[recv_node], recv_node, UNPACK, VarList1, VarList2, Symmetry);
|
||||
pending_recv--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (req_no > 0) MPI_Waitall(req_no, reqs, stats);
|
||||
|
||||
if (rec_data[myrank])
|
||||
data_packermix(rec_data[myrank], src[myrank], dst[myrank], myrank, UNPACK, VarList1, VarList2, Symmetry);
|
||||
for (node = 0; node < cpusize; node++)
|
||||
if (rec_data[node])
|
||||
data_packermix(rec_data[node], src[node], dst[node], node, UNPACK, VarList1, VarList2, Symmetry);
|
||||
|
||||
for (node = 0; node < cpusize; node++)
|
||||
{
|
||||
@@ -4132,13 +4049,8 @@ void Parallel::transfermix(MyList<Parallel::gridseg> **src, MyList<Parallel::gri
|
||||
|
||||
delete[] reqs;
|
||||
delete[] stats;
|
||||
delete[] req_node;
|
||||
delete[] req_is_recv;
|
||||
delete[] completed;
|
||||
delete[] send_data;
|
||||
delete[] rec_data;
|
||||
delete[] send_lengths;
|
||||
delete[] recv_lengths;
|
||||
}
|
||||
void Parallel::Sync(Patch *Pat, MyList<var> *VarList, int Symmetry)
|
||||
{
|
||||
@@ -4320,7 +4232,7 @@ Parallel::SyncCache::SyncCache()
|
||||
: valid(false), cpusize(0), combined_src(0), combined_dst(0),
|
||||
send_lengths(0), recv_lengths(0), send_bufs(0), recv_bufs(0),
|
||||
send_buf_caps(0), recv_buf_caps(0), reqs(0), stats(0), max_reqs(0),
|
||||
lengths_valid(false), tc_req_node(0), tc_req_is_recv(0), tc_completed(0)
|
||||
lengths_valid(false)
|
||||
{
|
||||
}
|
||||
// SyncCache invalidate: free grid segment lists but keep buffers
|
||||
@@ -4359,15 +4271,11 @@ void Parallel::SyncCache::destroy()
|
||||
if (recv_bufs) delete[] recv_bufs;
|
||||
if (reqs) delete[] reqs;
|
||||
if (stats) delete[] stats;
|
||||
if (tc_req_node) delete[] tc_req_node;
|
||||
if (tc_req_is_recv) delete[] tc_req_is_recv;
|
||||
if (tc_completed) delete[] tc_completed;
|
||||
combined_src = combined_dst = 0;
|
||||
send_lengths = recv_lengths = 0;
|
||||
send_buf_caps = recv_buf_caps = 0;
|
||||
send_bufs = recv_bufs = 0;
|
||||
reqs = 0; stats = 0;
|
||||
tc_req_node = 0; tc_req_is_recv = 0; tc_completed = 0;
|
||||
cpusize = 0; max_reqs = 0;
|
||||
}
|
||||
// transfer_cached: reuse pre-allocated buffers from SyncCache
|
||||
@@ -4381,54 +4289,28 @@ void Parallel::transfer_cached(MyList<Parallel::gridseg> **src, MyList<Parallel:
|
||||
int cpusize = cache.cpusize;
|
||||
|
||||
int req_no = 0;
|
||||
int pending_recv = 0;
|
||||
int node;
|
||||
int *req_node = cache.tc_req_node;
|
||||
int *req_is_recv = cache.tc_req_is_recv;
|
||||
int *completed = cache.tc_completed;
|
||||
|
||||
// Post receives first so peers can progress rendezvous early.
|
||||
for (node = 0; node < cpusize; node++)
|
||||
{
|
||||
if (node == myrank) continue;
|
||||
|
||||
int rlength = data_packer(0, src[node], dst[node], node, UNPACK, VarList1, VarList2, Symmetry);
|
||||
cache.recv_lengths[node] = rlength;
|
||||
if (rlength > 0)
|
||||
if (node == myrank)
|
||||
{
|
||||
if (rlength > cache.recv_buf_caps[node])
|
||||
int length = data_packer(0, src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
cache.recv_lengths[node] = length;
|
||||
if (length > 0)
|
||||
{
|
||||
if (length > cache.recv_buf_caps[node])
|
||||
{
|
||||
if (cache.recv_bufs[node]) delete[] cache.recv_bufs[node];
|
||||
cache.recv_bufs[node] = new double[rlength];
|
||||
cache.recv_buf_caps[node] = rlength;
|
||||
cache.recv_bufs[node] = new double[length];
|
||||
cache.recv_buf_caps[node] = length;
|
||||
}
|
||||
MPI_Irecv((void *)cache.recv_bufs[node], rlength, MPI_DOUBLE, node, 1, MPI_COMM_WORLD, cache.reqs + req_no);
|
||||
req_node[req_no] = node;
|
||||
req_is_recv[req_no] = 1;
|
||||
req_no++;
|
||||
pending_recv++;
|
||||
data_packer(cache.recv_bufs[node], src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
}
|
||||
}
|
||||
|
||||
// Local transfer on this rank.
|
||||
int self_len = data_packer(0, src[myrank], dst[myrank], myrank, PACK, VarList1, VarList2, Symmetry);
|
||||
cache.recv_lengths[myrank] = self_len;
|
||||
if (self_len > 0)
|
||||
else
|
||||
{
|
||||
if (self_len > cache.recv_buf_caps[myrank])
|
||||
{
|
||||
if (cache.recv_bufs[myrank]) delete[] cache.recv_bufs[myrank];
|
||||
cache.recv_bufs[myrank] = new double[self_len];
|
||||
cache.recv_buf_caps[myrank] = self_len;
|
||||
}
|
||||
data_packer(cache.recv_bufs[myrank], src[myrank], dst[myrank], myrank, PACK, VarList1, VarList2, Symmetry);
|
||||
}
|
||||
|
||||
// Pack and post sends.
|
||||
for (node = 0; node < cpusize; node++)
|
||||
{
|
||||
if (node == myrank) continue;
|
||||
|
||||
// send
|
||||
int slength = data_packer(0, src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
cache.send_lengths[node] = slength;
|
||||
if (slength > 0)
|
||||
@@ -4440,37 +4322,31 @@ void Parallel::transfer_cached(MyList<Parallel::gridseg> **src, MyList<Parallel:
|
||||
cache.send_buf_caps[node] = slength;
|
||||
}
|
||||
data_packer(cache.send_bufs[node], src[myrank], dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
MPI_Isend((void *)cache.send_bufs[node], slength, MPI_DOUBLE, node, 1, MPI_COMM_WORLD, cache.reqs + req_no);
|
||||
req_node[req_no] = node;
|
||||
req_is_recv[req_no] = 0;
|
||||
req_no++;
|
||||
MPI_Isend((void *)cache.send_bufs[node], slength, MPI_DOUBLE, node, 1, MPI_COMM_WORLD, cache.reqs + req_no++);
|
||||
}
|
||||
}
|
||||
|
||||
// Unpack as soon as receive completes to reduce pure wait time.
|
||||
while (pending_recv > 0)
|
||||
// recv
|
||||
int rlength = data_packer(0, src[node], dst[node], node, UNPACK, VarList1, VarList2, Symmetry);
|
||||
cache.recv_lengths[node] = rlength;
|
||||
if (rlength > 0)
|
||||
{
|
||||
int outcount = 0;
|
||||
MPI_Waitsome(req_no, cache.reqs, &outcount, completed, cache.stats);
|
||||
if (outcount == MPI_UNDEFINED) break;
|
||||
|
||||
for (int i = 0; i < outcount; i++)
|
||||
if (rlength > cache.recv_buf_caps[node])
|
||||
{
|
||||
int idx = completed[i];
|
||||
if (idx >= 0 && req_is_recv[idx])
|
||||
{
|
||||
int recv_node_i = req_node[idx];
|
||||
data_packer(cache.recv_bufs[recv_node_i], src[recv_node_i], dst[recv_node_i], recv_node_i, UNPACK, VarList1, VarList2, Symmetry);
|
||||
pending_recv--;
|
||||
if (cache.recv_bufs[node]) delete[] cache.recv_bufs[node];
|
||||
cache.recv_bufs[node] = new double[rlength];
|
||||
cache.recv_buf_caps[node] = rlength;
|
||||
}
|
||||
MPI_Irecv((void *)cache.recv_bufs[node], rlength, MPI_DOUBLE, node, 1, MPI_COMM_WORLD, cache.reqs + req_no++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (req_no > 0) MPI_Waitall(req_no, cache.reqs, cache.stats);
|
||||
MPI_Waitall(req_no, cache.reqs, cache.stats);
|
||||
|
||||
if (self_len > 0)
|
||||
data_packer(cache.recv_bufs[myrank], src[myrank], dst[myrank], myrank, UNPACK, VarList1, VarList2, Symmetry);
|
||||
for (node = 0; node < cpusize; node++)
|
||||
if (cache.recv_bufs[node] && cache.recv_lengths[node] > 0)
|
||||
data_packer(cache.recv_bufs[node], src[node], dst[node], node, UNPACK, VarList1, VarList2, Symmetry);
|
||||
}
|
||||
// Sync_cached: build grid segment lists on first call, reuse on subsequent calls
|
||||
void Parallel::Sync_cached(MyList<Patch> *PatL, MyList<var> *VarList, int Symmetry, SyncCache &cache)
|
||||
{
|
||||
if (!cache.valid)
|
||||
@@ -4498,9 +4374,6 @@ void Parallel::Sync_cached(MyList<Patch> *PatL, MyList<var> *VarList, int Symmet
|
||||
cache.max_reqs = 2 * cpusize;
|
||||
cache.reqs = new MPI_Request[cache.max_reqs];
|
||||
cache.stats = new MPI_Status[cache.max_reqs];
|
||||
cache.tc_req_node = new int[cache.max_reqs];
|
||||
cache.tc_req_is_recv = new int[cache.max_reqs];
|
||||
cache.tc_completed = new int[cache.max_reqs];
|
||||
}
|
||||
|
||||
for (int node = 0; node < cpusize; node++)
|
||||
@@ -4601,9 +4474,6 @@ void Parallel::Sync_start(MyList<Patch> *PatL, MyList<var> *VarList, int Symmetr
|
||||
cache.max_reqs = 2 * cpusize;
|
||||
cache.reqs = new MPI_Request[cache.max_reqs];
|
||||
cache.stats = new MPI_Status[cache.max_reqs];
|
||||
cache.tc_req_node = new int[cache.max_reqs];
|
||||
cache.tc_req_is_recv = new int[cache.max_reqs];
|
||||
cache.tc_completed = new int[cache.max_reqs];
|
||||
}
|
||||
|
||||
for (int node = 0; node < cpusize; node++)
|
||||
@@ -4674,11 +4544,6 @@ void Parallel::Sync_start(MyList<Patch> *PatL, MyList<var> *VarList, int Symmetr
|
||||
int cpusize = cache.cpusize;
|
||||
state.req_no = 0;
|
||||
state.active = true;
|
||||
state.pending_recv = 0;
|
||||
// Allocate tracking arrays
|
||||
delete[] state.req_node; delete[] state.req_is_recv;
|
||||
state.req_node = new int[cache.max_reqs];
|
||||
state.req_is_recv = new int[cache.max_reqs];
|
||||
|
||||
MyList<Parallel::gridseg> **src = cache.combined_src;
|
||||
MyList<Parallel::gridseg> **dst = cache.combined_dst;
|
||||
@@ -4723,8 +4588,6 @@ void Parallel::Sync_start(MyList<Patch> *PatL, MyList<var> *VarList, int Symmetr
|
||||
cache.send_buf_caps[node] = slength;
|
||||
}
|
||||
data_packer(cache.send_bufs[node], src[myrank], dst[myrank], node, PACK, VarList, VarList, Symmetry);
|
||||
state.req_node[state.req_no] = node;
|
||||
state.req_is_recv[state.req_no] = 0;
|
||||
MPI_Isend((void *)cache.send_bufs[node], slength, MPI_DOUBLE, node, 2, MPI_COMM_WORLD, cache.reqs + state.req_no++);
|
||||
}
|
||||
int rlength;
|
||||
@@ -4742,60 +4605,29 @@ void Parallel::Sync_start(MyList<Patch> *PatL, MyList<var> *VarList, int Symmetr
|
||||
cache.recv_bufs[node] = new double[rlength];
|
||||
cache.recv_buf_caps[node] = rlength;
|
||||
}
|
||||
state.req_node[state.req_no] = node;
|
||||
state.req_is_recv[state.req_no] = 1;
|
||||
state.pending_recv++;
|
||||
MPI_Irecv((void *)cache.recv_bufs[node], rlength, MPI_DOUBLE, node, 2, MPI_COMM_WORLD, cache.reqs + state.req_no++);
|
||||
}
|
||||
}
|
||||
}
|
||||
cache.lengths_valid = true;
|
||||
}
|
||||
// Sync_finish: progressive unpack as receives complete, then wait for sends
|
||||
// Sync_finish: wait for async MPI operations and unpack
|
||||
void Parallel::Sync_finish(SyncCache &cache, AsyncSyncState &state,
|
||||
MyList<var> *VarList, int Symmetry)
|
||||
{
|
||||
if (!state.active)
|
||||
return;
|
||||
|
||||
int myrank;
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
|
||||
MPI_Waitall(state.req_no, cache.reqs, cache.stats);
|
||||
|
||||
int cpusize = cache.cpusize;
|
||||
MyList<Parallel::gridseg> **src = cache.combined_src;
|
||||
MyList<Parallel::gridseg> **dst = cache.combined_dst;
|
||||
|
||||
// Unpack local data first (no MPI needed)
|
||||
if (cache.recv_bufs[myrank] && cache.recv_lengths[myrank] > 0)
|
||||
data_packer(cache.recv_bufs[myrank], src[myrank], dst[myrank], myrank, UNPACK, VarList, VarList, Symmetry);
|
||||
for (int node = 0; node < cpusize; node++)
|
||||
if (cache.recv_bufs[node] && cache.recv_lengths[node] > 0)
|
||||
data_packer(cache.recv_bufs[node], src[node], dst[node], node, UNPACK, VarList, VarList, Symmetry);
|
||||
|
||||
// Progressive unpack of remote receives
|
||||
if (state.pending_recv > 0 && state.req_no > 0)
|
||||
{
|
||||
int pending = state.pending_recv;
|
||||
int *completed = new int[cache.max_reqs];
|
||||
while (pending > 0)
|
||||
{
|
||||
int outcount = 0;
|
||||
MPI_Waitsome(state.req_no, cache.reqs, &outcount, completed, cache.stats);
|
||||
if (outcount == MPI_UNDEFINED) break;
|
||||
for (int i = 0; i < outcount; i++)
|
||||
{
|
||||
int idx = completed[i];
|
||||
if (idx >= 0 && state.req_is_recv[idx])
|
||||
{
|
||||
int recv_node = state.req_node[idx];
|
||||
data_packer(cache.recv_bufs[recv_node], src[recv_node], dst[recv_node], recv_node, UNPACK, VarList, VarList, Symmetry);
|
||||
pending--;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] completed;
|
||||
}
|
||||
|
||||
// Wait for remaining sends
|
||||
if (state.req_no > 0) MPI_Waitall(state.req_no, cache.reqs, cache.stats);
|
||||
|
||||
delete[] state.req_node; state.req_node = 0;
|
||||
delete[] state.req_is_recv; state.req_is_recv = 0;
|
||||
state.active = false;
|
||||
}
|
||||
// collect buffer grid segments or blocks for the periodic boundary condition of given patch
|
||||
@@ -5862,9 +5694,6 @@ void Parallel::Restrict_cached(MyList<Patch> *PatcL, MyList<Patch> *PatfL,
|
||||
cache.max_reqs = 2 * cpusize;
|
||||
cache.reqs = new MPI_Request[cache.max_reqs];
|
||||
cache.stats = new MPI_Status[cache.max_reqs];
|
||||
cache.tc_req_node = new int[cache.max_reqs];
|
||||
cache.tc_req_is_recv = new int[cache.max_reqs];
|
||||
cache.tc_completed = new int[cache.max_reqs];
|
||||
}
|
||||
|
||||
MyList<Parallel::gridseg> *dst = build_complete_gsl(PatcL);
|
||||
@@ -5911,9 +5740,6 @@ void Parallel::OutBdLow2Hi_cached(MyList<Patch> *PatcL, MyList<Patch> *PatfL,
|
||||
cache.max_reqs = 2 * cpusize;
|
||||
cache.reqs = new MPI_Request[cache.max_reqs];
|
||||
cache.stats = new MPI_Status[cache.max_reqs];
|
||||
cache.tc_req_node = new int[cache.max_reqs];
|
||||
cache.tc_req_is_recv = new int[cache.max_reqs];
|
||||
cache.tc_completed = new int[cache.max_reqs];
|
||||
}
|
||||
|
||||
MyList<Parallel::gridseg> *dst = build_buffer_gsl(PatfL);
|
||||
@@ -5960,9 +5786,6 @@ void Parallel::OutBdLow2Himix_cached(MyList<Patch> *PatcL, MyList<Patch> *PatfL,
|
||||
cache.max_reqs = 2 * cpusize;
|
||||
cache.reqs = new MPI_Request[cache.max_reqs];
|
||||
cache.stats = new MPI_Status[cache.max_reqs];
|
||||
cache.tc_req_node = new int[cache.max_reqs];
|
||||
cache.tc_req_is_recv = new int[cache.max_reqs];
|
||||
cache.tc_completed = new int[cache.max_reqs];
|
||||
}
|
||||
|
||||
MyList<Parallel::gridseg> *dst = build_buffer_gsl(PatfL);
|
||||
@@ -5984,53 +5807,25 @@ void Parallel::OutBdLow2Himix_cached(MyList<Patch> *PatcL, MyList<Patch> *PatfL,
|
||||
int cpusize = cache.cpusize;
|
||||
|
||||
int req_no = 0;
|
||||
int pending_recv = 0;
|
||||
int *req_node = new int[cache.max_reqs];
|
||||
int *req_is_recv = new int[cache.max_reqs];
|
||||
int *completed = new int[cache.max_reqs];
|
||||
|
||||
// Post receives first so peers can progress rendezvous early.
|
||||
for (int node = 0; node < cpusize; node++)
|
||||
{
|
||||
if (node == myrank) continue;
|
||||
|
||||
int rlength = data_packermix(0, cache.combined_src[node], cache.combined_dst[node], node, UNPACK, VarList1, VarList2, Symmetry);
|
||||
cache.recv_lengths[node] = rlength;
|
||||
if (rlength > 0)
|
||||
if (node == myrank)
|
||||
{
|
||||
if (rlength > cache.recv_buf_caps[node])
|
||||
int length = data_packermix(0, cache.combined_src[myrank], cache.combined_dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
cache.recv_lengths[node] = length;
|
||||
if (length > 0)
|
||||
{
|
||||
if (length > cache.recv_buf_caps[node])
|
||||
{
|
||||
if (cache.recv_bufs[node]) delete[] cache.recv_bufs[node];
|
||||
cache.recv_bufs[node] = new double[rlength];
|
||||
cache.recv_buf_caps[node] = rlength;
|
||||
cache.recv_bufs[node] = new double[length];
|
||||
cache.recv_buf_caps[node] = length;
|
||||
}
|
||||
MPI_Irecv((void *)cache.recv_bufs[node], rlength, MPI_DOUBLE, node, 1, MPI_COMM_WORLD, cache.reqs + req_no);
|
||||
req_node[req_no] = node;
|
||||
req_is_recv[req_no] = 1;
|
||||
req_no++;
|
||||
pending_recv++;
|
||||
data_packermix(cache.recv_bufs[node], cache.combined_src[myrank], cache.combined_dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
}
|
||||
}
|
||||
|
||||
// Local transfer on this rank.
|
||||
int self_len = data_packermix(0, cache.combined_src[myrank], cache.combined_dst[myrank], myrank, PACK, VarList1, VarList2, Symmetry);
|
||||
cache.recv_lengths[myrank] = self_len;
|
||||
if (self_len > 0)
|
||||
else
|
||||
{
|
||||
if (self_len > cache.recv_buf_caps[myrank])
|
||||
{
|
||||
if (cache.recv_bufs[myrank]) delete[] cache.recv_bufs[myrank];
|
||||
cache.recv_bufs[myrank] = new double[self_len];
|
||||
cache.recv_buf_caps[myrank] = self_len;
|
||||
}
|
||||
data_packermix(cache.recv_bufs[myrank], cache.combined_src[myrank], cache.combined_dst[myrank], myrank, PACK, VarList1, VarList2, Symmetry);
|
||||
}
|
||||
|
||||
// Pack and post sends.
|
||||
for (int node = 0; node < cpusize; node++)
|
||||
{
|
||||
if (node == myrank) continue;
|
||||
|
||||
int slength = data_packermix(0, cache.combined_src[myrank], cache.combined_dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
cache.send_lengths[node] = slength;
|
||||
if (slength > 0)
|
||||
@@ -6042,40 +5837,28 @@ void Parallel::OutBdLow2Himix_cached(MyList<Patch> *PatcL, MyList<Patch> *PatfL,
|
||||
cache.send_buf_caps[node] = slength;
|
||||
}
|
||||
data_packermix(cache.send_bufs[node], cache.combined_src[myrank], cache.combined_dst[myrank], node, PACK, VarList1, VarList2, Symmetry);
|
||||
MPI_Isend((void *)cache.send_bufs[node], slength, MPI_DOUBLE, node, 1, MPI_COMM_WORLD, cache.reqs + req_no);
|
||||
req_node[req_no] = node;
|
||||
req_is_recv[req_no] = 0;
|
||||
req_no++;
|
||||
MPI_Isend((void *)cache.send_bufs[node], slength, MPI_DOUBLE, node, 1, MPI_COMM_WORLD, cache.reqs + req_no++);
|
||||
}
|
||||
}
|
||||
|
||||
// Unpack as soon as receive completes to reduce pure wait time.
|
||||
while (pending_recv > 0)
|
||||
int rlength = data_packermix(0, cache.combined_src[node], cache.combined_dst[node], node, UNPACK, VarList1, VarList2, Symmetry);
|
||||
cache.recv_lengths[node] = rlength;
|
||||
if (rlength > 0)
|
||||
{
|
||||
int outcount = 0;
|
||||
MPI_Waitsome(req_no, cache.reqs, &outcount, completed, cache.stats);
|
||||
if (outcount == MPI_UNDEFINED) break;
|
||||
|
||||
for (int i = 0; i < outcount; i++)
|
||||
if (rlength > cache.recv_buf_caps[node])
|
||||
{
|
||||
int idx = completed[i];
|
||||
if (idx >= 0 && req_is_recv[idx])
|
||||
{
|
||||
int recv_node_i = req_node[idx];
|
||||
data_packermix(cache.recv_bufs[recv_node_i], cache.combined_src[recv_node_i], cache.combined_dst[recv_node_i], recv_node_i, UNPACK, VarList1, VarList2, Symmetry);
|
||||
pending_recv--;
|
||||
if (cache.recv_bufs[node]) delete[] cache.recv_bufs[node];
|
||||
cache.recv_bufs[node] = new double[rlength];
|
||||
cache.recv_buf_caps[node] = rlength;
|
||||
}
|
||||
MPI_Irecv((void *)cache.recv_bufs[node], rlength, MPI_DOUBLE, node, 1, MPI_COMM_WORLD, cache.reqs + req_no++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (req_no > 0) MPI_Waitall(req_no, cache.reqs, cache.stats);
|
||||
MPI_Waitall(req_no, cache.reqs, cache.stats);
|
||||
|
||||
if (self_len > 0)
|
||||
data_packermix(cache.recv_bufs[myrank], cache.combined_src[myrank], cache.combined_dst[myrank], myrank, UNPACK, VarList1, VarList2, Symmetry);
|
||||
|
||||
delete[] req_node;
|
||||
delete[] req_is_recv;
|
||||
delete[] completed;
|
||||
for (int node = 0; node < cpusize; node++)
|
||||
if (cache.recv_bufs[node] && cache.recv_lengths[node] > 0)
|
||||
data_packermix(cache.recv_bufs[node], cache.combined_src[node], cache.combined_dst[node], node, UNPACK, VarList1, VarList2, Symmetry);
|
||||
}
|
||||
|
||||
// collect all buffer grid segments or blocks for given patch
|
||||
|
||||
@@ -108,9 +108,6 @@ namespace Parallel
|
||||
MPI_Status *stats;
|
||||
int max_reqs;
|
||||
bool lengths_valid;
|
||||
int *tc_req_node;
|
||||
int *tc_req_is_recv;
|
||||
int *tc_completed;
|
||||
SyncCache();
|
||||
void invalidate();
|
||||
void destroy();
|
||||
@@ -124,10 +121,7 @@ namespace Parallel
|
||||
struct AsyncSyncState {
|
||||
int req_no;
|
||||
bool active;
|
||||
int *req_node;
|
||||
int *req_is_recv;
|
||||
int pending_recv;
|
||||
AsyncSyncState() : req_no(0), active(false), req_node(0), req_is_recv(0), pending_recv(0) {}
|
||||
AsyncSyncState() : req_no(0), active(false) {}
|
||||
};
|
||||
|
||||
void Sync_start(MyList<Patch> *PatL, MyList<var> *VarList, int Symmetry,
|
||||
|
||||
@@ -736,8 +736,6 @@ void bssn_class::Initialize()
|
||||
sync_cache_cor = new Parallel::SyncCache[GH->levels];
|
||||
sync_cache_rp_coarse = new Parallel::SyncCache[GH->levels];
|
||||
sync_cache_rp_fine = new Parallel::SyncCache[GH->levels];
|
||||
sync_cache_restrict = new Parallel::SyncCache[GH->levels];
|
||||
sync_cache_outbd = new Parallel::SyncCache[GH->levels];
|
||||
}
|
||||
|
||||
//================================================================================================
|
||||
@@ -2215,7 +2213,7 @@ void bssn_class::Evolve(int Steps)
|
||||
GH->Regrid(Symmetry, BH_num, Porgbr, Porg0,
|
||||
SynchList_cor, OldStateList, StateList, SynchList_pre,
|
||||
fgt(PhysTime - dT_mon, StartTime, dT_mon / 2), ErrorMonitor);
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); sync_cache_restrict[il].invalidate(); sync_cache_outbd[il].invalidate(); }
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); }
|
||||
#endif
|
||||
|
||||
#if (REGLEV == 0 && (PSTR == 1 || PSTR == 2))
|
||||
@@ -2431,7 +2429,7 @@ void bssn_class::RecursiveStep(int lev)
|
||||
if (GH->Regrid_Onelevel(lev, Symmetry, BH_num, Porgbr, Porg0,
|
||||
SynchList_cor, OldStateList, StateList, SynchList_pre,
|
||||
fgt(PhysTime - dT_lev, StartTime, dT_lev / 2), ErrorMonitor))
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); sync_cache_restrict[il].invalidate(); sync_cache_outbd[il].invalidate(); }
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); }
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2610,7 +2608,7 @@ void bssn_class::ParallelStep()
|
||||
if (GH->Regrid_Onelevel(GH->mylev, Symmetry, BH_num, Porgbr, Porg0,
|
||||
SynchList_cor, OldStateList, StateList, SynchList_pre,
|
||||
fgt(PhysTime - dT_lev, StartTime, dT_lev / 2), ErrorMonitor))
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); sync_cache_restrict[il].invalidate(); sync_cache_outbd[il].invalidate(); }
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); }
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2777,7 +2775,7 @@ void bssn_class::ParallelStep()
|
||||
if (GH->Regrid_Onelevel(lev + 1, Symmetry, BH_num, Porgbr, Porg0,
|
||||
SynchList_cor, OldStateList, StateList, SynchList_pre,
|
||||
fgt(PhysTime - dT_levp1, StartTime, dT_levp1 / 2), ErrorMonitor))
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); sync_cache_restrict[il].invalidate(); sync_cache_outbd[il].invalidate(); }
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); }
|
||||
|
||||
// a_stream.clear();
|
||||
// a_stream.str("");
|
||||
@@ -2792,7 +2790,7 @@ void bssn_class::ParallelStep()
|
||||
if (GH->Regrid_Onelevel(lev, Symmetry, BH_num, Porgbr, Porg0,
|
||||
SynchList_cor, OldStateList, StateList, SynchList_pre,
|
||||
fgt(PhysTime - dT_lev, StartTime, dT_lev / 2), ErrorMonitor))
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); sync_cache_restrict[il].invalidate(); sync_cache_outbd[il].invalidate(); }
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); }
|
||||
|
||||
// a_stream.clear();
|
||||
// a_stream.str("");
|
||||
@@ -2811,7 +2809,7 @@ void bssn_class::ParallelStep()
|
||||
if (GH->Regrid_Onelevel(lev - 1, Symmetry, BH_num, Porgbr, Porg0,
|
||||
SynchList_cor, OldStateList, StateList, SynchList_pre,
|
||||
fgt(PhysTime - dT_lev, StartTime, dT_levm1 / 2), ErrorMonitor))
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); sync_cache_restrict[il].invalidate(); sync_cache_outbd[il].invalidate(); }
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); }
|
||||
|
||||
// a_stream.clear();
|
||||
// a_stream.str("");
|
||||
@@ -2827,7 +2825,7 @@ void bssn_class::ParallelStep()
|
||||
if (GH->Regrid_Onelevel(lev - 1, Symmetry, BH_num, Porgbr, Porg0,
|
||||
SynchList_cor, OldStateList, StateList, SynchList_pre,
|
||||
fgt(PhysTime - dT_lev, StartTime, dT_levm1 / 2), ErrorMonitor))
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); sync_cache_restrict[il].invalidate(); sync_cache_outbd[il].invalidate(); }
|
||||
for (int il = 0; il < GH->levels; il++) { sync_cache_pre[il].invalidate(); sync_cache_cor[il].invalidate(); sync_cache_rp_coarse[il].invalidate(); sync_cache_rp_fine[il].invalidate(); }
|
||||
|
||||
// a_stream.clear();
|
||||
// a_stream.str("");
|
||||
@@ -5748,12 +5746,6 @@ void bssn_class::SHStep()
|
||||
// 0: do not use mixing two levels data for OutBD; 1: do use
|
||||
|
||||
#define MIXOUTB 0
|
||||
// In the cached Restrict->OutBdLow2Hi path, coarse Sync is usually redundant:
|
||||
// OutBdLow2Hi_cached reads coarse owned cells (build_owned_gsl type-4), not coarse ghost/buffer cells.
|
||||
// Keep a switch to restore the old behavior if needed for debugging.
|
||||
#ifndef RP_SYNC_COARSE_AFTER_RESTRICT
|
||||
#define RP_SYNC_COARSE_AFTER_RESTRICT 0
|
||||
#endif
|
||||
void bssn_class::RestrictProlong(int lev, int YN, bool BB,
|
||||
MyList<var> *SL, MyList<var> *OL, MyList<var> *corL)
|
||||
// we assume
|
||||
@@ -5804,7 +5796,7 @@ void bssn_class::RestrictProlong(int lev, int YN, bool BB,
|
||||
#endif
|
||||
|
||||
#if (RPB == 0)
|
||||
Parallel::Restrict_cached(GH->PatL[lev - 1], GH->PatL[lev], SL, SynchList_pre, Symmetry, sync_cache_restrict[lev]);
|
||||
Parallel::Restrict(GH->PatL[lev - 1], GH->PatL[lev], SL, SynchList_pre, Symmetry);
|
||||
#elif (RPB == 1)
|
||||
// Parallel::Restrict_bam(GH->PatL[lev-1],GH->PatL[lev],SL,SynchList_pre,Symmetry);
|
||||
Parallel::Restrict_bam(GH->PatL[lev - 1], GH->PatL[lev], SL, SynchList_pre, GH->rsul[lev], Symmetry);
|
||||
@@ -5817,9 +5809,7 @@ void bssn_class::RestrictProlong(int lev, int YN, bool BB,
|
||||
// misc::tillherecheck(GH->Commlev[GH->mylev],GH->start_rank[GH->mylev],a_stream.str());
|
||||
#endif
|
||||
|
||||
#if (RP_SYNC_COARSE_AFTER_RESTRICT == 1)
|
||||
Parallel::Sync_cached(GH->PatL[lev - 1], SynchList_pre, Symmetry, sync_cache_rp_coarse[lev]);
|
||||
#endif
|
||||
|
||||
#if (PSTR == 1 || PSTR == 2)
|
||||
// a_stream.clear();
|
||||
@@ -5830,7 +5820,7 @@ void bssn_class::RestrictProlong(int lev, int YN, bool BB,
|
||||
|
||||
#if (RPB == 0)
|
||||
#if (MIXOUTB == 0)
|
||||
Parallel::OutBdLow2Hi_cached(GH->PatL[lev - 1], GH->PatL[lev], SynchList_pre, SL, Symmetry, sync_cache_outbd[lev]);
|
||||
Parallel::OutBdLow2Hi(GH->PatL[lev - 1], GH->PatL[lev], SynchList_pre, SL, Symmetry);
|
||||
#elif (MIXOUTB == 1)
|
||||
Parallel::OutBdLow2Himix(GH->PatL[lev - 1], GH->PatL[lev], SynchList_pre, SL, Symmetry);
|
||||
#endif
|
||||
@@ -5857,7 +5847,7 @@ void bssn_class::RestrictProlong(int lev, int YN, bool BB,
|
||||
#endif
|
||||
|
||||
#if (RPB == 0)
|
||||
Parallel::Restrict_cached(GH->PatL[lev - 1], GH->PatL[lev], SL, SL, Symmetry, sync_cache_restrict[lev]);
|
||||
Parallel::Restrict(GH->PatL[lev - 1], GH->PatL[lev], SL, SL, Symmetry);
|
||||
#elif (RPB == 1)
|
||||
// Parallel::Restrict_bam(GH->PatL[lev-1],GH->PatL[lev],SL,SL,Symmetry);
|
||||
Parallel::Restrict_bam(GH->PatL[lev - 1], GH->PatL[lev], SL, SL, GH->rsul[lev], Symmetry);
|
||||
@@ -5870,9 +5860,7 @@ void bssn_class::RestrictProlong(int lev, int YN, bool BB,
|
||||
// misc::tillherecheck(GH->Commlev[GH->mylev],GH->start_rank[GH->mylev],a_stream.str());
|
||||
#endif
|
||||
|
||||
#if (RP_SYNC_COARSE_AFTER_RESTRICT == 1)
|
||||
Parallel::Sync_cached(GH->PatL[lev - 1], SL, Symmetry, sync_cache_rp_coarse[lev]);
|
||||
#endif
|
||||
|
||||
#if (PSTR == 1 || PSTR == 2)
|
||||
// a_stream.clear();
|
||||
@@ -5883,7 +5871,7 @@ void bssn_class::RestrictProlong(int lev, int YN, bool BB,
|
||||
|
||||
#if (RPB == 0)
|
||||
#if (MIXOUTB == 0)
|
||||
Parallel::OutBdLow2Hi_cached(GH->PatL[lev - 1], GH->PatL[lev], SL, SL, Symmetry, sync_cache_outbd[lev]);
|
||||
Parallel::OutBdLow2Hi(GH->PatL[lev - 1], GH->PatL[lev], SL, SL, Symmetry);
|
||||
#elif (MIXOUTB == 1)
|
||||
Parallel::OutBdLow2Himix(GH->PatL[lev - 1], GH->PatL[lev], SL, SL, Symmetry);
|
||||
#endif
|
||||
@@ -5952,19 +5940,17 @@ void bssn_class::RestrictProlong_aux(int lev, int YN, bool BB,
|
||||
}
|
||||
|
||||
#if (RPB == 0)
|
||||
Parallel::Restrict_cached(GH->PatL[lev - 1], GH->PatL[lev], SL, SynchList_pre, Symmetry, sync_cache_restrict[lev]);
|
||||
Parallel::Restrict(GH->PatL[lev - 1], GH->PatL[lev], SL, SynchList_pre, Symmetry);
|
||||
#elif (RPB == 1)
|
||||
// Parallel::Restrict_bam(GH->PatL[lev-1],GH->PatL[lev],SL,SynchList_pre,Symmetry);
|
||||
Parallel::Restrict_bam(GH->PatL[lev - 1], GH->PatL[lev], SL, SynchList_pre, GH->rsul[lev], Symmetry);
|
||||
#endif
|
||||
|
||||
#if (RP_SYNC_COARSE_AFTER_RESTRICT == 1)
|
||||
Parallel::Sync_cached(GH->PatL[lev - 1], SynchList_pre, Symmetry, sync_cache_rp_coarse[lev]);
|
||||
#endif
|
||||
|
||||
#if (RPB == 0)
|
||||
#if (MIXOUTB == 0)
|
||||
Parallel::OutBdLow2Hi_cached(GH->PatL[lev - 1], GH->PatL[lev], SynchList_pre, SL, Symmetry, sync_cache_outbd[lev]);
|
||||
Parallel::OutBdLow2Hi(GH->PatL[lev - 1], GH->PatL[lev], SynchList_pre, SL, Symmetry);
|
||||
#elif (MIXOUTB == 1)
|
||||
Parallel::OutBdLow2Himix(GH->PatL[lev - 1], GH->PatL[lev], SynchList_pre, SL, Symmetry);
|
||||
#endif
|
||||
@@ -5976,19 +5962,17 @@ void bssn_class::RestrictProlong_aux(int lev, int YN, bool BB,
|
||||
else // no time refinement levels and for all same time levels
|
||||
{
|
||||
#if (RPB == 0)
|
||||
Parallel::Restrict_cached(GH->PatL[lev - 1], GH->PatL[lev], SL, SL, Symmetry, sync_cache_restrict[lev]);
|
||||
Parallel::Restrict(GH->PatL[lev - 1], GH->PatL[lev], SL, SL, Symmetry);
|
||||
#elif (RPB == 1)
|
||||
// Parallel::Restrict_bam(GH->PatL[lev-1],GH->PatL[lev],SL,SL,Symmetry);
|
||||
Parallel::Restrict_bam(GH->PatL[lev - 1], GH->PatL[lev], SL, SL, GH->rsul[lev], Symmetry);
|
||||
#endif
|
||||
|
||||
#if (RP_SYNC_COARSE_AFTER_RESTRICT == 1)
|
||||
Parallel::Sync_cached(GH->PatL[lev - 1], SL, Symmetry, sync_cache_rp_coarse[lev]);
|
||||
#endif
|
||||
|
||||
#if (RPB == 0)
|
||||
#if (MIXOUTB == 0)
|
||||
Parallel::OutBdLow2Hi_cached(GH->PatL[lev - 1], GH->PatL[lev], SL, SL, Symmetry, sync_cache_outbd[lev]);
|
||||
Parallel::OutBdLow2Hi(GH->PatL[lev - 1], GH->PatL[lev], SL, SL, Symmetry);
|
||||
#elif (MIXOUTB == 1)
|
||||
Parallel::OutBdLow2Himix(GH->PatL[lev - 1], GH->PatL[lev], SL, SL, Symmetry);
|
||||
#endif
|
||||
@@ -6043,19 +6027,17 @@ void bssn_class::RestrictProlong(int lev, int YN, bool BB)
|
||||
}
|
||||
|
||||
#if (RPB == 0)
|
||||
Parallel::Restrict_cached(GH->PatL[lev - 1], GH->PatL[lev], SynchList_cor, SynchList_pre, Symmetry, sync_cache_restrict[lev]);
|
||||
Parallel::Restrict(GH->PatL[lev - 1], GH->PatL[lev], SynchList_cor, SynchList_pre, Symmetry);
|
||||
#elif (RPB == 1)
|
||||
// Parallel::Restrict_bam(GH->PatL[lev-1],GH->PatL[lev],SynchList_cor,SynchList_pre,Symmetry);
|
||||
Parallel::Restrict_bam(GH->PatL[lev - 1], GH->PatL[lev], SynchList_cor, SynchList_pre, GH->rsul[lev], Symmetry);
|
||||
#endif
|
||||
|
||||
#if (RP_SYNC_COARSE_AFTER_RESTRICT == 1)
|
||||
Parallel::Sync_cached(GH->PatL[lev - 1], SynchList_pre, Symmetry, sync_cache_rp_coarse[lev]);
|
||||
#endif
|
||||
|
||||
#if (RPB == 0)
|
||||
#if (MIXOUTB == 0)
|
||||
Parallel::OutBdLow2Hi_cached(GH->PatL[lev - 1], GH->PatL[lev], SynchList_pre, SynchList_cor, Symmetry, sync_cache_outbd[lev]);
|
||||
Parallel::OutBdLow2Hi(GH->PatL[lev - 1], GH->PatL[lev], SynchList_pre, SynchList_cor, Symmetry);
|
||||
#elif (MIXOUTB == 1)
|
||||
Parallel::OutBdLow2Himix(GH->PatL[lev - 1], GH->PatL[lev], SynchList_pre, SynchList_cor, Symmetry);
|
||||
#endif
|
||||
@@ -6069,19 +6051,17 @@ void bssn_class::RestrictProlong(int lev, int YN, bool BB)
|
||||
if (myrank == 0)
|
||||
cout << "===: " << GH->Lt[lev - 1] << "," << GH->Lt[lev] + dT_lev << endl;
|
||||
#if (RPB == 0)
|
||||
Parallel::Restrict_cached(GH->PatL[lev - 1], GH->PatL[lev], SynchList_cor, StateList, Symmetry, sync_cache_restrict[lev]);
|
||||
Parallel::Restrict(GH->PatL[lev - 1], GH->PatL[lev], SynchList_cor, StateList, Symmetry);
|
||||
#elif (RPB == 1)
|
||||
// Parallel::Restrict_bam(GH->PatL[lev-1],GH->PatL[lev],SynchList_cor,StateList,Symmetry);
|
||||
Parallel::Restrict_bam(GH->PatL[lev - 1], GH->PatL[lev], SynchList_cor, StateList, GH->rsul[lev], Symmetry);
|
||||
#endif
|
||||
|
||||
#if (RP_SYNC_COARSE_AFTER_RESTRICT == 1)
|
||||
Parallel::Sync_cached(GH->PatL[lev - 1], StateList, Symmetry, sync_cache_rp_coarse[lev]);
|
||||
#endif
|
||||
|
||||
#if (RPB == 0)
|
||||
#if (MIXOUTB == 0)
|
||||
Parallel::OutBdLow2Hi_cached(GH->PatL[lev - 1], GH->PatL[lev], StateList, SynchList_cor, Symmetry, sync_cache_outbd[lev]);
|
||||
Parallel::OutBdLow2Hi(GH->PatL[lev - 1], GH->PatL[lev], StateList, SynchList_cor, Symmetry);
|
||||
#elif (MIXOUTB == 1)
|
||||
Parallel::OutBdLow2Himix(GH->PatL[lev - 1], GH->PatL[lev], StateList, SynchList_cor, Symmetry);
|
||||
#endif
|
||||
@@ -6122,7 +6102,7 @@ void bssn_class::ProlongRestrict(int lev, int YN, bool BB)
|
||||
|
||||
#if (RPB == 0)
|
||||
#if (MIXOUTB == 0)
|
||||
Parallel::OutBdLow2Hi_cached(GH->PatL[lev - 1], GH->PatL[lev], SynchList_pre, SynchList_cor, Symmetry, sync_cache_outbd[lev]);
|
||||
Parallel::OutBdLow2Hi(GH->PatL[lev - 1], GH->PatL[lev], SynchList_pre, SynchList_cor, Symmetry);
|
||||
#elif (MIXOUTB == 1)
|
||||
Parallel::OutBdLow2Himix(GH->PatL[lev - 1], GH->PatL[lev], SynchList_pre, SynchList_cor, Symmetry);
|
||||
#endif
|
||||
@@ -6135,7 +6115,7 @@ void bssn_class::ProlongRestrict(int lev, int YN, bool BB)
|
||||
{
|
||||
#if (RPB == 0)
|
||||
#if (MIXOUTB == 0)
|
||||
Parallel::OutBdLow2Hi_cached(GH->PatL[lev - 1], GH->PatL[lev], StateList, SynchList_cor, Symmetry, sync_cache_outbd[lev]);
|
||||
Parallel::OutBdLow2Hi(GH->PatL[lev - 1], GH->PatL[lev], StateList, SynchList_cor, Symmetry);
|
||||
#elif (MIXOUTB == 1)
|
||||
Parallel::OutBdLow2Himix(GH->PatL[lev - 1], GH->PatL[lev], StateList, SynchList_cor, Symmetry);
|
||||
#endif
|
||||
@@ -6154,16 +6134,13 @@ void bssn_class::ProlongRestrict(int lev, int YN, bool BB)
|
||||
#else
|
||||
Parallel::Restrict_after(GH->PatL[lev - 1], GH->PatL[lev], SynchList_cor, StateList, Symmetry);
|
||||
#endif
|
||||
#if (RP_SYNC_COARSE_AFTER_RESTRICT == 1)
|
||||
Parallel::Sync_cached(GH->PatL[lev - 1], StateList, Symmetry, sync_cache_rp_coarse[lev]);
|
||||
#endif
|
||||
}
|
||||
|
||||
Parallel::Sync_cached(GH->PatL[lev], SynchList_cor, Symmetry, sync_cache_rp_fine[lev]);
|
||||
}
|
||||
}
|
||||
#undef MIXOUTB
|
||||
#undef RP_SYNC_COARSE_AFTER_RESTRICT
|
||||
|
||||
//================================================================================================
|
||||
|
||||
|
||||
@@ -130,8 +130,6 @@ public:
|
||||
Parallel::SyncCache *sync_cache_cor; // per-level cache for corrector sync
|
||||
Parallel::SyncCache *sync_cache_rp_coarse; // RestrictProlong sync on PatL[lev-1]
|
||||
Parallel::SyncCache *sync_cache_rp_fine; // RestrictProlong sync on PatL[lev]
|
||||
Parallel::SyncCache *sync_cache_restrict; // cached Restrict in RestrictProlong
|
||||
Parallel::SyncCache *sync_cache_outbd; // cached OutBdLow2Hi in RestrictProlong
|
||||
|
||||
monitor *ErrorMonitor, *Psi4Monitor, *BHMonitor, *MAPMonitor;
|
||||
monitor *ConVMonitor;
|
||||
|
||||
@@ -716,6 +716,7 @@ int f_compute_rhs_bssn(int *ex, double &T,
|
||||
|
||||
// 24ms //
|
||||
fdderivs(ex,Lap,fxx,fxy,fxz,fyy,fyz,fzz,X,Y,Z,SYM,SYM,SYM,Symmetry,Lev);
|
||||
fderivs(ex,chi,dtSfx_rhs,dtSfy_rhs,dtSfz_rhs,X,Y,Z,SYM,SYM,SYM,Symmetry,Lev);
|
||||
|
||||
// 6ms //
|
||||
for (int i=0;i<all;i+=1) {
|
||||
@@ -1013,12 +1014,12 @@ int f_compute_rhs_bssn(int *ex, double &T,
|
||||
betaz_rhs[i] = FF * dtSfz[i];
|
||||
|
||||
reta[i] =
|
||||
gupxx[i] * chix[i] * chix[i]
|
||||
+ gupyy[i] * chiy[i] * chiy[i]
|
||||
+ gupzz[i] * chiz[i] * chiz[i]
|
||||
+ TWO * ( gupxy[i] * chix[i] * chiy[i]
|
||||
+ gupxz[i] * chix[i] * chiz[i]
|
||||
+ gupyz[i] * chiy[i] * chiz[i] );
|
||||
gupxx[i] * dtSfx_rhs[i] * dtSfx_rhs[i]
|
||||
+ gupyy[i] * dtSfy_rhs[i] * dtSfy_rhs[i]
|
||||
+ gupzz[i] * dtSfz_rhs[i] * dtSfz_rhs[i]
|
||||
+ TWO * ( gupxy[i] * dtSfx_rhs[i] * dtSfy_rhs[i]
|
||||
+ gupxz[i] * dtSfx_rhs[i] * dtSfz_rhs[i]
|
||||
+ gupyz[i] * dtSfy_rhs[i] * dtSfz_rhs[i] );
|
||||
|
||||
#if (GAUGE == 2)
|
||||
reta[i] = 1.31 / 2.0 * sqrt( reta[i] / chin1[i] ) / pow( (ONE - sqrt(chin1[i])), 2.0 );
|
||||
@@ -1031,12 +1032,12 @@ int f_compute_rhs_bssn(int *ex, double &T,
|
||||
dtSfz_rhs[i] = Gamz_rhs[i] - reta[i] * dtSfz[i];
|
||||
#elif (GAUGE == 4 || GAUGE == 5)
|
||||
reta[i] =
|
||||
gupxx[i] * chix[i] * chix[i]
|
||||
+ gupyy[i] * chiy[i] * chiy[i]
|
||||
+ gupzz[i] * chiz[i] * chiz[i]
|
||||
+ TWO * ( gupxy[i] * chix[i] * chiy[i]
|
||||
+ gupxz[i] * chix[i] * chiz[i]
|
||||
+ gupyz[i] * chiy[i] * chiz[i] );
|
||||
gupxx[i] * dtSfx_rhs[i] * dtSfx_rhs[i]
|
||||
+ gupyy[i] * dtSfy_rhs[i] * dtSfy_rhs[i]
|
||||
+ gupzz[i] * dtSfz_rhs[i] * dtSfz_rhs[i]
|
||||
+ TWO * ( gupxy[i] * dtSfx_rhs[i] * dtSfy_rhs[i]
|
||||
+ gupxz[i] * dtSfx_rhs[i] * dtSfz_rhs[i]
|
||||
+ gupyz[i] * dtSfy_rhs[i] * dtSfz_rhs[i] );
|
||||
|
||||
#if (GAUGE == 4)
|
||||
reta[i] = 1.31 / 2.0 * sqrt( reta[i] / chin1[i] ) / pow( (ONE - sqrt(chin1[i])), 2.0 );
|
||||
@@ -1138,6 +1139,7 @@ int f_compute_rhs_bssn(int *ex, double &T,
|
||||
fderivs(ex,Ayy,gyyx,gyyy,gyyz,X,Y,Z,SYM ,SYM ,SYM ,Symmetry,0);
|
||||
fderivs(ex,Ayz,gyzx,gyzy,gyzz,X,Y,Z,SYM ,ANTI,ANTI,Symmetry,0);
|
||||
fderivs(ex,Azz,gzzx,gzzy,gzzz,X,Y,Z,SYM ,SYM ,SYM ,Symmetry,0);
|
||||
}
|
||||
// 7ms //
|
||||
for (int i=0;i<all;i+=1) {
|
||||
gxxx[i] = gxxx[i] - ( Gamxxx[i] * Axx[i] + Gamyxx[i] * Axy[i] + Gamzxx[i] * Axz[i]
|
||||
@@ -1191,7 +1193,6 @@ int f_compute_rhs_bssn(int *ex, double &T,
|
||||
movy_Res[i] = movy_Res[i] - F2o3*Ky[i] - F8*PI*Sy[i];
|
||||
movz_Res[i] = movz_Res[i] - F2o3*Kz[i] - F8*PI*Sz[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1513,7 +1513,6 @@
|
||||
real*8,dimension(-1:ex(1),-1:ex(2),-1:ex(3)) :: fh
|
||||
real*8, dimension(3) :: SoA
|
||||
integer :: imin,jmin,kmin,imax,jmax,kmax,i,j,k
|
||||
integer :: i_core_min,i_core_max,j_core_min,j_core_max,k_core_min,k_core_max
|
||||
real*8 :: Sdxdx,Sdydy,Sdzdz,Fdxdx,Fdydy,Fdzdz
|
||||
real*8 :: Sdxdy,Sdxdz,Sdydz,Fdxdy,Fdxdz,Fdydz
|
||||
integer, parameter :: NO_SYMM = 0, EQ_SYMM = 1, OCTANT = 2
|
||||
@@ -1566,47 +1565,9 @@
|
||||
fxz = ZEO
|
||||
fyz = ZEO
|
||||
|
||||
i_core_min = max(1, imin+2)
|
||||
i_core_max = min(ex(1), imax-2)
|
||||
j_core_min = max(1, jmin+2)
|
||||
j_core_max = min(ex(2), jmax-2)
|
||||
k_core_min = max(1, kmin+2)
|
||||
k_core_max = min(ex(3), kmax-2)
|
||||
|
||||
if(i_core_min <= i_core_max .and. j_core_min <= j_core_max .and. k_core_min <= k_core_max)then
|
||||
do k=k_core_min,k_core_max
|
||||
do j=j_core_min,j_core_max
|
||||
do i=i_core_min,i_core_max
|
||||
! interior points always use 4th-order stencils without branch checks
|
||||
fxx(i,j,k) = Fdxdx*(-fh(i-2,j,k)+F16*fh(i-1,j,k)-F30*fh(i,j,k) &
|
||||
-fh(i+2,j,k)+F16*fh(i+1,j,k) )
|
||||
fyy(i,j,k) = Fdydy*(-fh(i,j-2,k)+F16*fh(i,j-1,k)-F30*fh(i,j,k) &
|
||||
-fh(i,j+2,k)+F16*fh(i,j+1,k) )
|
||||
fzz(i,j,k) = Fdzdz*(-fh(i,j,k-2)+F16*fh(i,j,k-1)-F30*fh(i,j,k) &
|
||||
-fh(i,j,k+2)+F16*fh(i,j,k+1) )
|
||||
fxy(i,j,k) = Fdxdy*( (fh(i-2,j-2,k)-F8*fh(i-1,j-2,k)+F8*fh(i+1,j-2,k)-fh(i+2,j-2,k)) &
|
||||
-F8 *(fh(i-2,j-1,k)-F8*fh(i-1,j-1,k)+F8*fh(i+1,j-1,k)-fh(i+2,j-1,k)) &
|
||||
+F8 *(fh(i-2,j+1,k)-F8*fh(i-1,j+1,k)+F8*fh(i+1,j+1,k)-fh(i+2,j+1,k)) &
|
||||
- (fh(i-2,j+2,k)-F8*fh(i-1,j+2,k)+F8*fh(i+1,j+2,k)-fh(i+2,j+2,k)))
|
||||
fxz(i,j,k) = Fdxdz*( (fh(i-2,j,k-2)-F8*fh(i-1,j,k-2)+F8*fh(i+1,j,k-2)-fh(i+2,j,k-2)) &
|
||||
-F8 *(fh(i-2,j,k-1)-F8*fh(i-1,j,k-1)+F8*fh(i+1,j,k-1)-fh(i+2,j,k-1)) &
|
||||
+F8 *(fh(i-2,j,k+1)-F8*fh(i-1,j,k+1)+F8*fh(i+1,j,k+1)-fh(i+2,j,k+1)) &
|
||||
- (fh(i-2,j,k+2)-F8*fh(i-1,j,k+2)+F8*fh(i+1,j,k+2)-fh(i+2,j,k+2)))
|
||||
fyz(i,j,k) = Fdydz*( (fh(i,j-2,k-2)-F8*fh(i,j-1,k-2)+F8*fh(i,j+1,k-2)-fh(i,j+2,k-2)) &
|
||||
-F8 *(fh(i,j-2,k-1)-F8*fh(i,j-1,k-1)+F8*fh(i,j+1,k-1)-fh(i,j+2,k-1)) &
|
||||
+F8 *(fh(i,j-2,k+1)-F8*fh(i,j-1,k+1)+F8*fh(i,j+1,k+1)-fh(i,j+2,k+1)) &
|
||||
- (fh(i,j-2,k+2)-F8*fh(i,j-1,k+2)+F8*fh(i,j+1,k+2)-fh(i,j+2,k+2)))
|
||||
enddo
|
||||
enddo
|
||||
enddo
|
||||
endif
|
||||
|
||||
do k=1,ex(3)
|
||||
do j=1,ex(2)
|
||||
do i=1,ex(1)
|
||||
if(i>=i_core_min .and. i<=i_core_max .and. &
|
||||
j>=j_core_min .and. j<=j_core_max .and. &
|
||||
k>=k_core_min .and. k<=k_core_max) cycle
|
||||
!~~~~~~ fxx
|
||||
if(i+2 <= imax .and. i-2 >= imin)then
|
||||
!
|
||||
|
||||
@@ -141,26 +141,12 @@ void fdderivs(const int ex[3],
|
||||
const int j4_hi = ex2 - 3;
|
||||
const int k4_hi = ex3 - 3;
|
||||
|
||||
/*
|
||||
* Strategy A:
|
||||
* Avoid redundant work in overlap of 2nd/4th-order regions.
|
||||
* Only compute 2nd-order on shell points that are NOT overwritten by
|
||||
* the 4th-order pass.
|
||||
*/
|
||||
const int has4 = (i4_lo <= i4_hi && j4_lo <= j4_hi && k4_lo <= k4_hi);
|
||||
|
||||
if (i2_lo <= i2_hi && j2_lo <= j2_hi && k2_lo <= k2_hi) {
|
||||
for (int k0 = k2_lo; k0 <= k2_hi; ++k0) {
|
||||
const int kF = k0 + 1;
|
||||
for (int j0 = j2_lo; j0 <= j2_hi; ++j0) {
|
||||
const int jF = j0 + 1;
|
||||
for (int i0 = i2_lo; i0 <= i2_hi; ++i0) {
|
||||
if (has4 &&
|
||||
i0 >= i4_lo && i0 <= i4_hi &&
|
||||
j0 >= j4_lo && j0 <= j4_hi &&
|
||||
k0 >= k4_lo && k0 <= k4_hi) {
|
||||
continue;
|
||||
}
|
||||
const int iF = i0 + 1;
|
||||
const size_t p = idx_ex(i0, j0, k0, ex);
|
||||
|
||||
@@ -207,7 +193,7 @@ void fdderivs(const int ex[3],
|
||||
}
|
||||
}
|
||||
|
||||
if (has4) {
|
||||
if (i4_lo <= i4_hi && j4_lo <= j4_hi && k4_lo <= k4_hi) {
|
||||
for (int k0 = k4_lo; k0 <= k4_hi; ++k0) {
|
||||
const int kF = k0 + 1;
|
||||
for (int j0 = j4_lo; j0 <= j4_hi; ++j0) {
|
||||
|
||||
@@ -1956,13 +1956,11 @@
|
||||
|
||||
real*8,dimension(3) :: CD,FD
|
||||
real*8 :: tmp_yz(extc(1), 6) ! 存储整条 X 线上 6 个 Y 轴偏置的 Z 向插值结果
|
||||
real*8 :: tmp_xyz_line(-2:extc(1)) ! 包含 X 向 6 点模板访问所需下界
|
||||
real*8 :: tmp_xyz_line(extc(1)) ! 存储整条 X 线上完成 Y 向融合后的结果
|
||||
real*8 :: v1, v2, v3, v4, v5, v6
|
||||
integer :: ic, jc, kc, ix_offset,ix,iy,iz,jc_min,jc_max,ic_min,ic_max,kc_min,kc_max
|
||||
integer :: i_lo, i_hi, j_lo, j_hi, k_lo, k_hi
|
||||
logical :: need_full_symmetry
|
||||
integer :: ic, jc, kc, ix_offset,ix,iy,iz,jc_min,jc_max
|
||||
real*8 :: res_line
|
||||
real*8 :: tmp_z_slab(-2:extc(1), -2:extc(2)) ! 包含 Y/X 向模板访问所需下界
|
||||
real*8 :: tmp_z_slab(extc(1), extc(2)) ! 分配在 k 循环外
|
||||
if(wei.ne.3)then
|
||||
write(*,*)"prolongrestrict.f90::prolong3: this routine only surport 3 dimension"
|
||||
write(*,*)"dim = ",wei
|
||||
@@ -2065,41 +2063,24 @@
|
||||
endif
|
||||
enddo
|
||||
|
||||
ic_min = minval(cix(imino:imaxo))
|
||||
ic_max = maxval(cix(imino:imaxo))
|
||||
jc_min = minval(ciy(jmino:jmaxo))
|
||||
jc_max = maxval(ciy(jmino:jmaxo))
|
||||
kc_min = minval(ciz(kmino:kmaxo))
|
||||
kc_max = maxval(ciz(kmino:kmaxo))
|
||||
|
||||
maxcx = ic_max
|
||||
maxcy = jc_max
|
||||
maxcz = kc_max
|
||||
maxcx = maxval(cix(imino:imaxo))
|
||||
maxcy = maxval(ciy(jmino:jmaxo))
|
||||
maxcz = maxval(ciz(kmino:kmaxo))
|
||||
if(maxcx+3 > extc(1) .or. maxcy+3 > extc(2) .or. maxcz+3 > extc(3))then
|
||||
write(*,*)"error in prolong"
|
||||
return
|
||||
endif
|
||||
|
||||
i_lo = ic_min - 2
|
||||
i_hi = ic_max + 3
|
||||
j_lo = jc_min - 2
|
||||
j_hi = jc_max + 3
|
||||
k_lo = kc_min - 2
|
||||
k_hi = kc_max + 3
|
||||
need_full_symmetry = (i_lo < 1) .or. (j_lo < 1) .or. (k_lo < 1)
|
||||
if(need_full_symmetry)then
|
||||
call symmetry_bd(3,extc,func,funcc,SoA)
|
||||
else
|
||||
funcc(i_lo:i_hi,j_lo:j_hi,k_lo:k_hi) = func(i_lo:i_hi,j_lo:j_hi,k_lo:k_hi)
|
||||
endif
|
||||
|
||||
! 对每个 k(pz, kc 固定)预计算 Z 向插值的 2D 切片
|
||||
jc_min = minval(ciy(jmino:jmaxo))
|
||||
jc_max = maxval(ciy(jmino:jmaxo))
|
||||
|
||||
do k = kmino, kmaxo
|
||||
pz = piz(k); kc = ciz(k)
|
||||
! --- Pass 1: Z 方向,只算一次 ---
|
||||
do iy = jc_min-2, jc_max+3 ! 仅需的 iy 范围(对应 jc-2:jc+3)
|
||||
do ii = ic_min-2, ic_max+3 ! 仅需的 ii 范围(对应 cix-2:cix+3)
|
||||
do iy = jc_min-3, jc_max+3 ! 仅需的 iy 范围
|
||||
do ii = imini-3, imaxi+3 ! 仅需的 ii 范围
|
||||
tmp_z_slab(ii, iy) = sum(WC(:,pz) * funcc(ii, iy, kc-2:kc+3))
|
||||
end do
|
||||
end do
|
||||
@@ -2107,7 +2088,7 @@ do k = kmino, kmaxo
|
||||
do j = jmino, jmaxo
|
||||
py = piy(j); jc = ciy(j)
|
||||
! --- Pass 2: Y 方向 ---
|
||||
do ii = ic_min-2, ic_max+3
|
||||
do ii = imini-3, imaxi+3
|
||||
tmp_xyz_line(ii) = sum(WC(:,py) * tmp_z_slab(ii, jc-2:jc+3))
|
||||
end do
|
||||
! --- Pass 3: X 方向 ---
|
||||
@@ -2370,12 +2351,9 @@ end do
|
||||
|
||||
real*8,dimension(3) :: CD,FD
|
||||
|
||||
real*8 :: tmp_xz_plane(-1:extf(1), 6)
|
||||
real*8 :: tmp_x_line(-1:extf(1))
|
||||
real*8 :: tmp_xz_plane(extf(1), 6)
|
||||
real*8 :: tmp_x_line(extf(1))
|
||||
integer :: fi, fj, fk, ii, jj, kk
|
||||
integer :: fi_min, fi_max, ii_lo, ii_hi
|
||||
integer :: fj_min, fj_max, fk_min, fk_max, jj_lo, jj_hi, kk_lo, kk_hi
|
||||
logical :: need_full_symmetry
|
||||
|
||||
if(wei.ne.3)then
|
||||
write(*,*)"prolongrestrict.f90::restrict3: this routine only surport 3 dimension"
|
||||
@@ -2455,34 +2433,7 @@ end do
|
||||
stop
|
||||
endif
|
||||
|
||||
! 仅计算 X 向最终写回所需的窗口:
|
||||
! func(i,j,k) 只访问 tmp_x_line(fi-2:fi+3)
|
||||
fi_min = 2*(imino + lbc(1) - 1) - 1 - lbf(1) + 1
|
||||
fi_max = 2*(imaxo + lbc(1) - 1) - 1 - lbf(1) + 1
|
||||
fj_min = 2*(jmino + lbc(2) - 1) - 1 - lbf(2) + 1
|
||||
fj_max = 2*(jmaxo + lbc(2) - 1) - 1 - lbf(2) + 1
|
||||
fk_min = 2*(kmino + lbc(3) - 1) - 1 - lbf(3) + 1
|
||||
fk_max = 2*(kmaxo + lbc(3) - 1) - 1 - lbf(3) + 1
|
||||
ii_lo = fi_min - 2
|
||||
ii_hi = fi_max + 3
|
||||
jj_lo = fj_min - 2
|
||||
jj_hi = fj_max + 3
|
||||
kk_lo = fk_min - 2
|
||||
kk_hi = fk_max + 3
|
||||
if(ii_lo < -1 .or. ii_hi > extf(1) .or. &
|
||||
jj_lo < -1 .or. jj_hi > extf(2) .or. &
|
||||
kk_lo < -1 .or. kk_hi > extf(3))then
|
||||
write(*,*)"restrict3: invalid stencil window"
|
||||
write(*,*)"ii=",ii_lo,ii_hi," jj=",jj_lo,jj_hi," kk=",kk_lo,kk_hi
|
||||
write(*,*)"extf=",extf
|
||||
stop
|
||||
endif
|
||||
need_full_symmetry = (ii_lo < 1) .or. (jj_lo < 1) .or. (kk_lo < 1)
|
||||
if(need_full_symmetry)then
|
||||
call symmetry_bd(2,extf,funf,funff,SoA)
|
||||
else
|
||||
funff(ii_lo:ii_hi,jj_lo:jj_hi,kk_lo:kk_hi) = funf(ii_lo:ii_hi,jj_lo:jj_hi,kk_lo:kk_hi)
|
||||
endif
|
||||
|
||||
!~~~~~~> restriction start...
|
||||
do k = kmino, kmaxo
|
||||
@@ -2494,7 +2445,7 @@ do k = kmino, kmaxo
|
||||
! 优化点 1: 显式展开 Z 方向计算,减少循环开销
|
||||
! 确保 ii 循环是最内层且连续访问
|
||||
!DIR$ VECTOR ALWAYS
|
||||
do ii = ii_lo, ii_hi
|
||||
do ii = 1, extf(1)
|
||||
! 预计算当前 j 对应的 6 行在 Z 方向的压缩结果
|
||||
! 这里直接硬编码 jj 的偏移,彻底消除一层循环
|
||||
tmp_xz_plane(ii, 1) = C1*(funff(ii,fj-2,fk-2)+funff(ii,fj-2,fk+3)) + &
|
||||
@@ -2519,7 +2470,7 @@ do k = kmino, kmaxo
|
||||
|
||||
! 优化点 2: 同样向量化 Y 方向压缩
|
||||
!DIR$ VECTOR ALWAYS
|
||||
do ii = ii_lo, ii_hi
|
||||
do ii = 1, extf(1)
|
||||
tmp_x_line(ii) = C1*(tmp_xz_plane(ii, 1) + tmp_xz_plane(ii, 6)) + &
|
||||
C2*(tmp_xz_plane(ii, 2) + tmp_xz_plane(ii, 5)) + &
|
||||
C3*(tmp_xz_plane(ii, 3) + tmp_xz_plane(ii, 4))
|
||||
|
||||
Reference in New Issue
Block a user