netgen/libsrc/meshing/paralleltop.cpp

1250 lines
30 KiB
C++
Raw Normal View History

2009-01-26 00:37:14 +05:00
#ifdef PARALLEL
#include <meshing.hpp>
#include "paralleltop.hpp"
namespace netgen
{
2011-07-15 03:36:19 +06:00
static MPI_Group MPI_HIGHORDER_WORLD;
static MPI_Comm MPI_HIGHORDER_COMM;
void MyMPI_ExchangeTable (TABLE<int> & send_verts,
TABLE<int> & recv_verts, int tag,
MPI_Comm comm = MPI_COMM_WORLD)
{
int ntasks, rank;
MPI_Comm_size(comm, &ntasks);
MPI_Comm_rank(comm, &rank);
Array<MPI_Request> requests;
for (int dest = 0; dest < ntasks; dest++)
if (dest != rank)
requests.Append (MyMPI_ISend (send_verts[dest], dest, tag, comm));
for (int i = 0; i < ntasks-1; i++)
{
MPI_Status status;
MPI_Probe (MPI_ANY_SOURCE, tag, comm, &status);
int size, src = status.MPI_SOURCE;
MPI_Get_count (&status, MPI_INT, &size);
recv_verts.SetEntrySize (src, size, sizeof(int));
requests.Append (MyMPI_IRecv (recv_verts[src], src, tag, comm));
}
MPI_Waitall (requests.Size(), &requests[0], MPI_STATUS_IGNORE);
}
2009-01-26 00:37:14 +05:00
2011-07-04 18:29:02 +06:00
2009-01-26 00:37:14 +05:00
void ParallelMeshTopology :: Reset ()
{
*testout << "ParallelMeshTopology::Reset" << endl;
if ( ntasks == 1 ) return;
int nvold = nv;
ne = mesh.GetNE();
nv = mesh.GetNV();
nseg = mesh.GetNSeg();
nsurfel = mesh.GetNSE();
ned = mesh.GetTopology().GetNEdges();
nfa = mesh.GetTopology().GetNFaces();
loc2distedge.ChangeSize (ned);
for (int i = 0; i < ned; i++)
if (loc2distedge[i].Size() == 0)
loc2distedge.Add (i, -1); // will be the global nr
loc2distface.ChangeSize (nfa);
for (int i = 0; i < nfa; i++)
if (loc2distface[i].Size() == 0)
loc2distface.Add (i, -1); // will be the global nr
2011-02-15 21:22:05 +05:00
if ( nvold == nv ) return;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
SetNV(nv);
SetNE(ne);
}
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
ParallelMeshTopology :: ~ParallelMeshTopology ()
{
2011-07-15 03:36:19 +06:00
;
2011-02-15 21:22:05 +05:00
}
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
ParallelMeshTopology :: ParallelMeshTopology ( const netgen::Mesh & amesh )
: mesh(amesh)
{
2011-07-15 03:36:19 +06:00
ned = 0;
nfa = 0;
2011-02-15 21:22:05 +05:00
nv = 0;
ne = 0;
np = 0;
nseg = 0;
nsurfel = 0;
neglob = 0;
nvglob = 0;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
nparel = 0;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
coarseupdate = 0;
2011-07-15 03:36:19 +06:00
/*
2011-02-15 21:22:05 +05:00
isghostedge.SetSize(0);
isghostface.SetSize(0);
2011-07-15 03:36:19 +06:00
*/
// overlap = 0;
2011-02-15 21:22:05 +05:00
}
2009-01-26 00:37:14 +05:00
2011-07-15 03:36:19 +06:00
int ParallelMeshTopology :: Glob2Loc_Vert (int globnum)
2009-01-26 00:37:14 +05:00
{
for (int i = 1; i <= nv; i++)
if ( globnum == loc2distvert[i][0] )
return i;
return -1;
}
2011-02-15 21:22:05 +05:00
int ParallelMeshTopology :: Glob2Loc_VolEl (int globnum )
{
int locnum = -1;
for (int i = 0; i < ne; i++)
2011-07-15 03:36:19 +06:00
if ( globnum == loc2distel[i][0] )
locnum = i+1;
2011-02-15 21:22:05 +05:00
return locnum;
}
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
int ParallelMeshTopology :: Glob2Loc_SurfEl (int globnum )
2009-01-26 00:37:14 +05:00
{
int locnum = -1;
for (int i = 0; i < nsurfel; i++)
2011-07-15 03:36:19 +06:00
if ( globnum == loc2distsurfel[i][0] )
locnum = i+1;
2009-01-26 00:37:14 +05:00
return locnum;
}
2011-02-15 21:22:05 +05:00
int ParallelMeshTopology :: Glob2Loc_Segm (int globnum )
2009-01-26 00:37:14 +05:00
{
int locnum = -1;
for (int i = 0; i < nseg; i++)
2011-07-15 03:36:19 +06:00
if ( globnum == loc2distsegm[i][0] )
locnum = i+1;
2009-01-26 00:37:14 +05:00
return locnum;
}
void ParallelMeshTopology :: Print() const
{
2011-02-15 21:22:05 +05:00
(*testout) << endl << "TOPOLOGY FOR PARALLEL MESHES" << endl << endl;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
for ( int i = 1; i <= nv; i++ )
if ( IsExchangeVert (i) )
{
(*testout) << "exchange point " << i << ": global " << GetLoc2Glob_Vert(i) << endl;
for ( int dest = 0; dest < ntasks; dest ++)
if ( dest != id )
2009-01-26 00:37:14 +05:00
if ( GetDistantPNum( dest, i ) > 0 )
(*testout) << " p" << dest << ": " << GetDistantPNum ( dest, i ) << endl;
2011-02-15 21:22:05 +05:00
}
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
for ( int i = 1; i <= ned; i++ )
if ( IsExchangeEdge ( i ) )
{
int v1, v2;
mesh . GetTopology().GetEdgeVertices(i, v1, v2);
(*testout) << "exchange edge " << i << ": global vertices " << GetLoc2Glob_Vert(v1) << " "
<< GetLoc2Glob_Vert(v2) << endl;
for ( int dest = 0; dest < ntasks; dest++)
if ( GetDistantEdgeNum ( dest, i ) > 0 )
if ( dest != id )
2011-07-15 03:36:19 +06:00
(*testout) << " p" << dest << ": " << GetDistantEdgeNum ( dest, i ) << endl;
2011-02-15 21:22:05 +05:00
}
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
for ( int i = 1; i <= nfa; i++ )
if ( IsExchangeFace(i) )
{
Array<int> facevert;
mesh . GetTopology().GetFaceVertices(i, facevert);
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
(*testout) << "exchange face " << i << ": global vertices " ;
for ( int fi=0; fi < facevert.Size(); fi++)
(*testout) << GetLoc2Glob_Vert(facevert[fi]) << " ";
(*testout) << endl;
for ( int dest = 0; dest < ntasks; dest++)
if ( dest != id )
2009-01-26 00:37:14 +05:00
{
if ( GetDistantFaceNum ( dest, i ) >= 0 )
2011-02-15 21:22:05 +05:00
(*testout) << " p" << dest << ": " << GetDistantFaceNum ( dest, i ) << endl;
2009-01-26 00:37:14 +05:00
}
2011-02-15 21:22:05 +05:00
}
2009-01-26 00:37:14 +05:00
2011-07-15 03:36:19 +06:00
/*
2011-02-15 21:22:05 +05:00
for ( int i = 1; i < mesh.GetNE(); i++)
{
if ( !IsExchangeElement(i) ) continue;
Array<int> vert;
const Element & el = mesh.VolumeElement(i);
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
(*testout) << "parallel local element " << i << endl;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
(*testout) << "vertices " ;
for ( int j = 0; j < el.GetNV(); j++)
(*testout) << el.PNum(j+1) << " ";
(*testout) << "is ghost " << IsGhostEl(i) << endl;
(*testout) << endl;
}
2011-07-15 03:36:19 +06:00
*/
2009-01-26 00:37:14 +05:00
}
2011-02-15 21:22:05 +05:00
int ParallelMeshTopology :: GetDistantPNum ( int proc, int locpnum ) const
2009-01-26 00:37:14 +05:00
{
if ( proc == 0 )
return loc2distvert[locpnum][0];
for (int i = 1; i < loc2distvert[locpnum].Size(); i += 2)
if ( loc2distvert[locpnum][i] == proc )
return loc2distvert[locpnum][i+1];
return -1;
}
2011-02-15 21:22:05 +05:00
int ParallelMeshTopology :: GetDistantFaceNum ( int proc, int locfacenum ) const
2009-01-26 00:37:14 +05:00
{
if ( proc == 0 )
return loc2distface[locfacenum-1][0];
for ( int i = 1; i < loc2distface[locfacenum-1].Size(); i+=2 )
if ( loc2distface[locfacenum-1][i] == proc )
return loc2distface[locfacenum-1][i+1];
return -1;
}
2011-02-15 21:22:05 +05:00
int ParallelMeshTopology :: GetDistantEdgeNum ( int proc, int locedgenum ) const
2009-01-26 00:37:14 +05:00
{
if ( proc == 0 )
return loc2distedge[locedgenum-1][0];
for ( int i = 1; i < loc2distedge[locedgenum-1].Size(); i+=2 )
if ( loc2distedge[locedgenum-1][i] == proc )
return loc2distedge[locedgenum-1][i+1];
return -1;
}
2011-02-15 21:22:05 +05:00
int ParallelMeshTopology :: GetDistantElNum ( int proc, int locelnum ) const
2009-01-26 00:37:14 +05:00
{
if ( proc == 0 )
return loc2distel[locelnum-1][0];
for ( int i = 1; i < loc2distel[locelnum-1].Size(); i+=2 )
if ( loc2distel[locelnum-1][i] == proc )
return loc2distel[locelnum-1][i+1];
return -1;
}
// gibt anzahl an distant pnums zurueck
// * pnums entspricht Array<int[2] >
2011-02-15 21:22:05 +05:00
int ParallelMeshTopology :: GetDistantPNums ( int locpnum, int * distpnums ) const
2009-01-26 00:37:14 +05:00
{
distpnums[0] = 0;
distpnums[1] = loc2distvert[locpnum][0];
for ( int i = 1; i < loc2distvert[locpnum].Size(); i++ )
distpnums[i+1] = loc2distvert[locpnum][i];
2011-02-15 21:22:05 +05:00
int size = loc2distvert[locpnum].Size() / 2 + 1;
return size;
2009-01-26 00:37:14 +05:00
}
2011-02-15 21:22:05 +05:00
int ParallelMeshTopology :: GetDistantFaceNums ( int locfacenum, int * distfacenums ) const
2009-01-26 00:37:14 +05:00
{
distfacenums[0] = 0;
distfacenums[1] = loc2distface[locfacenum-1][0];
for ( int i = 1; i < loc2distface[locfacenum-1].Size(); i++ )
distfacenums[i+1] = loc2distface[locfacenum-1][i];
int size = loc2distface[locfacenum-1].Size() / 2 + 1;
return size;
}
2011-02-15 21:22:05 +05:00
int ParallelMeshTopology :: GetDistantEdgeNums ( int locedgenum, int * distedgenums ) const
2009-01-26 00:37:14 +05:00
{
distedgenums[0] = 0;
distedgenums[1] = loc2distedge[locedgenum-1][0];
for ( int i = 1; i < loc2distedge[locedgenum-1].Size(); i++ )
distedgenums[i+1] = loc2distedge[locedgenum-1][i];
int size = loc2distedge[locedgenum-1].Size() / 2 + 1;
return size;
}
2011-02-15 21:22:05 +05:00
int ParallelMeshTopology :: GetDistantElNums ( int locelnum, int * distelnums ) const
2009-01-26 00:37:14 +05:00
{
distelnums[0] = 0;
distelnums[1] = loc2distel[locelnum-1][0];
for ( int i = 1; i < loc2distel[locelnum-1].Size(); i++ )
distelnums[i+1] = loc2distel[locelnum-1][i];
int size = loc2distel[locelnum-1].Size() / 2 + 1;
return size;
}
void ParallelMeshTopology :: SetDistantFaceNum ( int dest, int locnum, int distnum )
{
if ( dest == 0 )
{
loc2distface[locnum-1][0] = distnum;
return;
}
for ( int i = 1; i < loc2distface[locnum-1].Size(); i+=2 )
if ( loc2distface[locnum-1][i] == dest )
{
loc2distface[locnum-1][i+1] = distnum;
return;
}
loc2distface.Add(locnum-1, dest);
loc2distface.Add(locnum-1, distnum);
}
void ParallelMeshTopology :: SetDistantPNum ( int dest, int locnum, int distnum )
{
if ( dest == 0 )
{
loc2distvert[locnum][0] = distnum; // HERE
return;
}
for ( int i = 1; i < loc2distvert[locnum].Size(); i+=2 )
if ( loc2distvert[locnum][i] == dest )
{
loc2distvert[locnum][i+1] = distnum;
return;
}
loc2distvert.Add (locnum, dest);
loc2distvert.Add (locnum, distnum);
}
void ParallelMeshTopology :: SetDistantEdgeNum ( int dest, int locnum, int distnum )
{
if ( dest == 0 )
{
loc2distedge[locnum-1][0] = distnum;
return;
}
for ( int i = 1; i < loc2distedge[locnum-1].Size(); i+=2 )
if ( loc2distedge[locnum-1][i] == dest )
{
loc2distedge[locnum-1][i+1] = distnum;
return;
}
loc2distedge.Add (locnum-1, dest);
loc2distedge.Add (locnum-1, distnum);
}
void ParallelMeshTopology :: SetDistantEl ( int dest, int locnum, int distnum )
{
if ( dest == 0 )
{
loc2distel[locnum-1][0] = distnum;
return;
}
for ( int i = 1; i < loc2distel[locnum-1].Size(); i+=2 )
if ( loc2distel[locnum-1][i] == dest )
{
loc2distel[locnum-1][i+1] = distnum;
return;
}
loc2distel.Add (locnum-1, dest);
loc2distel.Add (locnum-1, distnum);
}
void ParallelMeshTopology :: SetDistantSurfEl ( int dest, int locnum, int distnum )
{
2011-02-15 21:22:05 +05:00
if ( dest == 0 )
2009-01-26 00:37:14 +05:00
{
loc2distsurfel[locnum-1][0] = distnum;
return;
}
2011-02-15 21:22:05 +05:00
for ( int i = 1; i < loc2distsurfel[locnum-1].Size(); i+=2 )
2009-01-26 00:37:14 +05:00
if ( loc2distsurfel[locnum-1][i] == dest )
{
loc2distsurfel[locnum-1][i+1] = distnum;
return;
}
loc2distsurfel.Add (locnum-1, dest);
loc2distsurfel.Add (locnum-1, distnum);
}
void ParallelMeshTopology :: SetDistantSegm ( int dest, int locnum, int distnum )
{
if ( dest == 0 )
{
loc2distsegm[locnum-1][0] = distnum;
return;
}
for (int i = 1; i < loc2distsegm[locnum-1].Size(); i+=2 )
if ( loc2distsegm[locnum-1][i] == dest )
{
loc2distsegm[locnum-1][i+1] = distnum;
return;
}
loc2distsegm.Add (locnum-1, dest);
loc2distsegm.Add (locnum-1, distnum);
}
void ParallelMeshTopology :: GetVertNeighbours ( int vnum, Array<int> & dests ) const
{
dests.SetSize(0);
int i = 1;
while ( i < loc2distvert[vnum].Size() )
{
dests.Append ( loc2distvert[vnum][i] );
i+=2;
}
}
void ParallelMeshTopology :: Update ()
{
ne = mesh.GetNE();
nv = mesh.GetNV();
nseg = mesh.GetNSeg();
nsurfel = mesh.GetNSE();
ned = mesh.GetTopology().GetNEdges();
nfa = mesh.GetTopology().GetNFaces();
}
2011-02-15 21:22:05 +05:00
void ParallelMeshTopology :: UpdateRefinement ()
{
2011-07-15 03:36:19 +06:00
;
2011-02-15 21:22:05 +05:00
}
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
void ParallelMeshTopology :: UpdateCoarseGridGlobal ()
{
2011-07-15 03:36:19 +06:00
if (id == 0)
PrintMessage ( 3, "UPDATE GLOBAL COARSEGRID STARTS" ); // JS
2009-01-26 00:37:14 +05:00
2011-07-04 18:29:02 +06:00
MPI_Group MPI_GROUP_WORLD;
int n_ho = netgen::ntasks - 1;
int * process_ranks = new int[netgen::ntasks-1];
for ( int i = 0; i < netgen::ntasks-1; i++ )
process_ranks[i] = i+1;
MPI_Comm_group ( MPI_COMM_WORLD, &MPI_GROUP_WORLD);
MPI_Group_incl ( MPI_GROUP_WORLD, n_ho, process_ranks, & MPI_HIGHORDER_WORLD);
MPI_Comm_create ( MPI_COMM_WORLD, MPI_HIGHORDER_WORLD, & MPI_HIGHORDER_COMM);
2011-02-15 21:22:05 +05:00
int timer = NgProfiler::CreateTimer ("UpdateCoarseGridGlobal");
NgProfiler::RegionTimer reg(timer);
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
*testout << "ParallelMeshTopology :: UpdateCoarseGridGlobal" << endl;
const MeshTopology & topology = mesh.GetTopology();
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
Array<int> sendarray, recvarray;
nfa = topology . GetNFaces();
ned = topology . GetNEdges();
np = mesh . GetNP();
nv = mesh . GetNV();
ne = mesh . GetNE();
nseg = mesh.GetNSeg();
nsurfel = mesh.GetNSE();
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
// low order processor - save mesh partition
if ( id == 0 )
{
for ( int eli = 1; eli <= ne; eli++ )
2011-07-15 03:36:19 +06:00
loc2distel[eli-1][0] = eli;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
for ( int i = 1; i <= mesh .GetNV(); i++)
loc2distvert[i][0] = i;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
for ( int i = 0; i < mesh . GetNSeg(); i++)
loc2distsegm[i][0] = i+1;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
for ( int i = 0; i < mesh . GetNSE(); i++)
loc2distsurfel[i][0] = i+1;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
for ( int i = 0; i < topology .GetNEdges(); i++)
loc2distedge[i][0] = i+1;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
for ( int i = 0; i < topology .GetNFaces(); i++)
loc2distface[i][0] = i+1;
}
2009-01-26 00:37:14 +05:00
if ( id == 0 )
sendarray.Append (nfa);
BitArray recvface(nfa);
recvface.Clear();
/*
2011-02-15 21:22:05 +05:00
Array<int> edges, pnums, faces;
for ( int el = 1; el <= ne; el++ )
2009-01-26 00:37:14 +05:00
{
2011-02-15 21:22:05 +05:00
topology.GetElementFaces (el, faces);
int globeli = GetLoc2Glob_VolEl(el);
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
for ( int fai = 0; fai < faces.Size(); fai++)
{
int fa = faces[fai];
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
topology.GetElementEdges ( el, edges );
topology.GetFaceVertices ( fa, pnums );
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
// send :
// localfacenum
// np
// ned
// globalpnums
// localpnums
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
// localedgenums mit globalv1, globalv2
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
sendarray. Append ( fa );
sendarray. Append ( globeli );
sendarray. Append ( pnums.Size() );
sendarray. Append ( edges.Size() );
if (id == 0)
for ( int i = 0; i < pnums.Size(); i++ )
sendarray. Append( pnums[i] );
else
for ( int i = 0; i < pnums.Size(); i++ )
sendarray. Append( GetLoc2Glob_Vert(pnums[i]) );
for ( int i = 0; i < pnums.Size(); i++ )
sendarray. Append(pnums[i] );
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
for ( int i = 0; i < edges.Size(); i++ )
{
sendarray. Append(edges[i] );
int v1, v2;
topology . GetEdgeVertices ( edges[i], v1, v2 );
int dv1 = GetLoc2Glob_Vert ( v1 );
int dv2 = GetLoc2Glob_Vert ( v2 );
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
if (id > 0) if ( dv1 > dv2 ) swap ( dv1, dv2 );
sendarray . Append ( dv1 );
sendarray . Append ( dv2 );
}
}
2009-01-26 00:37:14 +05:00
}
*/
2011-02-15 21:22:05 +05:00
// new version
2009-01-26 00:37:14 +05:00
Array<int> edges, pnums, faces, elpnums;
sendarray.Append (ne);
for ( int el = 1; el <= ne; el++ )
{
topology.GetElementFaces (el, faces);
topology.GetElementEdges ( el, edges );
const Element & volel = mesh.VolumeElement (el);
int globeli = GetLoc2Glob_VolEl(el);
sendarray. Append ( globeli );
sendarray. Append ( faces.Size() );
sendarray. Append ( edges.Size() );
sendarray. Append ( volel.GetNP() );
for ( int i = 0; i < faces.Size(); i++ )
sendarray. Append(faces[i] );
for ( int i = 0; i < edges.Size(); i++ )
sendarray. Append(edges[i] );
for ( int i = 0; i < volel.GetNP(); i++ )
if (id == 0)
sendarray. Append(volel[i] );
else
sendarray. Append(GetLoc2Glob_Vert (volel[i]));
}
// end new version
BitArray edgeisinit(ned), vertisinit(np);
edgeisinit.Clear();
vertisinit.Clear();
// Array for temporary use, to find local from global element fast
Array<int,1> glob2loc_el;
if ( id != 0 )
{
glob2loc_el.SetSize (neglob);
glob2loc_el = -1;
for ( int locel = 1; locel <= mesh.GetNE(); locel++)
glob2loc_el[GetLoc2Glob_VolEl(locel)] = locel;
}
// MPI_Barrier (MPI_COMM_WORLD);
MPI_Request sendrequest;
if (id == 0)
{
2011-07-15 03:36:19 +06:00
// PrintMessage (4, "UpdateCoarseGridGlobal : bcast, size = ", int (sendarray.Size()*sizeof(int)) );
2009-01-26 00:37:14 +05:00
MyMPI_Bcast ( sendarray );
}
else
2011-07-15 03:36:19 +06:00
sendrequest = MyMPI_ISend ( sendarray, 0, MPI_TAG_MESH );
2009-01-26 00:37:14 +05:00
int nloops = (id == 0) ? ntasks-1 : 1;
for (int hi = 0; hi < nloops; hi++)
{
int sender;
if (id == 0)
{
2011-07-07 03:08:58 +06:00
sender = MyMPI_Recv ( recvarray, MPI_TAG_MESH );
2011-07-15 03:36:19 +06:00
// PrintMessage (4, "have received from ", sender);
2009-01-26 00:37:14 +05:00
}
else
{
MyMPI_Bcast ( recvarray );
sender = 0;
}
// compare received vertices with own ones
int ii = 0;
2011-06-26 13:42:55 +06:00
// int cntel = 0;
2009-01-26 00:37:14 +05:00
int volel = 1;
if ( id != 0 )
nfaglob = recvarray[ii++];
2011-07-15 03:36:19 +06:00
if (id == 0) continue;
2009-01-26 00:37:14 +05:00
Array<int> faces, edges;
Array<int> pnums, globalpnums;
int recv_ne = recvarray[ii++];
for (int hi = 0; hi < recv_ne; hi++)
{
int globvolel = recvarray[ii++];
int distnfa = recvarray[ii++];
int distned = recvarray[ii++];
int distnp = recvarray[ii++];
if ( id > 0 )
volel = glob2loc_el[globvolel];
else
volel = globvolel;
if (volel != -1)
{
topology.GetElementFaces( volel, faces);
topology.GetElementEdges ( volel, edges);
const Element & volelement = mesh.VolumeElement (volel);
for ( int i = 0; i < faces.Size(); i++)
SetDistantFaceNum ( sender, faces[i], recvarray[ii++]);
for ( int i = 0; i < edges.Size(); i++)
SetDistantEdgeNum ( sender, edges[i], recvarray[ii++]);
for ( int i = 0; i < distnp; i++)
SetDistantPNum ( sender, volelement[i], recvarray[ii++]);
}
else
ii += distnfa + distned + distnp;
}
}
coarseupdate = 1;
if (id != 0)
2011-07-15 03:36:19 +06:00
MPI_Wait (&sendrequest, MPI_STATUS_IGNORE);
2011-02-15 21:22:05 +05:00
}
2009-01-26 00:37:14 +05:00
void ParallelMeshTopology :: UpdateCoarseGrid ()
{
2011-07-15 03:36:19 +06:00
static int timer = NgProfiler::CreateTimer ("UpdateCoarseGrid");
2009-01-26 00:37:14 +05:00
NgProfiler::RegionTimer reg(timer);
2011-02-15 21:22:05 +05:00
2009-01-26 00:37:14 +05:00
(*testout) << "UPDATE COARSE GRID PARALLEL TOPOLOGY " << endl;
2011-07-15 03:36:19 +06:00
if (id == 0)
PrintMessage (1, "UPDATE COARSE GRID PARALLEL TOPOLOGY ");
2009-01-26 00:37:14 +05:00
// find exchange edges - first send exchangeedges locnum, v1, v2
// receive distant distnum, v1, v2
// find matching
const MeshTopology & topology = mesh.GetTopology();
UpdateCoarseGridGlobal();
2011-07-15 03:36:19 +06:00
MPI_Barrier (MPI_COMM_WORLD);
2009-01-26 00:37:14 +05:00
2011-07-15 03:36:19 +06:00
if ( id == 0 )
{
MPI_Barrier (MPI_COMM_WORLD);
return;
}
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
Array<int> sendarray, recvarray;
2009-01-26 00:37:14 +05:00
nfa = topology . GetNFaces();
ned = topology . GetNEdges();
np = mesh . GetNP();
nv = mesh . GetNV();
ne = mesh . GetNE();
nseg = mesh.GetNSeg();
nsurfel = mesh.GetNSE();
2011-07-15 03:36:19 +06:00
static int timerv = NgProfiler::CreateTimer ("UpdateCoarseGrid - ex vertices");
static int timere = NgProfiler::CreateTimer ("UpdateCoarseGrid - ex edges");
static int timerf = NgProfiler::CreateTimer ("UpdateCoarseGrid - ex faces");
Array<int,1> glob2loc;
Array<int> cnt_send(ntasks-1);
/*
2011-02-15 21:22:05 +05:00
// exchange vertices
2011-07-15 03:36:19 +06:00
NgProfiler::StartTimer (timerv);
2009-01-26 00:37:14 +05:00
2011-07-15 03:36:19 +06:00
*testout << "exchange vertices" << endl;
glob2loc.SetSize (nvglob);
glob2loc = -1;
for (int locv = 1; locv <= nv; locv++)
if (IsExchangeVert (locv) )
glob2loc[GetDistantPNum(0, locv)] = locv;
cnt_send = 0;
for (int vertex = 1; vertex <= nv; vertex++)
for (int dest = 1; dest < ntasks; dest++)
if (IsExchangeVert (dest, vertex))
cnt_send[dest-1]+=2;
// *testout << "cnt_send = " << cnt_send << endl;
TABLE<int> send_verts(cnt_send);
for (int vertex = 1; vertex <= nv; vertex++)
for (int dest = 1; dest < ntasks; dest++)
if (IsExchangeVert (dest, vertex))
{
send_verts.Add (dest-1, GetLoc2Glob_Vert (vertex));
send_verts.Add (dest-1, vertex);
}
TABLE<int> recv_verts (ntasks-1);
MyMPI_ExchangeTable (send_verts, recv_verts, MPI_TAG_MESH+8, MPI_HIGHORDER_COMM);
for (int sender = 1; sender < ntasks; sender ++)
if (id != sender)
{
FlatArray<int> recvarray = recv_verts[sender-1];
for (int ii = 0; ii < recvarray.Size(); )
{
int globv = recvarray[ii++];
int distv = recvarray[ii++];
int locv = glob2loc[globv];
if (locv != -1)
{
if (GetDistantPNum(sender, locv) != distv)
cerr << "distant pnum inconsistent: sender = " << sender << ", locv = "<< locv << ", distv = " << distv << ", getdist = " << GetDistantPNum(sender, locv) << endl;
// SetDistantPNum (sender, locv, distv);
}
}
}
*/
/*
2011-02-15 21:22:05 +05:00
for (int vertex = 1; vertex <= nv; vertex++)
if (IsExchangeVert (vertex) )
{
sendarray.Append (GetLoc2Glob_Vert (vertex));
sendarray.Append (vertex);
}
Array<int,1> glob2loc;
glob2loc.SetSize (nvglob);
glob2loc = -1;
for (int locv = 1; locv <= nv; locv++)
if (IsExchangeVert (locv) )
glob2loc[GetDistantPNum(0, locv)] = locv;
for (int sender = 1; sender < ntasks; sender ++)
2009-01-26 00:37:14 +05:00
{
2011-02-15 21:22:05 +05:00
if (id == sender)
MyMPI_Bcast (sendarray, sender-1, MPI_HIGHORDER_COMM);
else
{
MyMPI_Bcast (recvarray, sender-1, MPI_HIGHORDER_COMM);
for (int ii = 0; ii < recvarray.Size(); )
{
int globv = recvarray[ii++];
int distv = recvarray[ii++];
int locv = glob2loc[globv];
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
if (locv != -1)
SetDistantPNum (sender, locv, distv);
}
}
}
2009-01-26 00:37:14 +05:00
2011-07-15 03:36:19 +06:00
NgProfiler::StopTimer (timerv);
*/
NgProfiler::StartTimer (timere);
2011-02-15 21:22:05 +05:00
sendarray.SetSize (0);
recvarray.SetSize (0);
// exchange edges
int maxedge = 0;
for (int edge = 1; edge <= ned; edge++)
2011-07-15 03:36:19 +06:00
// if (IsExchangeEdge (edge) )
2011-02-15 21:22:05 +05:00
{
sendarray.Append (GetDistantEdgeNum (0, edge));
sendarray.Append (edge);
maxedge = max (maxedge, GetDistantEdgeNum (0, edge));
}
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
glob2loc.SetSize (maxedge+1);
glob2loc = -1;
for (int loc = 1; loc <= ned; loc++)
2011-07-15 03:36:19 +06:00
// if (IsExchangeEdge (loc) )
2011-02-15 21:22:05 +05:00
glob2loc[GetDistantEdgeNum(0, loc)] = loc;
for (int sender = 1; sender < ntasks; sender ++)
{
if (id == sender)
MyMPI_Bcast (sendarray, sender-1, MPI_HIGHORDER_COMM);
else
{
MyMPI_Bcast (recvarray, sender-1, MPI_HIGHORDER_COMM);
for (int ii = 0; ii < recvarray.Size(); )
{
int globe = recvarray[ii++];
int diste = recvarray[ii++];
if (globe > maxedge) continue;
int loce = glob2loc[globe];
if (loce != -1)
SetDistantEdgeNum (sender, loce, diste);
}
}
}
2011-07-15 03:36:19 +06:00
NgProfiler::StopTimer (timere);
NgProfiler::StartTimer (timerf);
glob2loc.SetSize (nfaglob);
glob2loc = -1;
for (int loc = 1; loc <= nfa; loc++)
glob2loc[GetDistantFaceNum(0, loc)] = loc;
cnt_send = 0;
Array<int> verts;
for (int face = 1; face <= nfa; face++)
{
topology.GetFaceVertices (face, verts);
for (int dest = 1; dest < ntasks; dest++)
if (IsExchangeVert (dest, verts[0]) &&
IsExchangeVert (dest, verts[1]) &&
IsExchangeVert (dest, verts[2]))
{
cnt_send[dest-1]+=2;
}
}
TABLE<int> send_faces(cnt_send);
for (int face = 1; face <= nfa; face++)
{
topology.GetFaceVertices (face, verts);
for (int dest = 1; dest < ntasks; dest++)
{
if (IsExchangeVert (dest, verts[0]) &&
IsExchangeVert (dest, verts[1]) &&
IsExchangeVert (dest, verts[2]))
{
send_faces.Add (dest-1, GetDistantFaceNum(0, face));
send_faces.Add (dest-1, face);
}
}
}
TABLE<int> recv_faces(ntasks-1);
MyMPI_ExchangeTable (send_faces, recv_faces, MPI_TAG_MESH+8, MPI_HIGHORDER_COMM);
// *testout << "send exchange faces: " << send_faces << endl;
// *testout << "recv exchange faces: " << recv_faces << endl;
for (int sender = 1; sender < ntasks; sender ++)
if (id != sender)
{
FlatArray<int> recvarray = recv_faces[sender-1];
for (int ii = 0; ii < recvarray.Size(); )
{
int globf = recvarray[ii++];
int distf = recvarray[ii++];
int locf = glob2loc[globf];
// *testout << "set distant face, sender = " << sender << ", locf = " << locf << "; distf = " << distf << endl;
if (locf != -1)
SetDistantFaceNum (sender, locf, distf);
}
}
/*
2011-02-15 21:22:05 +05:00
sendarray.SetSize (0);
recvarray.SetSize (0);
// exchange faces
for (int face = 1; face <= nfa; face++)
if (IsExchangeFace (face) )
{
sendarray.Append (GetDistantFaceNum (0, face));
sendarray.Append (face);
}
glob2loc.SetSize (nfaglob);
glob2loc = -1;
for (int loc = 1; loc <= nfa; loc++)
if (IsExchangeFace (loc) )
glob2loc[GetDistantFaceNum(0, loc)] = loc;
for (int sender = 1; sender < ntasks; sender ++)
{
if (id == sender)
MyMPI_Bcast (sendarray, sender-1, MPI_HIGHORDER_COMM);
else
{
MyMPI_Bcast (recvarray, sender-1, MPI_HIGHORDER_COMM);
for (int ii = 0; ii < recvarray.Size(); )
{
int globf = recvarray[ii++];
int distf = recvarray[ii++];
int locf = glob2loc[globf];
if (locf != -1)
SetDistantFaceNum (sender, locf, distf);
}
}
}
2011-07-15 03:36:19 +06:00
*/
2011-02-15 21:22:05 +05:00
2011-07-15 03:36:19 +06:00
NgProfiler::StopTimer (timerf);
2011-02-15 21:22:05 +05:00
#ifdef OLD
// BitArray recvface(nfa);
// recvface.Clear();
for (int fa = 1; fa <= nfa; fa++ )
{
if ( !IsExchangeFace ( fa ) ) continue;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
Array<int> edges, pnums;
int globfa = GetDistantFaceNum (0, fa);
topology.GetFaceEdges (fa, edges);
topology.GetFaceVertices (fa, pnums);
2009-01-26 00:37:14 +05:00
// send :
2011-02-15 21:22:05 +05:00
// localfacenum globalfacenum np ned globalpnums localpnums
2009-01-26 00:37:14 +05:00
// localedgenums mit globalv1, globalv2
2011-02-15 21:22:05 +05:00
sendarray.Append ( fa );
sendarray.Append ( globfa );
sendarray.Append ( pnums.Size() );
sendarray.Append ( edges.Size() );
for (int i = 0; i < pnums.Size(); i++ )
sendarray.Append( GetLoc2Glob_Vert(pnums[i]) );
2009-01-26 00:37:14 +05:00
for ( int i = 0; i < pnums.Size(); i++ )
2011-02-15 21:22:05 +05:00
sendarray.Append(pnums[i]);
2009-01-26 00:37:14 +05:00
for ( int i = 0; i < edges.Size(); i++ )
{
2011-02-15 21:22:05 +05:00
sendarray.Append(edges[i]);
2009-01-26 00:37:14 +05:00
int v1, v2;
2011-02-15 21:22:05 +05:00
topology.GetEdgeVertices ( edges[i], v1, v2 );
2009-01-26 00:37:14 +05:00
int dv1 = GetLoc2Glob_Vert ( v1 );
int dv2 = GetLoc2Glob_Vert ( v2 );
2011-02-15 21:22:05 +05:00
sendarray.Append ( dv1 );
sendarray.Append ( dv2 );
2009-01-26 00:37:14 +05:00
}
}
BitArray edgeisinit(ned), vertisinit(np);
edgeisinit.Clear();
vertisinit.Clear();
// Array for temporary use, to find local from global element fast
// only for not too big meshes
// seems ok, as low-order space is treated on one proc
2011-02-15 21:22:05 +05:00
Array<int,1> glob2locfa (nfaglob);
glob2locfa = -1;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
for (int locfa = 1; locfa <= nfa; locfa++)
if (IsExchangeFace (locfa) )
glob2locfa[GetDistantFaceNum(0, locfa)] = locfa;
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
for (int sender = 1; sender < ntasks; sender ++)
{
if (id == sender)
MyMPI_Bcast (sendarray, sender-1, MPI_HIGHORDER_COMM);
else
2009-01-26 00:37:14 +05:00
{
2011-02-15 21:22:05 +05:00
MyMPI_Bcast ( recvarray, sender-1, MPI_HIGHORDER_COMM);
2009-01-26 00:37:14 +05:00
// compare received vertices with own ones
int ii = 0;
int cntel = 0;
int locfa = 1;
2011-02-15 21:22:05 +05:00
while (ii < recvarray.Size())
2009-01-26 00:37:14 +05:00
{
// receive list :
2011-02-15 21:22:05 +05:00
// distant_facenum global_facenum np ned globalpnums distant_pnums
2009-01-26 00:37:14 +05:00
// distant edgenums mit globalv1, globalv2
2011-02-15 21:22:05 +05:00
int distfa = recvarray[ii++];
int globfa = recvarray[ii++];
int distnp = recvarray[ii++];
int distned =recvarray[ii++];
2009-01-26 00:37:14 +05:00
2011-02-15 21:22:05 +05:00
int locfa = (glob2locfa) [globfa];
2009-01-26 00:37:14 +05:00
if ( locfa == -1 )
{
ii += 2*distnp + 3*distned;
locfa = 1;
continue;
}
Array<int> edges;
int fa = locfa;
Array<int> pnums, globalpnums;
topology.GetFaceEdges ( fa, edges );
topology.GetFaceVertices ( fa, pnums );
globalpnums.SetSize ( distnp );
for ( int i = 0; i < distnp; i++)
globalpnums[i] = GetLoc2Glob_Vert ( pnums[i] );
SetDistantFaceNum ( sender, fa, distfa );
// find exchange points
for ( int i = 0; i < distnp; i++)
{
2011-02-15 21:22:05 +05:00
int distglobalpnum = recvarray[ii+i];
2009-01-26 00:37:14 +05:00
for ( int j = 0; j < distnp; j++ )
if ( globalpnums[j] == distglobalpnum )
{
// set sender -- distpnum ---- locpnum
2011-02-15 21:22:05 +05:00
int distpnum = recvarray[ii + i +distnp];
// SetDistantPNum ( sender, pnums[j], distpnum );
2009-01-26 00:37:14 +05:00
}
}
2011-02-15 21:22:05 +05:00
Array<int> distedgenums(distned);
2009-01-26 00:37:14 +05:00
// find exchange edges
for ( int i = 0; i < edges.Size(); i++)
{
int v1, v2;
topology . GetEdgeVertices ( edges[i], v1, v2 );
int dv1 = GetLoc2Glob_Vert ( v1 );
int dv2 = GetLoc2Glob_Vert ( v2 );
if ( dv1 > dv2 ) swap ( dv1, dv2 );
for ( int ed = 0; ed < distned; ed++)
{
2011-02-15 21:22:05 +05:00
distedgenums[ed] = recvarray[ii + 2*distnp + 3*ed];
int ddv1 = recvarray[ii + 2*distnp + 3*ed + 1];
int ddv2 = recvarray[ii + 2*distnp + 3*ed + 2];
2009-01-26 00:37:14 +05:00
if ( ddv1 > ddv2 ) swap ( ddv1, ddv2 );
if ( dv1 == ddv1 && dv2 == ddv2 )
{
// set sender -- distednum -- locednum
SetDistantEdgeNum ( sender, edges[i], distedgenums[ed] );
}
}
}
ii += 2*distnp + 3*distned;
}
}
}
2011-02-15 21:22:05 +05:00
#endif
2009-01-26 00:37:14 +05:00
// set which elements are where for the master processor
coarseupdate = 1;
2011-07-15 03:36:19 +06:00
MPI_Barrier (MPI_COMM_WORLD);
2009-01-26 00:37:14 +05:00
}
void ParallelMeshTopology :: UpdateTopology ()
{
const MeshTopology & topology = mesh.GetTopology();
int nfa = topology.GetNFaces();
int ned = topology.GetNEdges();
2011-07-15 03:36:19 +06:00
/*
2009-01-26 00:37:14 +05:00
isghostedge.SetSize(ned);
isghostface.SetSize(nfa);
isghostedge.Clear();
isghostface.Clear();
for ( int ed = 1; ed <= ned; ed++)
{
int v1, v2;
topology.GetEdgeVertices ( ed, v1, v2 );
if ( IsGhostVert(v1) || IsGhostVert(v2) )
SetGhostEdge ( ed );
}
2011-07-15 03:36:19 +06:00
*/
2009-01-26 00:37:14 +05:00
2011-07-15 03:36:19 +06:00
/*
2009-01-26 00:37:14 +05:00
Array<int> pnums;
for ( int fa = 1; fa <= nfa; fa++)
{
topology.GetFaceVertices ( fa, pnums );
for ( int i = 0; i < pnums.Size(); i++)
if ( IsGhostVert( pnums[i] ) )
{
SetGhostFace ( fa );
break;
}
}
2011-07-15 03:36:19 +06:00
*/
2009-01-26 00:37:14 +05:00
}
2011-02-15 21:22:05 +05:00
void ParallelMeshTopology :: SetNV ( const int anv )
2009-01-26 00:37:14 +05:00
{
*testout << "called setnv" << endl
<< "old size: " << loc2distvert.Size() << endl
<< "new size: " << anv << endl;
loc2distvert.ChangeSize (anv);
for (int i = 1; i <= anv; i++)
if (loc2distvert.EntrySize(i) == 0)
loc2distvert.Add (i, -1); // will be the global nr
nv = anv;
}
2011-02-15 21:22:05 +05:00
void ParallelMeshTopology :: SetNE ( const int ane )
2009-01-26 00:37:14 +05:00
{
loc2distel.ChangeSize (ane);
for (int i = 0; i < ane; i++)
2011-07-15 03:36:19 +06:00
if (loc2distel[i].Size() == 0)
loc2distel.Add (i, -1); // will be the global nr
2009-01-26 00:37:14 +05:00
ne = ane;
}
2011-02-15 21:22:05 +05:00
void ParallelMeshTopology :: SetNSE ( int anse )
2009-01-26 00:37:14 +05:00
{
loc2distsurfel.ChangeSize (anse);
for (int i = 0; i < anse; i++)
if (loc2distsurfel[i].Size() == 0)
loc2distsurfel.Add (i, -1); // will be the global nr
2011-02-15 21:22:05 +05:00
nsurfel = anse;
2009-01-26 00:37:14 +05:00
}
2011-02-15 21:22:05 +05:00
void ParallelMeshTopology :: SetNSegm ( int anseg )
{
loc2distsegm.ChangeSize (anseg);
for (int i = 0; i < anseg; i++)
if (loc2distsegm[i].Size() == 0)
2009-01-26 00:37:14 +05:00
loc2distsegm.Add (i, -1); // will be the global nr
2011-02-15 21:22:05 +05:00
nseg = anseg;
2009-01-26 00:37:14 +05:00
}
}
#endif