#include <iostream> #include <string> #include "VirtualFluids.h" using namespace std; void run(string configname) { SPtr<vf::parallel::Communicator> comm = vf::parallel::MPICommunicator::getInstance(); int myid = comm->getProcessID(); // Get the name of the processor char machinename[MPI_MAX_PROCESSOR_NAME]; int name_len; MPI_Get_processor_name(machinename, &name_len); try { //UbLog::reportingLevel() = UbLog::logLevelFromString("DEBUG5"); vf::basics::ConfigurationFile config; config.load(configname); string pathOut = config.getString("pathOut"); double endTime = config.getDouble("endTime"); int numOfThreads = config.getInt("numOfThreads"); vector<int> blockNx = config.getVector<int>("blockNx"); double availMem = config.getDouble("availMem"); bool logToFile = config.getBool("logToFile"); bool oneD = config.getBool("oneD"); bool output = config.getBool("output"); vector<double> nupsStep = config.getVector<double>("nupsStep"); bool priorityQueue = config.getBool("priorityQueue"); bool restart = config.getBool("restart"); double restartStep = config.getDouble("restartStep"); double cpStep = config.getDouble("cpStep"); if (logToFile) { #if defined(__unix__) if (myid==0) { const char* str = pathOut.c_str(); mkdir(str, S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH); } #endif if (myid==0) { stringstream logFilename; logFilename<<pathOut+"/logfile"+UbSystem::toString(UbSystem::getTimeStamp())+".txt"; UbLog::output_policy::setStream(logFilename.str()); } } if (myid==0) { UBLOG(logINFO, "MPI benchmark"); UBLOG(logINFO, "1. PID = "<<myid<<" host name: "<<machinename); UBLOG(logINFO, "1. PID = "<<myid<<" Number of processes = "<<comm->getNumberOfProcesses()); UBLOG(logINFO, "1. PID = "<<myid<<" Number of threads = "<<numOfThreads); UBLOG(logINFO, "1. PID = "<<myid<<" Total Physical Memory (RAM): "<<Utilities::getTotalPhysMem()/1073741824.0<<" GB"); UBLOG(logINFO, "1. PID = "<<myid<<" Physical Memory currently used: "<<Utilities::getPhysMemUsed()/1073741824.0<<" GB"); UBLOG(logINFO, "1. PID = "<<myid<<" Physical Memory currently used by current process: "<<Utilities::getPhysMemUsedByMe()/1073741824.0<<" GB"); } LBMReal uLB = 0.05; LBMReal Re = 20.0; LBMReal rhoLB = 0.0; LBMReal nueLB = 0.05842; SPtr<Grid3D> grid(new Grid3D(comm)); ////////////////////////////////////////////////////////////////////////// //restart SPtr<UbScheduler> rSch(new UbScheduler(cpStep,cpStep)); MPIIORestartCoProcessor rcp(grid, rSch, pathOut, comm); if (restart) { rcp.restart((int)restartStep); } else { double dx = 1; double g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3; double factor = 1.0; if (oneD) { factor = comm->getNumberOfProcesses() * numOfThreads; g_minX1 = 0; g_minX2 = 0; g_minX3 = 0; g_maxX1 = blockNx[0]*2.0 * factor; g_maxX2 = blockNx[1]*2.0; g_maxX3 = blockNx[2]*2.0; } else { factor = pow(comm->getNumberOfProcesses() * numOfThreads, 1.0/3.0); g_minX1 = 0; g_minX2 = 0; g_minX3 = 0; g_maxX1 = blockNx[0]*2.0 * factor; g_maxX2 = blockNx[1]*2.0 * factor; g_maxX3 = blockNx[2]*2.0 * factor; } SPtr<LBMUnitConverter> conv = SPtr<LBMUnitConverter>(new LBMUnitConverter()); grid->setDeltaX(dx); grid->setBlockNX(blockNx[0], blockNx[1], blockNx[2]); SPtr<GbObject3D> gridCube(new GbCuboid3D(g_minX1, g_minX2, g_minX3, g_maxX1, g_maxX2, g_maxX3)); if (myid==0&&output) GbSystem3D::writeGeoObject(gridCube.get(), pathOut+"/geo/gridCube", WbWriterVtkXmlASCII::getInstance()); GenBlocksGridVisitor genBlocks(gridCube); grid->accept(genBlocks); //grid->setPeriodicX1(true); //grid->setPeriodicX2(true); //grid->setPeriodicX3(true); if (myid==0) { UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////"); UBLOG(logINFO, "2. PID = "<<myid<<" Total Physical Memory (RAM): "<<Utilities::getTotalPhysMem()/1073741824.0<<" GB"); UBLOG(logINFO, "2. PID = "<<myid<<" Physical Memory currently used: "<<Utilities::getPhysMemUsed()/1073741824.0<<" GB"); UBLOG(logINFO, "2. PID = "<<myid<<" Physical Memory currently used by current process: "<<Utilities::getPhysMemUsedByMe()/1073741824.0<<" GB"); UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////"); } if (priorityQueue) { if (myid==0) UBLOG(logINFO, "MetisPartitioningGridVisitor:start"); MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::BSW); grid->accept(metisVisitor); if (myid==0) UBLOG(logINFO, "MetisPartitioningGridVisitor:end"); //domain decomposition for threads if (myid==0) UBLOG(logINFO, "PQueuePartitioningGridVisitor:start"); PQueuePartitioningGridVisitor pqPartVisitor(numOfThreads); grid->accept(pqPartVisitor); if (myid==0) UBLOG(logINFO, "PQueuePartitioningGridVisitor:end"); } else { if (myid==0) UBLOG(logINFO, "MetisPartitioningGridVisitor:start"); MetisPartitioningGridVisitor metisVisitor(comm, MetisPartitioningGridVisitor::LevelBased, D3Q27System::BSW, MetisPartitioner::KWAY, true, numOfThreads); grid->accept(metisVisitor); if (myid==0) UBLOG(logINFO, "MetisPartitioningGridVisitor:end"); } if (output) { WriteBlocksCoProcessor ppblocks(grid, SPtr<UbScheduler>(new UbScheduler(1)), pathOut, WbWriterVtkXmlBinary::getInstance(), comm); ppblocks.process(0); } unsigned long nob = grid->getNumberOfBlocks(); int gl = 3; unsigned long nodb = (blockNx[0])* (blockNx[1])* (blockNx[2]); unsigned long nod = nob * (blockNx[0])* (blockNx[1])* (blockNx[2]); unsigned long nodg = nob * (blockNx[0]+gl) * (blockNx[1]+gl) * (blockNx[2]+gl); double needMemAll = double(nodg*(27*sizeof(double)+sizeof(int)+sizeof(float)*4)); double needMem = needMemAll/double(comm->getNumberOfProcesses()); if (myid==0) { UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////"); UBLOG(logINFO, "Setup information:"); UBLOG(logINFO, "Size of block = "<<blockNx[0]<<" x "<<blockNx[1]<<" x "<<blockNx[2]<<" nodes"); UBLOG(logINFO, "Size of domain = "<<g_maxX1<<" x "<<g_maxX2<<" x "<<g_maxX3<<" dx "); UBLOG(logINFO, "Number of blocks = "<<nob); UBLOG(logINFO, "Number of nodes = "<<nod); int minInitLevel = grid->getCoarsestInitializedLevel(); int maxInitLevel = grid->getFinestInitializedLevel(); for (int level = minInitLevel; level<=maxInitLevel; level++) { int nobl = grid->getNumberOfBlocks(level); UBLOG(logINFO, "Number of blocks for level "<<level<<" = "<<nob); UBLOG(logINFO, "Number of nodes for level "<<level<<" = "<<nob*nodb); } UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////"); UBLOG(logINFO, "Necessary memory = "<<needMemAll/1073741824.0<<" GB"); UBLOG(logINFO, "Necessary memory per process = "<<needMem/1073741824.0<<" GB"); UBLOG(logINFO, "Available memory per process = "<<availMem/1073741824.0<<" GB"); UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////"); } SPtr<LBMKernel> kernel; kernel = SPtr<LBMKernel>(new InK15CompressibleNavierStokes(blockNx[0], blockNx[1], blockNx[2], InK15CompressibleNavierStokes::NORMAL)); SPtr<BCProcessor> bcProc(new BCProcessor()); kernel->setBCProcessor(bcProc); SetKernelBlockVisitor kernelVisitor(kernel, nueLB, availMem, needMem); grid->accept(kernelVisitor); //initialization of distributions InitDistributionsBlockVisitor initVisitor(nueLB, rhoLB); initVisitor.setVx1(uLB); grid->accept(initVisitor); } //set connectors if (myid==0) UBLOG(logINFO, "SetConnectorsBlockVisitor:start"); InterpolationProcessorPtr iProcessor(new IncompressibleOffsetInterpolator()); SetConnectorsBlockVisitor setConnsVisitor(comm, true, D3Q27System::ENDDIR, nueLB, iProcessor); grid->accept(setConnsVisitor); if (myid==0) UBLOG(logINFO, "SetConnectorsBlockVisitor:end"); SPtr<UbScheduler> nupsSch(new UbScheduler(nupsStep[0], nupsStep[1], nupsStep[2])); NUPSCounterCoProcessor npr(grid, nupsSch, numOfThreads, comm); SPtr<UbScheduler> visSch(new UbScheduler(500, 500)); if (myid==0) { UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////"); UBLOG(logINFO, "System information:"); UBLOG(logINFO, "Total Physical Memory (RAM): "<<Utilities::getTotalPhysMem()/1073741824.0<<" GB"); UBLOG(logINFO, "Physical Memory currently used: "<<Utilities::getPhysMemUsed()/1073741824.0<<" GB"); UBLOG(logINFO, "Physical Memory currently used by current process: "<<Utilities::getPhysMemUsedByMe()/1073741824.0<<" GB"); UBLOG(logINFO, "//////////////////////////////////////////////////////////////////////////"); } const SPtr<ConcreteCalculatorFactory> calculatorFactory = std::make_shared<ConcreteCalculatorFactory>(visSch); CalculationManagerPtr calculation(new CalculationManager(grid, numOfThreads, endTime, calculatorFactory, CalculatorType::MPI)); if (myid==0) UBLOG(logINFO, "Simulation-start"); calculation->calculate(); if (myid==0) UBLOG(logINFO, "Simulation-end"); } catch (std::exception& e) { cerr<<"PID = "<<myid<<" host name: "<<machinename<<endl<<flush; cerr<<e.what()<<endl<<flush<< boost::current_exception_diagnostic_information(); } catch (std::string& s) { cerr<<s<<endl<<boost::current_exception_diagnostic_information(); } catch (...) { cerr<<"unknown exception"<<endl<< boost::current_exception_diagnostic_information(); } } int main(int argc, char* argv[]) { if (argv!=NULL) { if (argv[1]!=NULL) { run(string(argv[1])); UBLOG(logINFO, "run end"); } else { cout<<"Configuration file must be set!: "<<argv[0]<<" <config file>"<<endl<<std::flush; } } return 0; }