MPI: Setup MPI now allows split in all directions with defitions read from xml-file

Warning: depends on API changes in CSXCAD!
pull/1/head
Thorsten Liebig 2011-02-25 11:58:23 +01:00
parent 8acb348edb
commit eb7524b6f6
3 changed files with 121 additions and 35 deletions

View File

@ -32,6 +32,7 @@
#include <time.h>
#include "mpi.h"
#include "tools/useful.h"
#include "tinyxml.h"
openEMS_FDTD_MPI::openEMS_FDTD_MPI() : openEMS()
{
@ -57,12 +58,18 @@ openEMS_FDTD_MPI::openEMS_FDTD_MPI() : openEMS()
m_Gather_Buffer = NULL;
m_Energy_Buffer = NULL;
}
m_Original_Grid = NULL;
}
openEMS_FDTD_MPI::~openEMS_FDTD_MPI()
{
delete[] m_Gather_Buffer;
m_Gather_Buffer = NULL;
delete[] m_Energy_Buffer;
m_Energy_Buffer = NULL;
delete m_Original_Grid;
m_Original_Grid = NULL;
}
bool openEMS_FDTD_MPI::parseCommandLineArgument( const char *argv )
@ -90,43 +97,107 @@ bool openEMS_FDTD_MPI::SetupMPI(TiXmlElement* FDTD_Opts)
//manipulate geometry for this part...
UNUSED(FDTD_Opts);
if (m_MPI_Enabled)
if (!m_MPI_Enabled)
{
CSRectGrid* grid = m_CSX->GetGrid();
int nz = grid->GetQtyLines(2);
std::vector<unsigned int> jobs = AssignJobs2Threads(nz, m_NumProc);
double z_lines[jobs.at(m_MyID)+1];
if (m_MyID==0)
{
for (unsigned int n=0;n<jobs.at(0);++n)
z_lines[n] = grid->GetLine(2,n);
grid->ClearLines(2);
grid->AddDiscLines(2,jobs.at(0),z_lines);
}
else
{
unsigned int z_start=0;
for (int n=0;n<m_MyID;++n)
z_start+=jobs.at(n);
for (unsigned int n=0;n<=jobs.at(m_MyID);++n)
z_lines[n] = grid->GetLine(2,z_start+n-1);
grid->ClearLines(2);
grid->AddDiscLines(2,jobs.at(m_MyID)+1,z_lines);
}
//lower neighbor is ID-1
if (m_MyID>0)
m_MPI_Op->SetNeighborDown(2,m_MyID-1);
//upper neighbor is ID+1
if (m_MyID<m_NumProc-1)
m_MPI_Op->SetNeighborUp(2,m_MyID+1);
m_MPI_Op->SetTag(0);
if (g_settings.GetVerboseLevel()>0)
cerr << "openEMS_FDTD_MPI::SetupMPI: Warning: Number of MPI processes is 1, skipping MPI engine... " << endl;
return true;
}
else
cerr << "openEMS_FDTD_MPI::SetupMPI: Warning: Number of MPI processes is 1, skipping MPI engine... " << endl;
TiXmlElement* MPI_Elem = FDTD_Opts->FirstChildElement("MPI");
CSRectGrid* grid = m_CSX->GetGrid();
delete m_Original_Grid;
m_Original_Grid = CSRectGrid::Clone(grid);
vector<unsigned int> SplitNumber[3];
string argNames[] = {"SplitPos_X", "SplitPos_Y", "SplitPos_Z"};
const char* tmp = NULL;
for (int n=0;n<3;++n)
{
SplitNumber[n].push_back(0);
tmp = MPI_Elem->Attribute(argNames[n].c_str());
if (tmp)
{
vector<double> SplitLines = SplitString2Double(tmp, ',');
bool inside;
unsigned int line;
for (size_t lineN = 0; lineN<SplitLines.size();++lineN)
{
line = m_Original_Grid->Snap2LineNumber(n, SplitLines.at(lineN), inside);
if (inside)
SplitNumber[n].push_back(line);
}
}
SplitNumber[n].push_back(m_Original_Grid->GetQtyLines(n)-1);
unique(SplitNumber[n].begin(), SplitNumber[n].end());
}
MPI_Barrier(MPI_COMM_WORLD);
//validate number of processes
int numProcs = (SplitNumber[0].size()-1)*(SplitNumber[1].size()-1)*(SplitNumber[2].size()-1);
if (numProcs!=m_NumProc)
{
if (m_MyID==0)
cerr << "openEMS_FDTD_MPI::SetupMPI: Error: Requested splits require " << numProcs << " processes, but only " << m_NumProc << " were found! Exit! " << endl;
exit(10);
}
//create process table
unsigned int procN = 0;
int procTable[SplitNumber[0].size()-1][SplitNumber[1].size()-1][SplitNumber[2].size()-1];
for (size_t i=0;i<SplitNumber[0].size()-1;++i)
for (size_t j=0;j<SplitNumber[1].size()-1;++j)
for (size_t k=0;k<SplitNumber[2].size()-1;++k)
{
procTable[i][j][k] = procN;
++procN;
}
//assign mesh and neighbors to this process
for (size_t i=0;i<SplitNumber[0].size()-1;++i)
{
for (size_t j=0;j<SplitNumber[1].size()-1;++j)
{
for (size_t k=0;k<SplitNumber[2].size()-1;++k)
{
if (procTable[i][j][k] == m_MyID)
{
grid->ClearLines(0);
grid->ClearLines(1);
grid->ClearLines(2);
for (unsigned int n=SplitNumber[0].at(i);n<=SplitNumber[0].at(i+1);++n)
grid->AddDiscLine(0, m_Original_Grid->GetLine(0,n) );
for (unsigned int n=SplitNumber[1].at(j);n<=SplitNumber[1].at(j+1);++n)
grid->AddDiscLine(1, m_Original_Grid->GetLine(1,n) );
for (unsigned int n=SplitNumber[2].at(k);n<=SplitNumber[2].at(k+1);++n)
grid->AddDiscLine(2, m_Original_Grid->GetLine(2,n) );
if (i>0)
m_MPI_Op->SetNeighborDown(0,procTable[i-1][j][k]);
if (i<SplitNumber[0].size()-2)
m_MPI_Op->SetNeighborUp(0,procTable[i+1][j][k]);
if (j>0)
m_MPI_Op->SetNeighborDown(1,procTable[i][j-1][k]);
if (j<SplitNumber[1].size()-2)
m_MPI_Op->SetNeighborUp(1,procTable[i][j+1][k]);
if (k>0)
m_MPI_Op->SetNeighborDown(2,procTable[i][j][k-1]);
if (k<SplitNumber[2].size()-2)
m_MPI_Op->SetNeighborUp(2,procTable[i][j][k+1]);
}
}
}
}
m_MPI_Op->SetTag(0);
return true;
}

View File

@ -22,6 +22,7 @@
class ProcessFields;
class Operator_MPI;
class CSRectGrid;
class openEMS_FDTD_MPI : public openEMS
{
@ -35,6 +36,7 @@ public:
protected:
Operator_MPI* m_MPI_Op;
CSRectGrid* m_Original_Grid;
int m_MyID;
int m_NumProc;
bool m_MPI_Enabled;

13
matlab/SetupMPI.m Normal file
View File

@ -0,0 +1,13 @@
function FDTD = SetupMPI(FDTD, varargin)
% function FDTD = SetupMPI(FDTD, varargin);
%
% % example
% FDTD = SetupMPI(FDTD,'SplitPos_X', '-500,500','SplitPos_Z', '-500,500');
%
% openEMS matlab interface
% -----------------------
% author: Thorsten Liebig
for n=1:(nargin-1)/2
FDTD.MPI.ATTRIBUTE.(varargin{2*n-1})=varargin{2*n};
end