Commit b25f5b34 authored by Alexander Danilov's avatar Alexander Danilov

Tests: added pmesh_test001

Added simple Partitioner test.

Initial mesh is partitioned using one of available partiioners. Then
number of cell elements and connected components is computed.

Wiki page for this test:
https://github.com/INMOST-DEV/INMOST/wiki/5301-Partitioner-Components
parent c702e997
......@@ -5,4 +5,7 @@ endif(USE_SOLVER)
if(USE_MESH AND USE_MPI)
add_subdirectory(pmesh_test000)
endif()
\ No newline at end of file
if(USE_PARTITIONER)
add_subdirectory(pmesh_test001)
endif()
endif()
project(pmesh_test001)
set(SOURCE main.cpp)
add_executable(pmesh_test001 ${SOURCE})
target_link_libraries(pmesh_test001 inmost)
if(USE_MPI)
message("linking pmesh_test001 with MPI")
target_link_libraries(pmesh_test001 ${MPI_LIBRARIES})
if(MPI_LINK_FLAGS)
set_target_properties(pmesh_test001 PROPERTIES LINK_FLAGS "${MPI_LINK_FLAGS}")
endif()
endif(USE_MPI)
if(USE_PARTITIONER_ZOLTAN)
message("linking pmesh_test001 with Zoltan")
target_link_libraries(pmesh_test001 ${ZOLTAN_LIBRARIES})
endif()
if(USE_PARTITIONER_PARMETIS)
message("linking pmesh_test001 with ParMETIS")
target_link_libraries(pmesh_test001 ${PARMETIS_LIBRARIES})
endif()
if( USE_MPI AND EXISTS ${MPIEXEC} )
add_test(NAME pmesh_test001_internal_np_2 COMMAND ${MPIEXEC} -np 2 $<TARGET_FILE:pmesh_test001> ${CMAKE_CURRENT_SOURCE_DIR}/menger9x9x9.vtk 0)
add_test(NAME pmesh_test001_internal_np_4 COMMAND ${MPIEXEC} -np 4 $<TARGET_FILE:pmesh_test001> ${CMAKE_CURRENT_SOURCE_DIR}/menger9x9x9.vtk 0)
if(USE_PARTITIONER_PARMETIS)
add_test(NAME pmesh_test001_parmetis_partition_np_2 COMMAND ${MPIEXEC} -np 2 $<TARGET_FILE:pmesh_test001> ${CMAKE_CURRENT_SOURCE_DIR}/menger9x9x9.vtk 1 0)
add_test(NAME pmesh_test001_parmetis_partition_np_4 COMMAND ${MPIEXEC} -np 4 $<TARGET_FILE:pmesh_test001> ${CMAKE_CURRENT_SOURCE_DIR}/menger9x9x9.vtk 1 0)
endif()
if(USE_PARTITIONER_ZOLTAN)
add_test(NAME pmesh_test001_zoltan_hsfc_np_2 COMMAND ${MPIEXEC} -np 2 $<TARGET_FILE:pmesh_test001> ${CMAKE_CURRENT_SOURCE_DIR}/menger9x9x9.vtk 2)
add_test(NAME pmesh_test001_zoltan_hsfc_np_4 COMMAND ${MPIEXEC} -np 4 $<TARGET_FILE:pmesh_test001> ${CMAKE_CURRENT_SOURCE_DIR}/menger9x9x9.vtk 2)
add_test(NAME pmesh_test001_zoltan_rib_np_2 COMMAND ${MPIEXEC} -np 2 $<TARGET_FILE:pmesh_test001> ${CMAKE_CURRENT_SOURCE_DIR}/menger9x9x9.vtk 3)
add_test(NAME pmesh_test001_zoltan_rib_np_4 COMMAND ${MPIEXEC} -np 4 $<TARGET_FILE:pmesh_test001> ${CMAKE_CURRENT_SOURCE_DIR}/menger9x9x9.vtk 3)
add_test(NAME pmesh_test001_zoltan_rcb_np_2 COMMAND ${MPIEXEC} -np 2 $<TARGET_FILE:pmesh_test001> ${CMAKE_CURRENT_SOURCE_DIR}/menger9x9x9.vtk 4)
add_test(NAME pmesh_test001_zoltan_rcb_np_4 COMMAND ${MPIEXEC} -np 4 $<TARGET_FILE:pmesh_test001> ${CMAKE_CURRENT_SOURCE_DIR}/menger9x9x9.vtk 4)
add_test(NAME pmesh_test001_zoltan_phg_np_2 COMMAND ${MPIEXEC} -np 2 $<TARGET_FILE:pmesh_test001> ${CMAKE_CURRENT_SOURCE_DIR}/menger9x9x9.vtk 5)
add_test(NAME pmesh_test001_zoltan_phg_np_4 COMMAND ${MPIEXEC} -np 4 $<TARGET_FILE:pmesh_test001> ${CMAKE_CURRENT_SOURCE_DIR}/menger9x9x9.vtk 5)
endif()
endif()
#include "../../inmost.h"
using namespace INMOST;
// Compute number of connected components
int components(Mesh *m, Tag t)
{
if( m->NumberOfCells() == 0 ) return 0;
// We use marker to mark unknown cells;
MarkerType unknown = m->CreateMarker();
if( unknown == InvalidMarker() ) return -1;
// Last-In-First-Out structure for searching connected components
ElementArray<Cell> lifo(m);
Cell lastcell;
int comp = 0, color = m->GetProcessorRank();
// Mark all cells
for(Mesh::iteratorCell it = m->BeginCell(); it != m->EndCell(); ++it)
{
it->SetMarker(unknown);
lastcell = it->getAsCell();
}
// Start with one cell
lifo.push_back(lastcell);
while( lifo.size() > 0 )
{
while( lifo.size() > 0 )
{
// Get last cell
lastcell = lifo.back();
lastcell->Integer(t) = color;
lifo.pop_back();
// Unmark cell
lastcell->RemMarker(unknown);
// Add all unknown neighbours
ElementArray<Cell> neighbours = lastcell->BridgeAdjacencies2Cell(FACE,unknown);
for(ElementArray<Cell>::iterator it = neighbours.begin(); it != neighbours.end(); ++it)
{
lifo.push_back(it->getAsCell());
}
}
// Connected component is closed
comp++;
color+=m->GetProcessorsNumber();
// Check if there are still unknown cells
for(Mesh::iteratorCell it = m->BeginCell(); it != m->EndCell(); ++it)
{
if( it->GetMarker(unknown) )
{
lastcell = it->getAsCell();
break;
}
}
if( lastcell->GetMarker(unknown) ) lifo.push_back(lastcell);
}
m->ReleaseMarker(unknown);
return comp;
}
int main(int argc,char ** argv)
{
if( argc < 3 )
{
std::cout << "Usage: " << argv[0] << " input.[p]vtk type [action]" << std::endl << std::endl
<< "type: " << std::endl
<< "0 - Inner_RCM" << std::endl
<< "1 - Parmetis" << std::endl
<< "2 - Zoltan_HSFC" << std::endl
<< "3 - Zoltan_RIB" << std::endl
<< "4 - Zoltan_RCB" << std::endl
<< "5 - Zoltan_PHG" << std::endl
<< "6 - Zoltan_Scotch" << std::endl
<< "7 - Zoltan_Parmetis" << std::endl
<< "-1 - No partitioner" << std::endl << std::endl
<< "action (for Parmetis): " << std::endl
<< "0 - Partition" << std::endl
<< "1 - Repartition" << std::endl
<< "2 - Refine" << std::endl;
return 0;
}
Mesh::Initialize(&argc,&argv);
Partitioner::Initialize(&argc,&argv);
Mesh * m = new Mesh(); // Create an empty mesh
m->SetCommunicator(INMOST_MPI_COMM_WORLD); // Set the MPI communicator for the mesh
int rank = m->GetProcessorRank(), nproc = m->GetProcessorsNumber();
if( rank == 0 || m->isParallelFileFormat(argv[1]) ) m->Load(argv[1]); // Load input mesh
int itype = atoi(argv[2]), iaction = 0;
if( argc > 3 ) iaction = atoi(argv[3]);
Partitioner::Type type;
switch(itype)
{
case 0: type = Partitioner::Inner_RCM; break;
case 1: type = Partitioner::Parmetis; break;
case 2: type = Partitioner::Zoltan_HSFC; break;
case 3: type = Partitioner::Zoltan_RIB; break;
case 4: type = Partitioner::Zoltan_RCB; break;
case 5: type = Partitioner::Zoltan_PHG; break;
case 6: type = Partitioner::Zoltan_Scotch; break;
case 7: type = Partitioner::Zoltan_Parmetis; break;
}
Partitioner::Action action;
switch(iaction)
{
case 0: action = Partitioner::Partition; break;
case 1: action = Partitioner::Repartition; break;
case 2: action = Partitioner::Refine; break;
}
if( itype >= 0 )
{
Partitioner * p = new Partitioner(m);
p->SetMethod(type,action); // Specify the partitioner
p->Evaluate(); // Compute the partitioner and store new processor ID in the mesh
delete p;
m->RemoveGhost(); // Delete all ghost cells
m->Redistribute(); // Redistribute the mesh data
m->ReorderEmpty(CELL|FACE|EDGE|NODE); // Clean the data after reordring
}
Tag c = m->CreateTag("Comp",DATA_INTEGER,CELL,NONE,1);
std::cout << "Proc " << rank << ": " << m->NumberOfCells() << " cells, " << components(m,c) << " components" << std::endl;
int maxcells = m->AggregateMax(m->NumberOfCells());
if( rank == 0 ) std::cout << "Max number of cells per proc: " << maxcells << std::endl;
// m->Save("dump.pvtk"); // Save mesh for visualization
delete m;
Partitioner::Finalize();
Mesh::Finalize();
return 0;
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment