working on DECL isosurface tools
This commit is contained in:
parent
39d7fa0430
commit
db1fe9e327
@ -33,38 +33,51 @@ Point Vertex::coords(unsigned long int idx){
|
|||||||
return P;
|
return P;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Halfedge::Halfedge(){
|
||||||
|
}
|
||||||
|
|
||||||
|
Halfedge::~Halfedge(){
|
||||||
|
|
||||||
|
}
|
||||||
unsigned long int Halfedge::v1(unsigned long int edge){
|
unsigned long int Halfedge::v1(unsigned long int edge){
|
||||||
return HalfEdge(0,edge);
|
return data(0,edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long int Halfedge::v2(unsigned long int edge){
|
unsigned long int Halfedge::v2(unsigned long int edge){
|
||||||
return HalfEdge(1,edge);
|
return data(1,edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long int Halfedge::face(unsigned long int edge){
|
unsigned long int Halfedge::face(unsigned long int edge){
|
||||||
return HalfEdge(2,edge);
|
return data(2,edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long int Halfedge::twin(unsigned long int edge){
|
unsigned long int Halfedge::twin(unsigned long int edge){
|
||||||
return HalfEdge(3,edge);
|
return data(3,edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long int Halfedge::prev(unsigned long int edge){
|
unsigned long int Halfedge::prev(unsigned long int edge){
|
||||||
return HalfEdge(4,edge);
|
return data(4,edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long int Halfedge::next(unsigned long int edge){
|
unsigned long int Halfedge::next(unsigned long int edge){
|
||||||
return HalfEdge(5,edge);
|
return data(5,edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL::DECL(){
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL::~DECL(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DECL::LocalIsosurface(const DoubleArray A, double value, int i, int j, int k){
|
void DECL::LocalIsosurface(const DoubleArray A, double value, int i, int j, int k){
|
||||||
Point P,Q;
|
Point P,Q;
|
||||||
Point PlaceHolder;
|
Point PlaceHolder;
|
||||||
double temp;
|
|
||||||
Point C0,C1,C2,C3,C4,C5,C6,C7;
|
Point C0,C1,C2,C3,C4,C5,C6,C7;
|
||||||
|
|
||||||
int TriangleCount;
|
int TriangleCount;
|
||||||
int NewVertexCount;
|
int NewVertexCount;
|
||||||
int CubeIndex;
|
int CubeIndex;
|
||||||
int nTris, nVert;
|
int nTris, nVert;
|
||||||
|
|
||||||
@ -78,10 +91,6 @@ void DECL::LocalIsosurface(const DoubleArray A, double value, int i, int j, int
|
|||||||
// Values from array 'A' at the cube corners
|
// Values from array 'A' at the cube corners
|
||||||
double CubeValues[8];
|
double CubeValues[8];
|
||||||
|
|
||||||
int Nx = A.size(0);
|
|
||||||
int Ny = A.size(1);
|
|
||||||
int Nz = A.size(2);
|
|
||||||
|
|
||||||
// Points corresponding to cube corners
|
// Points corresponding to cube corners
|
||||||
C0.x = 0.0; C0.y = 0.0; C0.z = 0.0;
|
C0.x = 0.0; C0.y = 0.0; C0.z = 0.0;
|
||||||
C1.x = 1.0; C1.y = 0.0; C1.z = 0.0;
|
C1.x = 1.0; C1.y = 0.0; C1.z = 0.0;
|
||||||
@ -92,188 +101,186 @@ void DECL::LocalIsosurface(const DoubleArray A, double value, int i, int j, int
|
|||||||
C6.x = 1.0; C6.y = 1.0; C6.z = 1.0;
|
C6.x = 1.0; C6.y = 1.0; C6.z = 1.0;
|
||||||
C7.x = 0.0; C7.y = 1.0; C7.z = 1.0;
|
C7.x = 0.0; C7.y = 1.0; C7.z = 1.0;
|
||||||
|
|
||||||
CubeValues[0] = A(i,j,k) - value;
|
CubeValues[0] = A(i,j,k) - value;
|
||||||
CubeValues[1] = A(i+1,j,k) - value;
|
CubeValues[1] = A(i+1,j,k) - value;
|
||||||
CubeValues[2] = A(i+1,j+1,k) - value;
|
CubeValues[2] = A(i+1,j+1,k) - value;
|
||||||
CubeValues[3] = A(i,j+1,k) - value;
|
CubeValues[3] = A(i,j+1,k) - value;
|
||||||
CubeValues[4] = A(i,j,k+1) - value;
|
CubeValues[4] = A(i,j,k+1) - value;
|
||||||
CubeValues[5] = A(i+1,j,k+1) - value;
|
CubeValues[5] = A(i+1,j,k+1) - value;
|
||||||
CubeValues[6] = A(i+1,j+1,k+1) - value;
|
CubeValues[6] = A(i+1,j+1,k+1) - value;
|
||||||
CubeValues[7] = A(i,j+1,k+1) -value;
|
CubeValues[7] = A(i,j+1,k+1) -value;
|
||||||
|
|
||||||
//Determine the index into the edge table which
|
//Determine the index into the edge table which
|
||||||
//tells us which vertices are inside of the surface
|
//tells us which vertices are inside of the surface
|
||||||
CubeIndex = 0;
|
CubeIndex = 0;
|
||||||
if (CubeValues[0] < 0.0f) CubeIndex |= 1;
|
if (CubeValues[0] < 0.0f) CubeIndex |= 1;
|
||||||
if (CubeValues[1] < 0.0f) CubeIndex |= 2;
|
if (CubeValues[1] < 0.0f) CubeIndex |= 2;
|
||||||
if (CubeValues[2] < 0.0f) CubeIndex |= 4;
|
if (CubeValues[2] < 0.0f) CubeIndex |= 4;
|
||||||
if (CubeValues[3] < 0.0f) CubeIndex |= 8;
|
if (CubeValues[3] < 0.0f) CubeIndex |= 8;
|
||||||
if (CubeValues[4] < 0.0f) CubeIndex |= 16;
|
if (CubeValues[4] < 0.0f) CubeIndex |= 16;
|
||||||
if (CubeValues[5] < 0.0f) CubeIndex |= 32;
|
if (CubeValues[5] < 0.0f) CubeIndex |= 32;
|
||||||
if (CubeValues[6] < 0.0f) CubeIndex |= 64;
|
if (CubeValues[6] < 0.0f) CubeIndex |= 64;
|
||||||
if (CubeValues[7] < 0.0f) CubeIndex |= 128;
|
if (CubeValues[7] < 0.0f) CubeIndex |= 128;
|
||||||
|
|
||||||
//Find the vertices where the surface intersects the cube
|
//Find the vertices where the surface intersects the cube
|
||||||
if (edgeTable[CubeIndex] & 1){
|
if (edgeTable[CubeIndex] & 1){
|
||||||
P = VertexInterp(C0,C1,CubeValues[0],CubeValues[1]);
|
P = VertexInterp(C0,C1,CubeValues[0],CubeValues[1]);
|
||||||
VertexList[0] = P;
|
VertexList[0] = P;
|
||||||
Q = C0;
|
Q = C0;
|
||||||
}
|
}
|
||||||
if (edgeTable[CubeIndex] & 2){
|
if (edgeTable[CubeIndex] & 2){
|
||||||
P = VertexInterp(C1,C2,CubeValues[1],CubeValues[2]);
|
P = VertexInterp(C1,C2,CubeValues[1],CubeValues[2]);
|
||||||
VertexList[1] = P;
|
VertexList[1] = P;
|
||||||
Q = C1;
|
Q = C1;
|
||||||
}
|
}
|
||||||
if (edgeTable[CubeIndex] & 4){
|
if (edgeTable[CubeIndex] & 4){
|
||||||
P = VertexInterp(C2,C3,CubeValues[2],CubeValues[3]);
|
P = VertexInterp(C2,C3,CubeValues[2],CubeValues[3]);
|
||||||
VertexList[2] = P;
|
VertexList[2] = P;
|
||||||
Q = C2;
|
Q = C2;
|
||||||
}
|
}
|
||||||
if (edgeTable[CubeIndex] & 8){
|
if (edgeTable[CubeIndex] & 8){
|
||||||
P = VertexInterp(C3,C0,CubeValues[3],CubeValues[0]);
|
P = VertexInterp(C3,C0,CubeValues[3],CubeValues[0]);
|
||||||
VertexList[3] = P;
|
VertexList[3] = P;
|
||||||
Q = C3;
|
Q = C3;
|
||||||
}
|
}
|
||||||
if (edgeTable[CubeIndex] & 16){
|
if (edgeTable[CubeIndex] & 16){
|
||||||
P = VertexInterp(C4,C5,CubeValues[4],CubeValues[5]);
|
P = VertexInterp(C4,C5,CubeValues[4],CubeValues[5]);
|
||||||
VertexList[4] = P;
|
VertexList[4] = P;
|
||||||
Q = C4;
|
Q = C4;
|
||||||
}
|
}
|
||||||
if (edgeTable[CubeIndex] & 32){
|
if (edgeTable[CubeIndex] & 32){
|
||||||
P = VertexInterp(C5,C6,CubeValues[5],CubeValues[6]);
|
P = VertexInterp(C5,C6,CubeValues[5],CubeValues[6]);
|
||||||
VertexList[5] = P;
|
VertexList[5] = P;
|
||||||
Q = C5;
|
Q = C5;
|
||||||
}
|
}
|
||||||
if (edgeTable[CubeIndex] & 64){
|
if (edgeTable[CubeIndex] & 64){
|
||||||
P = VertexInterp(C6,C7,CubeValues[6],CubeValues[7]);
|
P = VertexInterp(C6,C7,CubeValues[6],CubeValues[7]);
|
||||||
VertexList[6] = P;
|
VertexList[6] = P;
|
||||||
Q = C6;
|
Q = C6;
|
||||||
}
|
}
|
||||||
if (edgeTable[CubeIndex] & 128){
|
if (edgeTable[CubeIndex] & 128){
|
||||||
P = VertexInterp(C7,C4,CubeValues[7],CubeValues[4]);
|
P = VertexInterp(C7,C4,CubeValues[7],CubeValues[4]);
|
||||||
VertexList[7] = P;
|
VertexList[7] = P;
|
||||||
Q = C7;
|
Q = C7;
|
||||||
}
|
}
|
||||||
if (edgeTable[CubeIndex] & 256){
|
if (edgeTable[CubeIndex] & 256){
|
||||||
P = VertexInterp(C0,C4,CubeValues[0],CubeValues[4]);
|
P = VertexInterp(C0,C4,CubeValues[0],CubeValues[4]);
|
||||||
VertexList[8] = P;
|
VertexList[8] = P;
|
||||||
Q = C0;
|
Q = C0;
|
||||||
}
|
}
|
||||||
if (edgeTable[CubeIndex] & 512){
|
if (edgeTable[CubeIndex] & 512){
|
||||||
P = VertexInterp(C1,C5,CubeValues[1],CubeValues[5]);
|
P = VertexInterp(C1,C5,CubeValues[1],CubeValues[5]);
|
||||||
VertexList[9] = P;
|
VertexList[9] = P;
|
||||||
Q = C1;
|
Q = C1;
|
||||||
}
|
}
|
||||||
if (edgeTable[CubeIndex] & 1024){
|
if (edgeTable[CubeIndex] & 1024){
|
||||||
P = VertexInterp(C2,C6,CubeValues[2],CubeValues[6]);
|
P = VertexInterp(C2,C6,CubeValues[2],CubeValues[6]);
|
||||||
VertexList[10] = P;
|
VertexList[10] = P;
|
||||||
Q = C2;
|
Q = C2;
|
||||||
}
|
}
|
||||||
if (edgeTable[CubeIndex] & 2048){
|
if (edgeTable[CubeIndex] & 2048){
|
||||||
P = VertexInterp(C3,C7,CubeValues[3],CubeValues[7]);
|
P = VertexInterp(C3,C7,CubeValues[3],CubeValues[7]);
|
||||||
VertexList[11] = P;
|
VertexList[11] = P;
|
||||||
Q = C3;
|
Q = C3;
|
||||||
}
|
}
|
||||||
|
|
||||||
NewVertexCount=0;
|
NewVertexCount=0;
|
||||||
for (int idx=0;idx<12;idx++)
|
for (int idx=0;idx<12;idx++)
|
||||||
LocalRemap[idx] = -1;
|
LocalRemap[idx] = -1;
|
||||||
|
|
||||||
for (int idx=0;triTable[CubeIndex][idx]!=-1;idx++)
|
for (int idx=0;triTable[CubeIndex][idx]!=-1;idx++)
|
||||||
{
|
{
|
||||||
if(LocalRemap[triTable[CubeIndex][idx]] == -1)
|
if(LocalRemap[triTable[CubeIndex][idx]] == -1)
|
||||||
{
|
{
|
||||||
NewVertexList[NewVertexCount] = VertexList[triTable[CubeIndex][idx]];
|
NewVertexList[NewVertexCount] = VertexList[triTable[CubeIndex][idx]];
|
||||||
LocalRemap[triTable[CubeIndex][idx]] = NewVertexCount;
|
LocalRemap[triTable[CubeIndex][idx]] = NewVertexCount;
|
||||||
NewVertexCount++;
|
NewVertexCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int idx=0;idx<NewVertexCount;idx++) {
|
for (int idx=0;idx<NewVertexCount;idx++) {
|
||||||
P = NewVertexList[idx];
|
P = NewVertexList[idx];
|
||||||
//P.x += i;
|
//P.x += i;
|
||||||
//P.y += j;
|
//P.y += j;
|
||||||
//P.z += k;
|
//P.z += k;
|
||||||
cellvertices(idx) = P;
|
cellvertices(idx) = P;
|
||||||
}
|
}
|
||||||
nVert = NewVertexCount;
|
nVert = NewVertexCount;
|
||||||
|
|
||||||
TriangleCount = 0;
|
TriangleCount = 0;
|
||||||
for (int idx=0;triTable[CubeIndex][idx]!=-1;idx+=3) {
|
for (int idx=0;triTable[CubeIndex][idx]!=-1;idx+=3) {
|
||||||
Triangles(0,TriangleCount) = LocalRemap[triTable[CubeIndex][idx+0]];
|
Triangles(0,TriangleCount) = LocalRemap[triTable[CubeIndex][idx+0]];
|
||||||
Triangles(1,TriangleCount) = LocalRemap[triTable[CubeIndex][idx+1]];
|
Triangles(1,TriangleCount) = LocalRemap[triTable[CubeIndex][idx+1]];
|
||||||
Triangles(2,TriangleCount) = LocalRemap[triTable[CubeIndex][idx+2]];
|
Triangles(2,TriangleCount) = LocalRemap[triTable[CubeIndex][idx+2]];
|
||||||
TriangleCount++;
|
TriangleCount++;
|
||||||
}
|
}
|
||||||
nTris = TriangleCount;
|
nTris = TriangleCount;
|
||||||
|
|
||||||
// Now add the local values to the DECL data structure
|
|
||||||
IntArray HalfEdge(6,nTris*3);
|
|
||||||
DoubleArray EdgeAngles(nTris*3);
|
|
||||||
int idx_edge=0;
|
|
||||||
for (int idx=0; idx<TriangleCount; idx++){
|
|
||||||
int V1 = Triangles(0,idx);
|
|
||||||
int V2 = Triangles(1,idx);
|
|
||||||
int V3 = Triangles(2,idx);
|
|
||||||
// first edge: V1->V2
|
|
||||||
HalfEdge(0,idx_edge) = V1; // first vertex
|
|
||||||
HalfEdge(1,idx_edge) = V2; // second vertex
|
|
||||||
HalfEdge(2,idx_edge) = idx; // triangle
|
|
||||||
HalfEdge(3,idx_edge) = -1; // twin
|
|
||||||
HalfEdge(4,idx_edge) = idx_edge+2; // previous edge
|
|
||||||
HalfEdge(5,idx_edge) = idx_edge+1; // next edge
|
|
||||||
idx_edge++;
|
|
||||||
// second edge: V2->V3
|
|
||||||
HalfEdge(0,idx_edge) = V2; // first vertex
|
|
||||||
HalfEdge(1,idx_edge) = V3; // second vertex
|
|
||||||
HalfEdge(2,idx_edge) = idx; // triangle
|
|
||||||
HalfEdge(3,idx_edge) = -1; // twin
|
|
||||||
HalfEdge(4,idx_edge) = idx_edge-1; // previous edge
|
|
||||||
HalfEdge(5,idx_edge) = idx_edge+1; // next edge
|
|
||||||
idx_edge++;
|
|
||||||
// third edge: V3->V1
|
|
||||||
HalfEdge(0,idx_edge) = V3; // first vertex
|
|
||||||
HalfEdge(1,idx_edge) = V1; // second vertex
|
|
||||||
HalfEdge(2,idx_edge) = idx; // triangle
|
|
||||||
HalfEdge(3,idx_edge) = -1; // twin
|
|
||||||
HalfEdge(4,idx_edge) = idx_edge-1; // previous edge
|
|
||||||
HalfEdge(5,idx_edge) = idx_edge-2; // next edge
|
|
||||||
idx_edge++;
|
|
||||||
}
|
|
||||||
int EdgeCount=idx_edge;
|
|
||||||
for (int idx=0; idx<EdgeCount; idx++){
|
|
||||||
int V1=HalfEdge(0,idx);
|
|
||||||
int V2=HalfEdge(1,idx);
|
|
||||||
// Find all the twins within the cube
|
|
||||||
for (int jdx=0; idx<EdgeCount; jdx++){
|
|
||||||
if (HalfEdge(1,jdx) == V1 && HalfEdge(0,jdx) == V2){
|
|
||||||
// this is the pair
|
|
||||||
HalfEdge(3,idx) = jdx;
|
|
||||||
HalfEdge(3,jdx) = idx;
|
|
||||||
}
|
|
||||||
if (HalfEdge(1,jdx) == V2 && HalfEdge(0,jdx) == V1 && !(idx==jdx)){
|
|
||||||
std::printf("WARNING: half edges with identical orientation! \n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Use "ghost" twins if edge is on a cube face
|
|
||||||
P = cellvertices(V1);
|
|
||||||
Q = cellvertices(V2);
|
|
||||||
if (P.x == 0.0 && Q.x == 0.0) HalfEdge(3,idx_edge) = -1; // ghost twin for x=0 face
|
|
||||||
if (P.x == 1.0 && Q.x == 1.0) HalfEdge(3,idx_edge) = -2; // ghost twin for x=1 face
|
|
||||||
if (P.y == 0.0 && Q.y == 0.0) HalfEdge(3,idx_edge) = -3; // ghost twin for y=0 face
|
|
||||||
if (P.y == 1.0 && Q.y == 1.0) HalfEdge(3,idx_edge) = -4; // ghost twin for y=1 face
|
|
||||||
if (P.z == 0.0 && Q.z == 0.0) HalfEdge(3,idx_edge) = -5; // ghost twin for z=0 face
|
|
||||||
if (P.z == 1.0 && Q.z == 1.0) HalfEdge(3,idx_edge) = -6; // ghost twin for z=1 face
|
|
||||||
}
|
|
||||||
// Map vertices to global coordinates
|
|
||||||
for (int idx=0;idx<NewVertexCount;idx++) {
|
|
||||||
P = cellvertices(idx);
|
|
||||||
P.x += i;
|
|
||||||
P.y += j;
|
|
||||||
P.z += k;
|
|
||||||
cellvertices(idx) = P;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Now add the local values to the DECL data structure
|
||||||
|
halfedge.data.resize(6,nTris*3);
|
||||||
|
int idx_edge=0;
|
||||||
|
for (int idx=0; idx<TriangleCount; idx++){
|
||||||
|
int V1 = Triangles(0,idx);
|
||||||
|
int V2 = Triangles(1,idx);
|
||||||
|
int V3 = Triangles(2,idx);
|
||||||
|
// first edge: V1->V2
|
||||||
|
halfedge.data(0,idx_edge) = V1; // first vertex
|
||||||
|
halfedge.data(1,idx_edge) = V2; // second vertex
|
||||||
|
halfedge.data(2,idx_edge) = idx; // triangle
|
||||||
|
halfedge.data(3,idx_edge) = -1; // twin
|
||||||
|
halfedge.data(4,idx_edge) = idx_edge+2; // previous edge
|
||||||
|
halfedge.data(5,idx_edge) = idx_edge+1; // next edge
|
||||||
|
idx_edge++;
|
||||||
|
// second edge: V2->V3
|
||||||
|
halfedge.data(0,idx_edge) = V2; // first vertex
|
||||||
|
halfedge.data(1,idx_edge) = V3; // second vertex
|
||||||
|
halfedge.data(2,idx_edge) = idx; // triangle
|
||||||
|
halfedge.data(3,idx_edge) = -1; // twin
|
||||||
|
halfedge.data(4,idx_edge) = idx_edge-1; // previous edge
|
||||||
|
halfedge.data(5,idx_edge) = idx_edge+1; // next edge
|
||||||
|
idx_edge++;
|
||||||
|
// third edge: V3->V1
|
||||||
|
halfedge.data(0,idx_edge) = V3; // first vertex
|
||||||
|
halfedge.data(1,idx_edge) = V1; // second vertex
|
||||||
|
halfedge.data(2,idx_edge) = idx; // triangle
|
||||||
|
halfedge.data(3,idx_edge) = -1; // twin
|
||||||
|
halfedge.data(4,idx_edge) = idx_edge-1; // previous edge
|
||||||
|
halfedge.data(5,idx_edge) = idx_edge-2; // next edge
|
||||||
|
idx_edge++;
|
||||||
|
}
|
||||||
|
int EdgeCount=idx_edge;
|
||||||
|
for (int idx=0; idx<EdgeCount; idx++){
|
||||||
|
int V1=halfedge.data(0,idx);
|
||||||
|
int V2=halfedge.data(1,idx);
|
||||||
|
// Find all the twins within the cube
|
||||||
|
for (int jdx=0; idx<EdgeCount; jdx++){
|
||||||
|
if (halfedge.data(1,jdx) == V1 && halfedge.data(0,jdx) == V2){
|
||||||
|
// this is the pair
|
||||||
|
halfedge.data(3,idx) = jdx;
|
||||||
|
halfedge.data(3,jdx) = idx;
|
||||||
|
}
|
||||||
|
if (halfedge.data(1,jdx) == V2 && halfedge.data(0,jdx) == V1 && !(idx==jdx)){
|
||||||
|
std::printf("WARNING: half edges with identical orientation! \n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Use "ghost" twins if edge is on a cube face
|
||||||
|
P = cellvertices(V1);
|
||||||
|
Q = cellvertices(V2);
|
||||||
|
if (P.x == 0.0 && Q.x == 0.0) halfedge.data(3,idx_edge) = -1; // ghost twin for x=0 face
|
||||||
|
if (P.x == 1.0 && Q.x == 1.0) halfedge.data(3,idx_edge) = -2; // ghost twin for x=1 face
|
||||||
|
if (P.y == 0.0 && Q.y == 0.0) halfedge.data(3,idx_edge) = -3; // ghost twin for y=0 face
|
||||||
|
if (P.y == 1.0 && Q.y == 1.0) halfedge.data(3,idx_edge) = -4; // ghost twin for y=1 face
|
||||||
|
if (P.z == 0.0 && Q.z == 0.0) halfedge.data(3,idx_edge) = -5; // ghost twin for z=0 face
|
||||||
|
if (P.z == 1.0 && Q.z == 1.0) halfedge.data(3,idx_edge) = -6; // ghost twin for z=1 face
|
||||||
|
}
|
||||||
|
// Map vertices to global coordinates
|
||||||
|
for (int idx=0;idx<NewVertexCount;idx++) {
|
||||||
|
P = cellvertices(idx);
|
||||||
|
P.x += i;
|
||||||
|
P.y += j;
|
||||||
|
P.z += k;
|
||||||
|
cellvertices(idx) = P;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Point DECL::TriNormal(int edge)
|
Point DECL::TriNormal(int edge)
|
||||||
@ -281,9 +288,15 @@ Point DECL::TriNormal(int edge)
|
|||||||
Point P,Q;
|
Point P,Q;
|
||||||
double ux,uy,uz,vx,vy,vz;
|
double ux,uy,uz,vx,vy,vz;
|
||||||
double nx,ny,nz,len;
|
double nx,ny,nz,len;
|
||||||
if (edge == -1) P.x = 1.0; P.y = 0.0; P.z = 0.0; // x cube face
|
if (edge == -1){
|
||||||
else if (edge == -2) P.x = 0.0; P.y = 1.0; P.z = 0.0; // y cube face
|
P.x = 1.0; P.y = 0.0; P.z = 0.0; // x cube face
|
||||||
else if (edge == -3) P.x = 0.0; P.y = 0.0; P.z = 1.0; // z cube face
|
}
|
||||||
|
else if (edge == -2){
|
||||||
|
P.x = 0.0; P.y = 1.0; P.z = 0.0; // y cube face
|
||||||
|
}
|
||||||
|
else if (edge == -3){
|
||||||
|
P.x = 0.0; P.y = 0.0; P.z = 1.0; // z cube face
|
||||||
|
}
|
||||||
else{
|
else{
|
||||||
// coordinates for first edge
|
// coordinates for first edge
|
||||||
P = vertex.coords(halfedge.v1(edge));
|
P = vertex.coords(halfedge.v1(edge));
|
||||||
@ -325,7 +338,7 @@ void Isosurface(DoubleArray &A, const double &v)
|
|||||||
Point C0,C1,C2,C3,C4,C5,C6,C7;
|
Point C0,C1,C2,C3,C4,C5,C6,C7;
|
||||||
|
|
||||||
int TriangleCount;
|
int TriangleCount;
|
||||||
int NewVertexCount;
|
int NewVertexCount;
|
||||||
int CubeIndex;
|
int CubeIndex;
|
||||||
int nTris, nVert;
|
int nTris, nVert;
|
||||||
|
|
||||||
|
@ -32,8 +32,8 @@ public:
|
|||||||
unsigned long int next(unsigned long int edge);
|
unsigned long int next(unsigned long int edge);
|
||||||
unsigned long int prev(unsigned long int edge);
|
unsigned long int prev(unsigned long int edge);
|
||||||
|
|
||||||
|
Array<unsigned long int> data;
|
||||||
private:
|
private:
|
||||||
Array<unsigned long int> HalfEdge;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// DECL
|
// DECL
|
||||||
@ -45,7 +45,7 @@ public:
|
|||||||
unsigned long int face();
|
unsigned long int face();
|
||||||
Vertex vertex;
|
Vertex vertex;
|
||||||
Halfedge halfedge;
|
Halfedge halfedge;
|
||||||
void AddCube(); // need a function to add new faces based on marching cubes surface
|
void LocalIsosurface(const DoubleArray A, double value, int i, int j, int k);
|
||||||
|
|
||||||
double origin(int edge);
|
double origin(int edge);
|
||||||
double EdgeAngle(int edge);
|
double EdgeAngle(int edge);
|
||||||
|
@ -16,23 +16,23 @@
|
|||||||
|
|
||||||
AnalysisType& operator |=(AnalysisType &lhs, AnalysisType rhs)
|
AnalysisType& operator |=(AnalysisType &lhs, AnalysisType rhs)
|
||||||
{
|
{
|
||||||
lhs = static_cast<AnalysisType>(
|
lhs = static_cast<AnalysisType>(
|
||||||
static_cast<std::underlying_type<AnalysisType>::type>(lhs) |
|
static_cast<std::underlying_type<AnalysisType>::type>(lhs) |
|
||||||
static_cast<std::underlying_type<AnalysisType>::type>(rhs)
|
static_cast<std::underlying_type<AnalysisType>::type>(rhs)
|
||||||
);
|
);
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
bool matches( AnalysisType x, AnalysisType y )
|
bool matches( AnalysisType x, AnalysisType y )
|
||||||
{
|
{
|
||||||
return static_cast<std::underlying_type<AnalysisType>::type>(x) &
|
return static_cast<std::underlying_type<AnalysisType>::type>(x) &
|
||||||
static_cast<std::underlying_type<AnalysisType>::type>(y) != 0;
|
static_cast<std::underlying_type<AnalysisType>::type>(y) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class TYPE>
|
template<class TYPE>
|
||||||
void DeleteArray( const TYPE *p )
|
void DeleteArray( const TYPE *p )
|
||||||
{
|
{
|
||||||
delete [] p;
|
delete [] p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -40,32 +40,32 @@ void DeleteArray( const TYPE *p )
|
|||||||
class WriteRestartWorkItem: public ThreadPool::WorkItemRet<void>
|
class WriteRestartWorkItem: public ThreadPool::WorkItemRet<void>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WriteRestartWorkItem( const char* filename_, std::shared_ptr<double> cphi_, std::shared_ptr<double> cfq_, int N_ ):
|
WriteRestartWorkItem( const char* filename_, std::shared_ptr<double> cphi_, std::shared_ptr<double> cfq_, int N_ ):
|
||||||
filename(filename_), cphi(cphi_), cfq(cfq_), N(N_) {}
|
filename(filename_), cphi(cphi_), cfq(cfq_), N(N_) {}
|
||||||
virtual void run() {
|
virtual void run() {
|
||||||
PROFILE_START("Save Checkpoint",1);
|
PROFILE_START("Save Checkpoint",1);
|
||||||
double value;
|
double value;
|
||||||
ofstream File(filename,ios::binary);
|
ofstream File(filename,ios::binary);
|
||||||
for (int n=0; n<N; n++){
|
for (int n=0; n<N; n++){
|
||||||
// Write the two density values
|
// Write the two density values
|
||||||
value = cphi.get()[n];
|
value = cphi.get()[n];
|
||||||
File.write((char*) &value, sizeof(value));
|
File.write((char*) &value, sizeof(value));
|
||||||
// Write the distributions
|
// Write the distributions
|
||||||
for (int q=0; q<19; q++){
|
for (int q=0; q<19; q++){
|
||||||
value = cfq.get()[q*N+n];
|
value = cfq.get()[q*N+n];
|
||||||
File.write((char*) &value, sizeof(value));
|
File.write((char*) &value, sizeof(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File.close();
|
File.close();
|
||||||
PROFILE_STOP("Save Checkpoint",1);
|
PROFILE_STOP("Save Checkpoint",1);
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
WriteRestartWorkItem();
|
WriteRestartWorkItem();
|
||||||
const char* filename;
|
const char* filename;
|
||||||
std::shared_ptr<double> cfq,cphi;
|
std::shared_ptr<double> cfq,cphi;
|
||||||
// const DoubleArray& phase;
|
// const DoubleArray& phase;
|
||||||
//const DoubleArray& dist;
|
//const DoubleArray& dist;
|
||||||
const int N;
|
const int N;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -74,78 +74,78 @@ static const std::string id_map_filename = "lbpm_id_map.txt";
|
|||||||
class BlobIdentificationWorkItem1: public ThreadPool::WorkItemRet<void>
|
class BlobIdentificationWorkItem1: public ThreadPool::WorkItemRet<void>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BlobIdentificationWorkItem1( int timestep_, int Nx_, int Ny_, int Nz_, const RankInfoStruct& rank_info_,
|
BlobIdentificationWorkItem1( int timestep_, int Nx_, int Ny_, int Nz_, const RankInfoStruct& rank_info_,
|
||||||
std::shared_ptr<const DoubleArray> phase_, const DoubleArray& dist_,
|
std::shared_ptr<const DoubleArray> phase_, const DoubleArray& dist_,
|
||||||
BlobIDstruct last_id_, BlobIDstruct new_index_, BlobIDstruct new_id_, BlobIDList new_list_, runAnalysis::commWrapper&& comm_ ):
|
BlobIDstruct last_id_, BlobIDstruct new_index_, BlobIDstruct new_id_, BlobIDList new_list_, runAnalysis::commWrapper&& comm_ ):
|
||||||
timestep(timestep_), Nx(Nx_), Ny(Ny_), Nz(Nz_), rank_info(rank_info_),
|
timestep(timestep_), Nx(Nx_), Ny(Ny_), Nz(Nz_), rank_info(rank_info_),
|
||||||
phase(phase_), dist(dist_), last_id(last_id_), new_index(new_index_), new_id(new_id_), new_list(new_list_), comm(std::move(comm_))
|
phase(phase_), dist(dist_), last_id(last_id_), new_index(new_index_), new_id(new_id_), new_list(new_list_), comm(std::move(comm_))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~BlobIdentificationWorkItem1() { }
|
~BlobIdentificationWorkItem1() { }
|
||||||
virtual void run() {
|
virtual void run() {
|
||||||
// Compute the global blob id and compare to the previous version
|
// Compute the global blob id and compare to the previous version
|
||||||
PROFILE_START("Identify blobs",1);
|
PROFILE_START("Identify blobs",1);
|
||||||
double vF = 0.0;
|
double vF = 0.0;
|
||||||
double vS = -1.0; // one voxel buffer region around solid
|
double vS = -1.0; // one voxel buffer region around solid
|
||||||
IntArray& ids = new_index->second;
|
IntArray& ids = new_index->second;
|
||||||
new_index->first = ComputeGlobalBlobIDs(Nx-2,Ny-2,Nz-2,rank_info,*phase,dist,vF,vS,ids,comm.comm);
|
new_index->first = ComputeGlobalBlobIDs(Nx-2,Ny-2,Nz-2,rank_info,*phase,dist,vF,vS,ids,comm.comm);
|
||||||
PROFILE_STOP("Identify blobs",1);
|
PROFILE_STOP("Identify blobs",1);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
BlobIdentificationWorkItem1();
|
BlobIdentificationWorkItem1();
|
||||||
int timestep;
|
int timestep;
|
||||||
int Nx, Ny, Nz;
|
int Nx, Ny, Nz;
|
||||||
const RankInfoStruct& rank_info;
|
const RankInfoStruct& rank_info;
|
||||||
std::shared_ptr<const DoubleArray> phase;
|
std::shared_ptr<const DoubleArray> phase;
|
||||||
const DoubleArray& dist;
|
const DoubleArray& dist;
|
||||||
BlobIDstruct last_id, new_index, new_id;
|
BlobIDstruct last_id, new_index, new_id;
|
||||||
BlobIDList new_list;
|
BlobIDList new_list;
|
||||||
runAnalysis::commWrapper comm;
|
runAnalysis::commWrapper comm;
|
||||||
};
|
};
|
||||||
class BlobIdentificationWorkItem2: public ThreadPool::WorkItemRet<void>
|
class BlobIdentificationWorkItem2: public ThreadPool::WorkItemRet<void>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BlobIdentificationWorkItem2( int timestep_, int Nx_, int Ny_, int Nz_, const RankInfoStruct& rank_info_,
|
BlobIdentificationWorkItem2( int timestep_, int Nx_, int Ny_, int Nz_, const RankInfoStruct& rank_info_,
|
||||||
std::shared_ptr<const DoubleArray> phase_, const DoubleArray& dist_,
|
std::shared_ptr<const DoubleArray> phase_, const DoubleArray& dist_,
|
||||||
BlobIDstruct last_id_, BlobIDstruct new_index_, BlobIDstruct new_id_, BlobIDList new_list_ , runAnalysis::commWrapper&& comm_ ):
|
BlobIDstruct last_id_, BlobIDstruct new_index_, BlobIDstruct new_id_, BlobIDList new_list_ , runAnalysis::commWrapper&& comm_ ):
|
||||||
timestep(timestep_), Nx(Nx_), Ny(Ny_), Nz(Nz_), rank_info(rank_info_),
|
timestep(timestep_), Nx(Nx_), Ny(Ny_), Nz(Nz_), rank_info(rank_info_),
|
||||||
phase(phase_), dist(dist_), last_id(last_id_), new_index(new_index_), new_id(new_id_), new_list(new_list_), comm(std::move(comm_))
|
phase(phase_), dist(dist_), last_id(last_id_), new_index(new_index_), new_id(new_id_), new_list(new_list_), comm(std::move(comm_))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~BlobIdentificationWorkItem2() { }
|
~BlobIdentificationWorkItem2() { }
|
||||||
virtual void run() {
|
virtual void run() {
|
||||||
// Compute the global blob id and compare to the previous version
|
// Compute the global blob id and compare to the previous version
|
||||||
PROFILE_START("Identify blobs maps",1);
|
PROFILE_START("Identify blobs maps",1);
|
||||||
const IntArray& ids = new_index->second;
|
const IntArray& ids = new_index->second;
|
||||||
static int max_id = -1;
|
static int max_id = -1;
|
||||||
new_id->first = new_index->first;
|
new_id->first = new_index->first;
|
||||||
new_id->second = new_index->second;
|
new_id->second = new_index->second;
|
||||||
if ( last_id.get()!=NULL ) {
|
if ( last_id.get()!=NULL ) {
|
||||||
// Compute the timestep-timestep map
|
// Compute the timestep-timestep map
|
||||||
const IntArray& old_ids = last_id->second;
|
const IntArray& old_ids = last_id->second;
|
||||||
ID_map_struct map = computeIDMap(Nx,Ny,Nz,old_ids,ids,comm.comm);
|
ID_map_struct map = computeIDMap(Nx,Ny,Nz,old_ids,ids,comm.comm);
|
||||||
// Renumber the current timestep's ids
|
// Renumber the current timestep's ids
|
||||||
getNewIDs(map,max_id,*new_list);
|
getNewIDs(map,max_id,*new_list);
|
||||||
renumberIDs(*new_list,new_id->second);
|
renumberIDs(*new_list,new_id->second);
|
||||||
writeIDMap(map,timestep,id_map_filename);
|
writeIDMap(map,timestep,id_map_filename);
|
||||||
} else {
|
} else {
|
||||||
max_id = -1;
|
max_id = -1;
|
||||||
ID_map_struct map(new_id->first);
|
ID_map_struct map(new_id->first);
|
||||||
getNewIDs(map,max_id,*new_list);
|
getNewIDs(map,max_id,*new_list);
|
||||||
writeIDMap(map,timestep,id_map_filename);
|
writeIDMap(map,timestep,id_map_filename);
|
||||||
}
|
}
|
||||||
PROFILE_STOP("Identify blobs maps",1);
|
PROFILE_STOP("Identify blobs maps",1);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
BlobIdentificationWorkItem2();
|
BlobIdentificationWorkItem2();
|
||||||
int timestep;
|
int timestep;
|
||||||
int Nx, Ny, Nz;
|
int Nx, Ny, Nz;
|
||||||
const RankInfoStruct& rank_info;
|
const RankInfoStruct& rank_info;
|
||||||
std::shared_ptr<const DoubleArray> phase;
|
std::shared_ptr<const DoubleArray> phase;
|
||||||
const DoubleArray& dist;
|
const DoubleArray& dist;
|
||||||
BlobIDstruct last_id, new_index, new_id;
|
BlobIDstruct last_id, new_index, new_id;
|
||||||
BlobIDList new_list;
|
BlobIDList new_list;
|
||||||
runAnalysis::commWrapper comm;
|
runAnalysis::commWrapper comm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -153,36 +153,36 @@ private:
|
|||||||
class WriteVisWorkItem: public ThreadPool::WorkItemRet<void>
|
class WriteVisWorkItem: public ThreadPool::WorkItemRet<void>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WriteVisWorkItem( int timestep_, std::vector<IO::MeshDataStruct>& visData_,
|
WriteVisWorkItem( int timestep_, std::vector<IO::MeshDataStruct>& visData_,
|
||||||
TwoPhase& Avgerages_, fillHalo<double>& fillData_, runAnalysis::commWrapper&& comm_ ):
|
TwoPhase& Avgerages_, fillHalo<double>& fillData_, runAnalysis::commWrapper&& comm_ ):
|
||||||
timestep(timestep_), visData(visData_), Averages(Avgerages_), fillData(fillData_), comm(std::move(comm_))
|
timestep(timestep_), visData(visData_), Averages(Avgerages_), fillData(fillData_), comm(std::move(comm_))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~WriteVisWorkItem() { }
|
~WriteVisWorkItem() { }
|
||||||
virtual void run() {
|
virtual void run() {
|
||||||
PROFILE_START("Save Vis",1);
|
PROFILE_START("Save Vis",1);
|
||||||
ASSERT(visData[0].vars[0]->name=="phase");
|
ASSERT(visData[0].vars[0]->name=="phase");
|
||||||
ASSERT(visData[0].vars[1]->name=="Pressure");
|
ASSERT(visData[0].vars[1]->name=="Pressure");
|
||||||
ASSERT(visData[0].vars[2]->name=="SignDist");
|
ASSERT(visData[0].vars[2]->name=="SignDist");
|
||||||
ASSERT(visData[0].vars[3]->name=="BlobID");
|
ASSERT(visData[0].vars[3]->name=="BlobID");
|
||||||
Array<double>& PhaseData = visData[0].vars[0]->data;
|
Array<double>& PhaseData = visData[0].vars[0]->data;
|
||||||
Array<double>& PressData = visData[0].vars[1]->data;
|
Array<double>& PressData = visData[0].vars[1]->data;
|
||||||
Array<double>& SignData = visData[0].vars[2]->data;
|
Array<double>& SignData = visData[0].vars[2]->data;
|
||||||
Array<double>& BlobData = visData[0].vars[3]->data;
|
Array<double>& BlobData = visData[0].vars[3]->data;
|
||||||
fillData.copy(Averages.SDn,PhaseData);
|
fillData.copy(Averages.SDn,PhaseData);
|
||||||
fillData.copy(Averages.Press,PressData);
|
fillData.copy(Averages.Press,PressData);
|
||||||
fillData.copy(Averages.SDs,SignData);
|
fillData.copy(Averages.SDs,SignData);
|
||||||
fillData.copy(Averages.Label_NWP,BlobData);
|
fillData.copy(Averages.Label_NWP,BlobData);
|
||||||
IO::writeData( timestep, visData, comm.comm );
|
IO::writeData( timestep, visData, comm.comm );
|
||||||
PROFILE_STOP("Save Vis",1);
|
PROFILE_STOP("Save Vis",1);
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
WriteVisWorkItem();
|
WriteVisWorkItem();
|
||||||
int timestep;
|
int timestep;
|
||||||
std::vector<IO::MeshDataStruct>& visData;
|
std::vector<IO::MeshDataStruct>& visData;
|
||||||
TwoPhase& Averages;
|
TwoPhase& Averages;
|
||||||
fillHalo<double>& fillData;
|
fillHalo<double>& fillData;
|
||||||
runAnalysis::commWrapper comm;
|
runAnalysis::commWrapper comm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -191,46 +191,46 @@ private:
|
|||||||
class AnalysisWorkItem: public ThreadPool::WorkItemRet<void>
|
class AnalysisWorkItem: public ThreadPool::WorkItemRet<void>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AnalysisWorkItem( AnalysisType type_, int timestep_, TwoPhase& Averages_,
|
AnalysisWorkItem( AnalysisType type_, int timestep_, TwoPhase& Averages_,
|
||||||
BlobIDstruct ids, BlobIDList id_list_, double beta_ ):
|
BlobIDstruct ids, BlobIDList id_list_, double beta_ ):
|
||||||
type(type_), timestep(timestep_), Averages(Averages_),
|
type(type_), timestep(timestep_), Averages(Averages_),
|
||||||
blob_ids(ids), id_list(id_list_), beta(beta_) { }
|
blob_ids(ids), id_list(id_list_), beta(beta_) { }
|
||||||
~AnalysisWorkItem() { }
|
~AnalysisWorkItem() { }
|
||||||
virtual void run() {
|
virtual void run() {
|
||||||
Averages.NumberComponents_NWP = blob_ids->first;
|
Averages.NumberComponents_NWP = blob_ids->first;
|
||||||
Averages.Label_NWP = blob_ids->second;
|
Averages.Label_NWP = blob_ids->second;
|
||||||
Averages.Label_NWP_map = *id_list;
|
Averages.Label_NWP_map = *id_list;
|
||||||
Averages.NumberComponents_WP = 1;
|
Averages.NumberComponents_WP = 1;
|
||||||
Averages.Label_WP.fill(0.0);
|
Averages.Label_WP.fill(0.0);
|
||||||
if ( matches(type,AnalysisType::CopyPhaseIndicator) ) {
|
if ( matches(type,AnalysisType::CopyPhaseIndicator) ) {
|
||||||
// Averages.ColorToSignedDistance(beta,Averages.Phase,Averages.Phase_tplus);
|
// Averages.ColorToSignedDistance(beta,Averages.Phase,Averages.Phase_tplus);
|
||||||
}
|
}
|
||||||
if ( matches(type,AnalysisType::ComputeAverages) ) {
|
if ( matches(type,AnalysisType::ComputeAverages) ) {
|
||||||
PROFILE_START("Compute dist",1);
|
PROFILE_START("Compute dist",1);
|
||||||
Averages.Initialize();
|
Averages.Initialize();
|
||||||
Averages.ComputeDelPhi();
|
Averages.ComputeDelPhi();
|
||||||
Averages.ColorToSignedDistance(beta,Averages.Phase,Averages.SDn);
|
Averages.ColorToSignedDistance(beta,Averages.Phase,Averages.SDn);
|
||||||
Averages.ColorToSignedDistance(beta,Averages.Phase_tminus,Averages.Phase_tminus);
|
Averages.ColorToSignedDistance(beta,Averages.Phase_tminus,Averages.Phase_tminus);
|
||||||
Averages.ColorToSignedDistance(beta,Averages.Phase_tplus,Averages.Phase_tplus);
|
Averages.ColorToSignedDistance(beta,Averages.Phase_tplus,Averages.Phase_tplus);
|
||||||
Averages.UpdateMeshValues();
|
Averages.UpdateMeshValues();
|
||||||
Averages.ComputeLocal();
|
Averages.ComputeLocal();
|
||||||
Averages.Reduce();
|
Averages.Reduce();
|
||||||
Averages.PrintAll(timestep);
|
Averages.PrintAll(timestep);
|
||||||
Averages.Initialize();
|
Averages.Initialize();
|
||||||
Averages.ComponentAverages();
|
Averages.ComponentAverages();
|
||||||
Averages.SortBlobs();
|
Averages.SortBlobs();
|
||||||
Averages.PrintComponents(timestep);
|
Averages.PrintComponents(timestep);
|
||||||
PROFILE_STOP("Compute dist",1);
|
PROFILE_STOP("Compute dist",1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
AnalysisWorkItem();
|
AnalysisWorkItem();
|
||||||
AnalysisType type;
|
AnalysisType type;
|
||||||
int timestep;
|
int timestep;
|
||||||
TwoPhase& Averages;
|
TwoPhase& Averages;
|
||||||
BlobIDstruct blob_ids;
|
BlobIDstruct blob_ids;
|
||||||
BlobIDList id_list;
|
BlobIDList id_list;
|
||||||
double beta;
|
double beta;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -238,44 +238,44 @@ private:
|
|||||||
* MPI comm wrapper for use with analysis *
|
* MPI comm wrapper for use with analysis *
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
runAnalysis::commWrapper::commWrapper( int tag_, MPI_Comm comm_, runAnalysis* analysis_ ):
|
runAnalysis::commWrapper::commWrapper( int tag_, MPI_Comm comm_, runAnalysis* analysis_ ):
|
||||||
comm(comm_),
|
comm(comm_),
|
||||||
tag(tag_),
|
tag(tag_),
|
||||||
analysis(analysis_)
|
analysis(analysis_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
runAnalysis::commWrapper::commWrapper( commWrapper &&rhs ):
|
runAnalysis::commWrapper::commWrapper( commWrapper &&rhs ):
|
||||||
comm(rhs.comm),
|
comm(rhs.comm),
|
||||||
tag(rhs.tag),
|
tag(rhs.tag),
|
||||||
analysis(rhs.analysis)
|
analysis(rhs.analysis)
|
||||||
{
|
{
|
||||||
rhs.tag = -1;
|
rhs.tag = -1;
|
||||||
}
|
}
|
||||||
runAnalysis::commWrapper::~commWrapper()
|
runAnalysis::commWrapper::~commWrapper()
|
||||||
{
|
{
|
||||||
if ( tag == -1 )
|
if ( tag == -1 )
|
||||||
return;
|
return;
|
||||||
MPI_Barrier( comm );
|
MPI_Barrier( comm );
|
||||||
analysis->d_comm_used[tag] = false;
|
analysis->d_comm_used[tag] = false;
|
||||||
}
|
}
|
||||||
runAnalysis::commWrapper runAnalysis::getComm( )
|
runAnalysis::commWrapper runAnalysis::getComm( )
|
||||||
{
|
{
|
||||||
// Get a tag from root
|
// Get a tag from root
|
||||||
int tag = -1;
|
int tag = -1;
|
||||||
if ( d_rank == 0 ) {
|
if ( d_rank == 0 ) {
|
||||||
for (int i=0; i<1024; i++) {
|
for (int i=0; i<1024; i++) {
|
||||||
if ( !d_comm_used[i] ) {
|
if ( !d_comm_used[i] ) {
|
||||||
tag = i;
|
tag = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( tag == -1 )
|
if ( tag == -1 )
|
||||||
ERROR("Unable to get comm");
|
ERROR("Unable to get comm");
|
||||||
}
|
}
|
||||||
MPI_Bcast( &tag, 1, MPI_INT, 0, d_comm );
|
MPI_Bcast( &tag, 1, MPI_INT, 0, d_comm );
|
||||||
d_comm_used[tag] = true;
|
d_comm_used[tag] = true;
|
||||||
if ( d_comms[tag] == MPI_COMM_NULL )
|
if ( d_comms[tag] == MPI_COMM_NULL )
|
||||||
MPI_Comm_dup( MPI_COMM_WORLD, &d_comms[tag] );
|
MPI_Comm_dup( MPI_COMM_WORLD, &d_comms[tag] );
|
||||||
return commWrapper(tag,d_comms[tag],this);
|
return commWrapper(tag,d_comms[tag],this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -283,29 +283,29 @@ runAnalysis::commWrapper runAnalysis::getComm( )
|
|||||||
* Constructor/Destructors *
|
* Constructor/Destructors *
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
runAnalysis::runAnalysis( std::shared_ptr<Database> db,
|
runAnalysis::runAnalysis( std::shared_ptr<Database> db,
|
||||||
const RankInfoStruct& rank_info, std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm, std::shared_ptr <Domain> Dm,
|
const RankInfoStruct& rank_info, std::shared_ptr<ScaLBL_Communicator> ScaLBL_Comm, std::shared_ptr <Domain> Dm,
|
||||||
int Np, bool Regular, double beta, IntArray Map ):
|
int Np, bool Regular, double beta, IntArray Map ):
|
||||||
d_Np( Np ),
|
d_Np( Np ),
|
||||||
d_beta( beta ),
|
d_beta( beta ),
|
||||||
d_regular ( Regular),
|
d_regular ( Regular),
|
||||||
d_rank_info( rank_info ),
|
d_rank_info( rank_info ),
|
||||||
d_Map( Map ),
|
d_Map( Map ),
|
||||||
d_ScaLBL_Comm( ScaLBL_Comm),
|
d_ScaLBL_Comm( ScaLBL_Comm),
|
||||||
d_fillData(Dm->Comm,Dm->rank_info,{Dm->Nx-2,Dm->Ny-2,Dm->Nz-2},{1,1,1},0,1)
|
d_fillData(Dm->Comm,Dm->rank_info,{Dm->Nx-2,Dm->Ny-2,Dm->Nz-2},{1,1,1},0,1)
|
||||||
{
|
{
|
||||||
|
|
||||||
char rankString[20];
|
char rankString[20];
|
||||||
sprintf(rankString,"%05d",Dm->rank());
|
sprintf(rankString,"%05d",Dm->rank());
|
||||||
d_N[0] = Dm->Nx;
|
d_N[0] = Dm->Nx;
|
||||||
d_N[1] = Dm->Ny;
|
d_N[1] = Dm->Ny;
|
||||||
d_N[2] = Dm->Nz;
|
d_N[2] = Dm->Nz;
|
||||||
d_restart_interval = db->getScalar<int>( "restart_interval" );
|
d_restart_interval = db->getScalar<int>( "restart_interval" );
|
||||||
d_analysis_interval = db->getScalar<int>( "analysis_interval" );
|
d_analysis_interval = db->getScalar<int>( "analysis_interval" );
|
||||||
d_blobid_interval = db->getScalar<int>( "blobid_interval" );
|
d_blobid_interval = db->getScalar<int>( "blobid_interval" );
|
||||||
d_visualization_interval = db->getScalar<int>( "visualization_interval" );
|
d_visualization_interval = db->getScalar<int>( "visualization_interval" );
|
||||||
auto restart_file = db->getScalar<std::string>( "restart_file" );
|
auto restart_file = db->getScalar<std::string>( "restart_file" );
|
||||||
d_restartFile = restart_file + "." + rankString;
|
d_restartFile = restart_file + "." + rankString;
|
||||||
d_rank = MPI_WORLD_RANK();
|
d_rank = MPI_WORLD_RANK();
|
||||||
writeIDMap(ID_map_struct(),0,id_map_filename);
|
writeIDMap(ID_map_struct(),0,id_map_filename);
|
||||||
// Initialize IO for silo
|
// Initialize IO for silo
|
||||||
IO::initialize("","silo","false");
|
IO::initialize("","silo","false");
|
||||||
@ -337,41 +337,41 @@ runAnalysis::runAnalysis( std::shared_ptr<Database> db,
|
|||||||
BlobIDVar->dim = 1;
|
BlobIDVar->dim = 1;
|
||||||
BlobIDVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2);
|
BlobIDVar->data.resize(Dm->Nx-2,Dm->Ny-2,Dm->Nz-2);
|
||||||
d_meshData[0].vars.push_back(BlobIDVar);
|
d_meshData[0].vars.push_back(BlobIDVar);
|
||||||
// Initialize the comms
|
// Initialize the comms
|
||||||
MPI_Comm_dup(MPI_COMM_WORLD,&d_comm);
|
MPI_Comm_dup(MPI_COMM_WORLD,&d_comm);
|
||||||
for (int i=0; i<1024; i++) {
|
for (int i=0; i<1024; i++) {
|
||||||
d_comms[i] = MPI_COMM_NULL;
|
d_comms[i] = MPI_COMM_NULL;
|
||||||
d_comm_used[i] = false;
|
d_comm_used[i] = false;
|
||||||
}
|
}
|
||||||
// Initialize the threads
|
// Initialize the threads
|
||||||
int N_threads = db->getWithDefault<int>( "N_threads", 4 );
|
int N_threads = db->getWithDefault<int>( "N_threads", 4 );
|
||||||
auto method = db->getWithDefault<std::string>( "load_balance", "default" );
|
auto method = db->getWithDefault<std::string>( "load_balance", "default" );
|
||||||
createThreads( method, N_threads );
|
createThreads( method, N_threads );
|
||||||
}
|
}
|
||||||
runAnalysis::~runAnalysis( )
|
runAnalysis::~runAnalysis( )
|
||||||
{
|
{
|
||||||
// Finish processing analysis
|
// Finish processing analysis
|
||||||
finish();
|
finish();
|
||||||
// Clear internal data
|
// Clear internal data
|
||||||
MPI_Comm_free( &d_comm );
|
MPI_Comm_free( &d_comm );
|
||||||
for (int i=0; i<1024; i++) {
|
for (int i=0; i<1024; i++) {
|
||||||
if ( d_comms[i] != MPI_COMM_NULL )
|
if ( d_comms[i] != MPI_COMM_NULL )
|
||||||
MPI_Comm_free(&d_comms[i]);
|
MPI_Comm_free(&d_comms[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void runAnalysis::finish( )
|
void runAnalysis::finish( )
|
||||||
{
|
{
|
||||||
PROFILE_START("finish");
|
PROFILE_START("finish");
|
||||||
// Wait for the work items to finish
|
// Wait for the work items to finish
|
||||||
d_tpool.wait_pool_finished();
|
d_tpool.wait_pool_finished();
|
||||||
// Clear the wait ids
|
// Clear the wait ids
|
||||||
d_wait_blobID.reset();
|
d_wait_blobID.reset();
|
||||||
d_wait_analysis.reset();
|
d_wait_analysis.reset();
|
||||||
d_wait_vis.reset();
|
d_wait_vis.reset();
|
||||||
d_wait_restart.reset();
|
d_wait_restart.reset();
|
||||||
// Syncronize
|
// Syncronize
|
||||||
MPI_Barrier( d_comm );
|
MPI_Barrier( d_comm );
|
||||||
PROFILE_STOP("finish");
|
PROFILE_STOP("finish");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -380,50 +380,50 @@ void runAnalysis::finish( )
|
|||||||
******************************************************************/
|
******************************************************************/
|
||||||
void print( const std::vector<int>& ids )
|
void print( const std::vector<int>& ids )
|
||||||
{
|
{
|
||||||
if ( ids.empty() )
|
if ( ids.empty() )
|
||||||
return;
|
return;
|
||||||
printf("%i",ids[0]);
|
printf("%i",ids[0]);
|
||||||
for (size_t i=1; i<ids.size(); i++)
|
for (size_t i=1; i<ids.size(); i++)
|
||||||
printf(", %i",ids[i]);
|
printf(", %i",ids[i]);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
void runAnalysis::createThreads( const std::string& method, int N_threads )
|
void runAnalysis::createThreads( const std::string& method, int N_threads )
|
||||||
{
|
{
|
||||||
// Check if we are not using analysis threads
|
// Check if we are not using analysis threads
|
||||||
if ( method == "none" )
|
if ( method == "none" )
|
||||||
return;
|
return;
|
||||||
// Check if we have thread support
|
// Check if we have thread support
|
||||||
int thread_support;
|
int thread_support;
|
||||||
MPI_Query_thread( &thread_support );
|
MPI_Query_thread( &thread_support );
|
||||||
if ( thread_support < MPI_THREAD_MULTIPLE ) {
|
if ( thread_support < MPI_THREAD_MULTIPLE ) {
|
||||||
std::cerr << "Warning: Failed to start MPI with necessary thread support, thread support will be disabled" << std::endl;
|
std::cerr << "Warning: Failed to start MPI with necessary thread support, thread support will be disabled" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Create the threads
|
// Create the threads
|
||||||
const auto cores = d_tpool.getProcessAffinity();
|
const auto cores = d_tpool.getProcessAffinity();
|
||||||
if ( cores.empty() ) {
|
if ( cores.empty() ) {
|
||||||
// We were not able to get the cores for the process
|
// We were not able to get the cores for the process
|
||||||
d_tpool.setNumThreads( N_threads );
|
d_tpool.setNumThreads( N_threads );
|
||||||
} else if ( method == "default" ) {
|
} else if ( method == "default" ) {
|
||||||
// Create the given number of threads, but let the OS manage affinities
|
// Create the given number of threads, but let the OS manage affinities
|
||||||
d_tpool.setNumThreads( N_threads );
|
d_tpool.setNumThreads( N_threads );
|
||||||
} else if ( method == "independent" ) {
|
} else if ( method == "independent" ) {
|
||||||
int N = cores.size() - 1;
|
int N = cores.size() - 1;
|
||||||
d_tpool.setNumThreads( N );
|
d_tpool.setNumThreads( N );
|
||||||
d_tpool.setThreadAffinity( { cores[0] } );
|
d_tpool.setThreadAffinity( { cores[0] } );
|
||||||
for ( int i=0; i<N; i++)
|
for ( int i=0; i<N; i++)
|
||||||
d_tpool.setThreadAffinity( i, { cores[i+1] } );
|
d_tpool.setThreadAffinity( i, { cores[i+1] } );
|
||||||
}
|
}
|
||||||
// Print the current affinities
|
// Print the current affinities
|
||||||
if ( d_rank == 0 ) {
|
if ( d_rank == 0 ) {
|
||||||
printf("Affinities - rank 0:\n");
|
printf("Affinities - rank 0:\n");
|
||||||
printf("Main: ");
|
printf("Main: ");
|
||||||
print(d_tpool.getProcessAffinity());
|
print(d_tpool.getProcessAffinity());
|
||||||
for (int i=0; i<d_tpool.getNumThreads(); i++) {
|
for (int i=0; i<d_tpool.getNumThreads(); i++) {
|
||||||
printf("Thread %i: ",i+1);
|
printf("Thread %i: ",i+1);
|
||||||
print(d_tpool.getThreadAffinity(i));
|
print(d_tpool.getThreadAffinity(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -432,17 +432,17 @@ void runAnalysis::createThreads( const std::string& method, int N_threads )
|
|||||||
******************************************************************/
|
******************************************************************/
|
||||||
AnalysisType runAnalysis::computeAnalysisType( int timestep )
|
AnalysisType runAnalysis::computeAnalysisType( int timestep )
|
||||||
{
|
{
|
||||||
AnalysisType type = AnalysisType::AnalyzeNone;
|
AnalysisType type = AnalysisType::AnalyzeNone;
|
||||||
if ( timestep%d_analysis_interval + 8 == d_analysis_interval ) {
|
if ( timestep%d_analysis_interval + 8 == d_analysis_interval ) {
|
||||||
// Copy the phase indicator field for the earlier timestep
|
// Copy the phase indicator field for the earlier timestep
|
||||||
// printf("Copy phase indicator,timestep=%i\n",timestep);
|
// printf("Copy phase indicator,timestep=%i\n",timestep);
|
||||||
type |= AnalysisType::CopyPhaseIndicator;
|
type |= AnalysisType::CopyPhaseIndicator;
|
||||||
}
|
}
|
||||||
if ( timestep%d_blobid_interval == 0 ) {
|
if ( timestep%d_blobid_interval == 0 ) {
|
||||||
// Identify blobs and update global ids in time
|
// Identify blobs and update global ids in time
|
||||||
type |= AnalysisType::IdentifyBlobs;
|
type |= AnalysisType::IdentifyBlobs;
|
||||||
}
|
}
|
||||||
/*#ifdef USE_CUDA
|
/*#ifdef USE_CUDA
|
||||||
if ( tpool.getQueueSize()<=3 && tpool.getNumThreads()>0 && timestep%50==0 ) {
|
if ( tpool.getQueueSize()<=3 && tpool.getNumThreads()>0 && timestep%50==0 ) {
|
||||||
// Keep a few blob identifications queued up to keep the processors busy,
|
// Keep a few blob identifications queued up to keep the processors busy,
|
||||||
// allowing us to track the blobs as fast as possible
|
// allowing us to track the blobs as fast as possible
|
||||||
@ -450,28 +450,28 @@ AnalysisType runAnalysis::computeAnalysisType( int timestep )
|
|||||||
type |= AnalysisType::IdentifyBlobs;
|
type |= AnalysisType::IdentifyBlobs;
|
||||||
}
|
}
|
||||||
#endif */
|
#endif */
|
||||||
if ( timestep%d_analysis_interval + 4 == d_analysis_interval ) {
|
if ( timestep%d_analysis_interval + 4 == d_analysis_interval ) {
|
||||||
// Copy the averages to the CPU (and identify blobs)
|
// Copy the averages to the CPU (and identify blobs)
|
||||||
//printf("Copy sim state, timestep=%i \n",timestep);
|
//printf("Copy sim state, timestep=%i \n",timestep);
|
||||||
type |= AnalysisType::CopySimState;
|
type |= AnalysisType::CopySimState;
|
||||||
type |= AnalysisType::IdentifyBlobs;
|
type |= AnalysisType::IdentifyBlobs;
|
||||||
}
|
}
|
||||||
if ( timestep%d_analysis_interval == 0 ) {
|
if ( timestep%d_analysis_interval == 0 ) {
|
||||||
// Run the analysis
|
// Run the analysis
|
||||||
//printf("Compute averages, timestep=%i \n",timestep);
|
//printf("Compute averages, timestep=%i \n",timestep);
|
||||||
type |= AnalysisType::ComputeAverages;
|
type |= AnalysisType::ComputeAverages;
|
||||||
}
|
}
|
||||||
if (timestep%d_restart_interval == 0) {
|
if (timestep%d_restart_interval == 0) {
|
||||||
// Write the restart file
|
// Write the restart file
|
||||||
type |= AnalysisType::CreateRestart;
|
type |= AnalysisType::CreateRestart;
|
||||||
}
|
}
|
||||||
if (timestep%d_visualization_interval == 0) {
|
if (timestep%d_visualization_interval == 0) {
|
||||||
// Write the visualization data
|
// Write the visualization data
|
||||||
type |= AnalysisType::WriteVis;
|
type |= AnalysisType::WriteVis;
|
||||||
type |= AnalysisType::CopySimState;
|
type |= AnalysisType::CopySimState;
|
||||||
type |= AnalysisType::IdentifyBlobs;
|
type |= AnalysisType::IdentifyBlobs;
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -480,28 +480,28 @@ AnalysisType runAnalysis::computeAnalysisType( int timestep )
|
|||||||
* Run the analysis *
|
* Run the analysis *
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
void runAnalysis::run( int timestep, TwoPhase& Averages, const double *Phi,
|
void runAnalysis::run( int timestep, TwoPhase& Averages, const double *Phi,
|
||||||
double *Pressure, double *Velocity, double *fq, double *Den)
|
double *Pressure, double *Velocity, double *fq, double *Den)
|
||||||
{
|
{
|
||||||
int N = d_N[0]*d_N[1]*d_N[2];
|
int N = d_N[0]*d_N[1]*d_N[2];
|
||||||
|
|
||||||
// Check which analysis steps we need to perform
|
// Check which analysis steps we need to perform
|
||||||
auto type = computeAnalysisType( timestep );
|
auto type = computeAnalysisType( timestep );
|
||||||
if ( type == AnalysisType::AnalyzeNone )
|
if ( type == AnalysisType::AnalyzeNone )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Check how may queued items we have
|
// Check how may queued items we have
|
||||||
if ( d_tpool.N_queued() > 20 ) {
|
if ( d_tpool.N_queued() > 20 ) {
|
||||||
std::cerr << "Analysis queue is getting behind, waiting ...\n";
|
std::cerr << "Analysis queue is getting behind, waiting ...\n";
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
PROFILE_START("run");
|
PROFILE_START("run");
|
||||||
|
|
||||||
// Copy the appropriate variables to the host (so we can spawn new threads)
|
// Copy the appropriate variables to the host (so we can spawn new threads)
|
||||||
ScaLBL_DeviceBarrier();
|
ScaLBL_DeviceBarrier();
|
||||||
PROFILE_START("Copy data to host",1);
|
PROFILE_START("Copy data to host",1);
|
||||||
std::shared_ptr<DoubleArray> phase;
|
std::shared_ptr<DoubleArray> phase;
|
||||||
/* if ( matches(type,AnalysisType::CopyPhaseIndicator) ||
|
/* if ( matches(type,AnalysisType::CopyPhaseIndicator) ||
|
||||||
matches(type,AnalysisType::ComputeAverages) ||
|
matches(type,AnalysisType::ComputeAverages) ||
|
||||||
matches(type,AnalysisType::CopySimState) ||
|
matches(type,AnalysisType::CopySimState) ||
|
||||||
matches(type,AnalysisType::IdentifyBlobs) )
|
matches(type,AnalysisType::IdentifyBlobs) )
|
||||||
@ -531,113 +531,113 @@ void runAnalysis::run( int timestep, TwoPhase& Averages, const double *Phi,
|
|||||||
}
|
}
|
||||||
delete [] TmpDat;
|
delete [] TmpDat;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
//if ( matches(type,AnalysisType::CopyPhaseIndicator) ) {
|
//if ( matches(type,AnalysisType::CopyPhaseIndicator) ) {
|
||||||
if ( timestep%d_analysis_interval + 8 == d_analysis_interval ) {
|
if ( timestep%d_analysis_interval + 8 == d_analysis_interval ) {
|
||||||
if (d_regular)
|
if (d_regular)
|
||||||
d_ScaLBL_Comm->RegularLayout(d_Map,Phi,Averages.Phase_tplus);
|
d_ScaLBL_Comm->RegularLayout(d_Map,Phi,Averages.Phase_tplus);
|
||||||
else
|
else
|
||||||
ScaLBL_CopyToHost(Averages.Phase_tplus.data(),Phi,N*sizeof(double));
|
ScaLBL_CopyToHost(Averages.Phase_tplus.data(),Phi,N*sizeof(double));
|
||||||
//memcpy(Averages.Phase_tplus.data(),phase->data(),N*sizeof(double));
|
//memcpy(Averages.Phase_tplus.data(),phase->data(),N*sizeof(double));
|
||||||
}
|
}
|
||||||
if ( timestep%d_analysis_interval == 0 ) {
|
if ( timestep%d_analysis_interval == 0 ) {
|
||||||
if (d_regular)
|
if (d_regular)
|
||||||
d_ScaLBL_Comm->RegularLayout(d_Map,Phi,Averages.Phase_tminus);
|
d_ScaLBL_Comm->RegularLayout(d_Map,Phi,Averages.Phase_tminus);
|
||||||
else
|
else
|
||||||
ScaLBL_CopyToHost(Averages.Phase_tminus.data(),Phi,N*sizeof(double));
|
ScaLBL_CopyToHost(Averages.Phase_tminus.data(),Phi,N*sizeof(double));
|
||||||
//memcpy(Averages.Phase_tminus.data(),phase->data(),N*sizeof(double));
|
//memcpy(Averages.Phase_tminus.data(),phase->data(),N*sizeof(double));
|
||||||
}
|
}
|
||||||
//if ( matches(type,AnalysisType::CopySimState) ) {
|
//if ( matches(type,AnalysisType::CopySimState) ) {
|
||||||
if ( timestep%d_analysis_interval + 4 == d_analysis_interval ) {
|
if ( timestep%d_analysis_interval + 4 == d_analysis_interval ) {
|
||||||
// Copy the members of Averages to the cpu (phase was copied above)
|
// Copy the members of Averages to the cpu (phase was copied above)
|
||||||
PROFILE_START("Copy-Pressure",1);
|
PROFILE_START("Copy-Pressure",1);
|
||||||
ScaLBL_D3Q19_Pressure(fq,Pressure,d_Np);
|
ScaLBL_D3Q19_Pressure(fq,Pressure,d_Np);
|
||||||
ScaLBL_D3Q19_Momentum(fq,Velocity,d_Np);
|
ScaLBL_D3Q19_Momentum(fq,Velocity,d_Np);
|
||||||
ScaLBL_DeviceBarrier();
|
ScaLBL_DeviceBarrier();
|
||||||
PROFILE_STOP("Copy-Pressure",1);
|
PROFILE_STOP("Copy-Pressure",1);
|
||||||
PROFILE_START("Copy-Wait",1);
|
PROFILE_START("Copy-Wait",1);
|
||||||
PROFILE_STOP("Copy-Wait",1);
|
PROFILE_STOP("Copy-Wait",1);
|
||||||
PROFILE_START("Copy-State",1);
|
PROFILE_START("Copy-State",1);
|
||||||
//memcpy(Averages.Phase.data(),phase->data(),N*sizeof(double));
|
//memcpy(Averages.Phase.data(),phase->data(),N*sizeof(double));
|
||||||
if (d_regular)
|
if (d_regular)
|
||||||
d_ScaLBL_Comm->RegularLayout(d_Map,Phi,Averages.Phase);
|
d_ScaLBL_Comm->RegularLayout(d_Map,Phi,Averages.Phase);
|
||||||
else
|
else
|
||||||
ScaLBL_CopyToHost(Averages.Phase.data(),Phi,N*sizeof(double));
|
ScaLBL_CopyToHost(Averages.Phase.data(),Phi,N*sizeof(double));
|
||||||
// copy other variables
|
// copy other variables
|
||||||
d_ScaLBL_Comm->RegularLayout(d_Map,Pressure,Averages.Press);
|
d_ScaLBL_Comm->RegularLayout(d_Map,Pressure,Averages.Press);
|
||||||
d_ScaLBL_Comm->RegularLayout(d_Map,&Velocity[0],Averages.Vel_x);
|
d_ScaLBL_Comm->RegularLayout(d_Map,&Velocity[0],Averages.Vel_x);
|
||||||
d_ScaLBL_Comm->RegularLayout(d_Map,&Velocity[d_Np],Averages.Vel_y);
|
d_ScaLBL_Comm->RegularLayout(d_Map,&Velocity[d_Np],Averages.Vel_y);
|
||||||
d_ScaLBL_Comm->RegularLayout(d_Map,&Velocity[2*d_Np],Averages.Vel_z);
|
d_ScaLBL_Comm->RegularLayout(d_Map,&Velocity[2*d_Np],Averages.Vel_z);
|
||||||
PROFILE_STOP("Copy-State",1);
|
PROFILE_STOP("Copy-State",1);
|
||||||
}
|
}
|
||||||
std::shared_ptr<double> cfq,cPhi;
|
std::shared_ptr<double> cfq,cPhi;
|
||||||
//if ( matches(type,AnalysisType::CreateRestart) ) {
|
//if ( matches(type,AnalysisType::CreateRestart) ) {
|
||||||
if (timestep%d_restart_interval==0){
|
if (timestep%d_restart_interval==0){
|
||||||
// Copy restart data to the CPU
|
// Copy restart data to the CPU
|
||||||
cPhi = std::shared_ptr<double>(new double[d_Np],DeleteArray<double>);
|
cPhi = std::shared_ptr<double>(new double[d_Np],DeleteArray<double>);
|
||||||
cfq = std::shared_ptr<double>(new double[19*d_Np],DeleteArray<double>);
|
cfq = std::shared_ptr<double>(new double[19*d_Np],DeleteArray<double>);
|
||||||
ScaLBL_CopyToHost(cfq.get(),fq,19*d_Np*sizeof(double));
|
ScaLBL_CopyToHost(cfq.get(),fq,19*d_Np*sizeof(double));
|
||||||
ScaLBL_CopyToHost(cPhi.get(),Phi,d_Np*sizeof(double));
|
ScaLBL_CopyToHost(cPhi.get(),Phi,d_Np*sizeof(double));
|
||||||
}
|
}
|
||||||
PROFILE_STOP("Copy data to host",1);
|
PROFILE_STOP("Copy data to host",1);
|
||||||
|
|
||||||
// Spawn threads to do blob identification work
|
// Spawn threads to do blob identification work
|
||||||
if ( matches(type,AnalysisType::IdentifyBlobs) ) {
|
if ( matches(type,AnalysisType::IdentifyBlobs) ) {
|
||||||
phase = std::shared_ptr<DoubleArray>(new DoubleArray(d_N[0],d_N[1],d_N[2]));
|
phase = std::shared_ptr<DoubleArray>(new DoubleArray(d_N[0],d_N[1],d_N[2]));
|
||||||
d_ScaLBL_Comm->RegularLayout(d_Map,Phi,*phase);
|
d_ScaLBL_Comm->RegularLayout(d_Map,Phi,*phase);
|
||||||
|
|
||||||
BlobIDstruct new_index(new std::pair<int,IntArray>(0,IntArray()));
|
BlobIDstruct new_index(new std::pair<int,IntArray>(0,IntArray()));
|
||||||
BlobIDstruct new_ids(new std::pair<int,IntArray>(0,IntArray()));
|
BlobIDstruct new_ids(new std::pair<int,IntArray>(0,IntArray()));
|
||||||
BlobIDList new_list(new std::vector<BlobIDType>());
|
BlobIDList new_list(new std::vector<BlobIDType>());
|
||||||
auto work1 = new BlobIdentificationWorkItem1(timestep,d_N[0],d_N[1],d_N[2],d_rank_info,
|
auto work1 = new BlobIdentificationWorkItem1(timestep,d_N[0],d_N[1],d_N[2],d_rank_info,
|
||||||
phase,Averages.SDs,d_last_ids,new_index,new_ids,new_list,getComm());
|
phase,Averages.SDs,d_last_ids,new_index,new_ids,new_list,getComm());
|
||||||
auto work2 = new BlobIdentificationWorkItem2(timestep,d_N[0],d_N[1],d_N[2],d_rank_info,
|
auto work2 = new BlobIdentificationWorkItem2(timestep,d_N[0],d_N[1],d_N[2],d_rank_info,
|
||||||
phase,Averages.SDs,d_last_ids,new_index,new_ids,new_list,getComm());
|
phase,Averages.SDs,d_last_ids,new_index,new_ids,new_list,getComm());
|
||||||
work1->add_dependency(d_wait_blobID);
|
work1->add_dependency(d_wait_blobID);
|
||||||
work2->add_dependency(d_tpool.add_work(work1));
|
work2->add_dependency(d_tpool.add_work(work1));
|
||||||
d_wait_blobID = d_tpool.add_work(work2);
|
d_wait_blobID = d_tpool.add_work(work2);
|
||||||
d_last_index = new_index;
|
d_last_index = new_index;
|
||||||
d_last_ids = new_ids;
|
d_last_ids = new_ids;
|
||||||
d_last_id_map = new_list;
|
d_last_id_map = new_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn threads to do the analysis work
|
// Spawn threads to do the analysis work
|
||||||
//if (timestep%d_restart_interval==0){
|
//if (timestep%d_restart_interval==0){
|
||||||
// if ( matches(type,AnalysisType::ComputeAverages) ) {
|
// if ( matches(type,AnalysisType::ComputeAverages) ) {
|
||||||
if ( timestep%d_analysis_interval == 0 ) {
|
if ( timestep%d_analysis_interval == 0 ) {
|
||||||
auto work = new AnalysisWorkItem(type,timestep,Averages,d_last_index,d_last_id_map,d_beta);
|
auto work = new AnalysisWorkItem(type,timestep,Averages,d_last_index,d_last_id_map,d_beta);
|
||||||
work->add_dependency(d_wait_blobID);
|
work->add_dependency(d_wait_blobID);
|
||||||
work->add_dependency(d_wait_analysis);
|
work->add_dependency(d_wait_analysis);
|
||||||
work->add_dependency(d_wait_vis); // Make sure we are done using analysis before modifying
|
work->add_dependency(d_wait_vis); // Make sure we are done using analysis before modifying
|
||||||
d_wait_analysis = d_tpool.add_work(work);
|
d_wait_analysis = d_tpool.add_work(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn a thread to write the restart file
|
// Spawn a thread to write the restart file
|
||||||
// if ( matches(type,AnalysisType::CreateRestart) ) {
|
// if ( matches(type,AnalysisType::CreateRestart) ) {
|
||||||
if (timestep%d_restart_interval==0){
|
if (timestep%d_restart_interval==0){
|
||||||
|
|
||||||
if (d_rank==0) {
|
if (d_rank==0) {
|
||||||
FILE *Rst = fopen("Restart.txt","w");
|
FILE *Rst = fopen("Restart.txt","w");
|
||||||
fprintf(Rst,"%i\n",timestep+4);
|
fprintf(Rst,"%i\n",timestep+4);
|
||||||
fclose(Rst);
|
fclose(Rst);
|
||||||
}
|
}
|
||||||
// Write the restart file (using a seperate thread)
|
// Write the restart file (using a seperate thread)
|
||||||
auto work = new WriteRestartWorkItem(d_restartFile.c_str(),cPhi,cfq,d_Np);
|
auto work = new WriteRestartWorkItem(d_restartFile.c_str(),cPhi,cfq,d_Np);
|
||||||
work->add_dependency(d_wait_restart);
|
work->add_dependency(d_wait_restart);
|
||||||
d_wait_restart = d_tpool.add_work(work);
|
d_wait_restart = d_tpool.add_work(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the results for visualization
|
// Save the results for visualization
|
||||||
// if ( matches(type,AnalysisType::CreateRestart) ) {
|
// if ( matches(type,AnalysisType::CreateRestart) ) {
|
||||||
if (timestep%d_restart_interval==0){
|
if (timestep%d_restart_interval==0){
|
||||||
// Write the vis files
|
// Write the vis files
|
||||||
auto work = new WriteVisWorkItem( timestep, d_meshData, Averages, d_fillData, getComm() );
|
auto work = new WriteVisWorkItem( timestep, d_meshData, Averages, d_fillData, getComm() );
|
||||||
work->add_dependency(d_wait_blobID);
|
work->add_dependency(d_wait_blobID);
|
||||||
work->add_dependency(d_wait_analysis);
|
work->add_dependency(d_wait_analysis);
|
||||||
work->add_dependency(d_wait_vis);
|
work->add_dependency(d_wait_vis);
|
||||||
d_wait_vis = d_tpool.add_work(work);
|
d_wait_vis = d_tpool.add_work(work);
|
||||||
}
|
}
|
||||||
PROFILE_STOP("run");
|
PROFILE_STOP("run");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user