Compare commits

...
1 Commits
Author SHA1 Message Date
Ketan Mittal 917f537f74 initial commit with parRSB working 2021-08-17 09:11:41 -07:00
10 changed files with 402 additions and 9 deletions
+3
View File
@@ -144,6 +144,9 @@
// Enable MFEM functionality based on the GSLIB library
// #define MFEM_USE_GSLIB
// Enable MFEM functionality based on the PARRSB library
// #define MFEM_USE_PARRSB
// Build the NVIDIA GPU/CUDA-enabled version of the MFEM library.
// Requires a CUDA compiler (nvcc).
// #define MFEM_USE_CUDA
+1
View File
@@ -48,6 +48,7 @@ MFEM_USE_CONDUIT = @MFEM_USE_CONDUIT@
MFEM_USE_PUMI = @MFEM_USE_PUMI@
MFEM_USE_HIOP = @MFEM_USE_HIOP@
MFEM_USE_GSLIB = @MFEM_USE_GSLIB@
MFEM_USE_PARRSB = @MFEM_USE_PARRSB@
MFEM_USE_CUDA = @MFEM_USE_CUDA@
MFEM_USE_HIP = @MFEM_USE_HIP@
MFEM_USE_RAJA = @MFEM_USE_RAJA@
+6
View File
@@ -141,6 +141,7 @@ MFEM_USE_CONDUIT = NO
MFEM_USE_PUMI = NO
MFEM_USE_HIOP = NO
MFEM_USE_GSLIB = NO
MFEM_USE_PARRSB = NO
MFEM_USE_CUDA = NO
MFEM_USE_HIP = NO
MFEM_USE_RAJA = NO
@@ -411,6 +412,11 @@ GSLIB_DIR = @MFEM_DIR@/../gslib/build
GSLIB_OPT = -I$(GSLIB_DIR)/include
GSLIB_LIB = -L$(GSLIB_DIR)/lib -lgs
# PARRSB library
PARRSB_DIR = @MFEM_DIR@/../parRSB/build
PARRSB_OPT = -I$(PARRSB_DIR)/include
PARRSB_LIB = -L$(PARRSB_DIR)/lib -lparRSB
# CUDA library configuration
CUDA_OPT =
CUDA_LIB = -lcusparse
+3 -3
View File
@@ -1,9 +1,9 @@
MFEM INLINE mesh v1.0
type = hex
nx = 4
ny = 4
nz = 4
nx = 6
ny = 6
nz = 6
sx = 1.0
sy = 1.0
sz = 1.0
+2 -2
View File
@@ -1,7 +1,7 @@
MFEM INLINE mesh v1.0
type = quad
nx = 4
ny = 4
nx = 114
ny = 114
sx = 1.0
sy = 1.0
+2 -2
View File
@@ -1,7 +1,7 @@
MFEM INLINE mesh v1.0
type = tri
nx = 4
ny = 4
nx = 5
ny = 6
sx = 1.0
sy = 1.0
+122
View File
@@ -23,6 +23,7 @@
namespace gslib
{
#include "gslib.h"
#include "parRSBCPP.h"
}
#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
@@ -1000,4 +1001,125 @@ void OversetFindPointsGSLIB::Interpolate(const Vector &point_pos,
} // namespace mfem
#ifdef MFEM_USE_PARRSB
namespace mfem
{
MFEMPARRSB::~MFEMPARRSB()
{
//delete gsl_comm;
//delete cr;
}
void MFEMPARRSB::GetPartitioningSerial(MPI_Comm comm, Array<int> &partition)
{
MFEM_VERIFY(serial, " Initialize with serial mesh.");
Array<long long> vertglob;
int geomtype = m->GetElementBaseGeometry(0);
int nvert;
if (geomtype == Geometry::SQUARE) {
nvert = 4;
}
else if (geomtype == Geometry::TRIANGLE) {
nvert = 3;
}
else if (geomtype == Geometry::CUBE) {
nvert = 8;
}
else if (geomtype == Geometry::TETRAHEDRON) {
nvert = 4;
}
else {
MFEM_ABORT(" Geometry type not currently supported.");
}
Vector coord(m->GetNE()*nvert*m->Dimension());
int n = 0;
for (int i = 0; i < m->GetNE(); i++) {
Array<int> vert;
m->GetElementVertices(i, vert);
for (int j = 0; j < vert.Size(); j++) {
vertglob.Append(vert[j]);
double *pos = m->GetVertex(vert[j]);
for (int d = 0; d < m->Dimension(); d++) {
coord[n++] = pos[d];
}
}
}
int myid;
MPI_Comm_rank(comm, &myid);
int nel = m->GetNE();
partition.SetSize(m->GetNE());
if (myid != 0) {
//vertglob.SetSize(0);
//coord.SetSize(0);
nel = 0;
//partition.SetSize(0);
}
gslib::parrsb_options options = gslib::parrsb_default_options;
parRSB_partMesh(partition, NULL, vertglob.GetData(),
coord.GetData(), nel, nvert, options, comm);
partition.SetSize(m->GetNE());
MPI_Bcast(partition.GetData(), partition.Size(), MPI_INT, 0, comm);
}
void MFEMPARRSB::GetPartitioningParallel(Array<int> &partition)
{
MFEM_VERIFY(!serial, " Initialize with parallel mesh.");
Array<long long> vertglob;
int geomtype = pm->GetElementBaseGeometry(0);
int nvert;
if (geomtype == Geometry::SQUARE) {
nvert = 4;
}
else if (geomtype == Geometry::TRIANGLE) {
nvert = 3;
}
else if (geomtype == Geometry::CUBE) {
nvert = 8;
}
else if (geomtype == Geometry::TETRAHEDRON) {
nvert = 4;
}
else {
MFEM_ABORT(" Geometry type not currently supported.");
}
Vector coord(pm->GetNE()*nvert*pm->Dimension());
Array<HYPRE_Int> gi;
pm->GetGlobalVertexIndices(gi);
int n = 0;
for (int i = 0; i < pm->GetNE(); i++) {
Array<int> vert;
pm->GetElementVertices(i, vert);
for (int j = 0; j < vert.Size(); j++) {
vertglob.Append(gi[vert[j]]);
double *pos = pm->GetVertex(vert[j]);
for (int d = 0; d < pm->Dimension(); d++) {
coord[n++] = pos[d];
}
}
}
partition.SetSize(pm->GetNE());
partition = -1;
gslib::parrsb_options options = gslib::parrsb_default_options;
parRSB_partMesh(partition, NULL, vertglob.GetData(),
coord.GetData(), pm->GetNE(), nvert, options ,pm->GetComm());
}
void MFEMPARRSB::FreeData()
{
}
}
#endif // MFEM_USE_PARRSB
#endif // MFEM_USE_GSLIB
+35
View File
@@ -14,6 +14,7 @@
#include "../config/config.hpp"
#include "gridfunc.hpp"
#include "../mesh/pmesh.hpp"
#ifdef MFEM_USE_GSLIB
@@ -248,6 +249,40 @@ public:
} // namespace mfem
#ifdef MFEM_USE_PARRSB
namespace mfem
{
class MFEMPARRSB
{
public:
Mesh *m;
#ifdef MFEM_USE_MPI
ParMesh *pm;
#endif
bool serial;
public:
MFEMPARRSB(Mesh &mesh) : m(&mesh), serial(true) { };
#ifdef MFEM_USE_MPI
MFEMPARRSB(ParMesh &pmesh) : pm(&pmesh), serial(false) { };
#endif
~MFEMPARRSB();
void GetPartitioningSerial(MPI_Comm comm, Array<int> &partition);
void GetPartitioningParallel(Array<int> &partition);
void FreeData();
};
}
#endif // MFEM_USE_PARRSB
#endif // MFEM_USE_GSLIB
#endif // MFEM_GSLIB
+3 -2
View File
@@ -273,7 +273,7 @@ endif
# List of MFEM dependencies, that require the *_LIB variable to be non-empty
MFEM_REQ_LIB_DEPS = SUPERLU MUMPS METIS FMS CONDUIT SIDRE LAPACK SUNDIALS MESQUITE\
SUITESPARSE STRUMPACK GINKGO GNUTLS NETCDF PETSC SLEPC MPFR PUMI HIOP GSLIB\
SUITESPARSE STRUMPACK GINKGO GNUTLS NETCDF PETSC SLEPC MPFR PUMI HIOP GSLIB PARRSB\
OCCA CEED RAJA UMPIRE MKL_CPARDISO AMGX CALIPER
PETSC_ERROR_MSG = $(if $(PETSC_FOUND),,. PETSC config not found: $(PETSC_VARS))
@@ -337,7 +337,7 @@ MFEM_DEFINES = MFEM_VERSION MFEM_VERSION_STRING MFEM_GIT_STRING MFEM_USE_MPI\
MFEM_USE_MESQUITE MFEM_USE_SUITESPARSE MFEM_USE_GINKGO MFEM_USE_SUPERLU\
MFEM_USE_STRUMPACK MFEM_USE_GNUTLS MFEM_USE_NETCDF MFEM_USE_PETSC\
MFEM_USE_SLEPC MFEM_USE_MPFR MFEM_USE_SIDRE MFEM_USE_FMS MFEM_USE_CONDUIT\
MFEM_USE_PUMI MFEM_USE_HIOP MFEM_USE_GSLIB MFEM_USE_CUDA MFEM_USE_HIP\
MFEM_USE_PUMI MFEM_USE_HIOP MFEM_USE_GSLIB MFEM_USE_PARRSB MFEM_USE_CUDA MFEM_USE_HIP\
MFEM_USE_OCCA MFEM_USE_CEED MFEM_USE_RAJA MFEM_USE_UMPIRE MFEM_USE_SIMD\
MFEM_USE_ADIOS2 MFEM_USE_MKL_CPARDISO MFEM_USE_AMGX MFEM_USE_MUMPS\
MFEM_USE_CALIPER MFEM_SOURCE_DIR MFEM_INSTALL_DIR
@@ -668,6 +668,7 @@ status info:
$(info MFEM_USE_PUMI = $(MFEM_USE_PUMI))
$(info MFEM_USE_HIOP = $(MFEM_USE_HIOP))
$(info MFEM_USE_GSLIB = $(MFEM_USE_GSLIB))
$(info MFEM_USE_PARRSB = $(MFEM_USE_PARRSB))
$(info MFEM_USE_CUDA = $(MFEM_USE_CUDA))
$(info MFEM_USE_HIP = $(MFEM_USE_HIP))
$(info MFEM_USE_RAJA = $(MFEM_USE_RAJA))
+225
View File
@@ -0,0 +1,225 @@
// Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// Compile with: make parrsb
//
// Sample runs:
// mpirun -np 4 parrsb -m ../../data/inline-quad.mesh
// mpirun -np 4 parrsb -m ../../data/inline-hex.mesh
// mpirun -np 4 parrsb -m ../../data/armadillo.vtk
#include "../../mfem.hpp"
using namespace mfem;
using namespace std;
int main (int argc, char *argv[])
{
// Initialize MPI.
int num_procs, myid;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
// Set the method's default parameters.
const char *mesh_file = "../../data/rt-2d-q3.mesh";
int order = 3;
int mesh_poly_deg = 3;
int rs_levels = 0;
int rp_levels = 0;
bool visualization = false;
int fieldtype = 0;
int ncomp = 1;
// Parse command-line options.
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree).");
args.AddOption(&mesh_poly_deg, "-mo", "--mesh-order",
"Polynomial degree of mesh finite element space.");
args.AddOption(&rs_levels, "-rs", "--refine-serial",
"Number of times to refine the mesh uniformly in serial.");
args.AddOption(&rp_levels, "-rp", "--refine-parallel",
"Number of times to refine the mesh uniformly in parallel.");
args.AddOption(&fieldtype, "-ft", "--field-type",
"Field type: 0 - H1, 1 - L2, 2 - H(div), 3 - H(curl).");
args.AddOption(&ncomp, "-nc", "--ncomp",
"Number of components for H1 or L2 GridFunctions");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.Parse();
if (!args.Good())
{
args.PrintUsage(cout);
return 1;
}
if (myid == 0) { args.PrintOptions(cout); }
// Initialize and refine the starting mesh.
Mesh *mesh = new Mesh(mesh_file, 1, 1, false);
for (int lev = 0; lev < rs_levels; lev++) { mesh->UniformRefinement(); }
const int dim = mesh->Dimension();
if (myid == 0)
{
cout << "Mesh curvature of the original mesh: ";
if (mesh->GetNodes()) { cout << mesh->GetNodes()->OwnFEC()->Name(); }
else { cout << "(NONE)"; }
cout << endl;
}
// Mesh bounding box (for the full serial mesh).
Vector pos_min, pos_max;
MFEM_VERIFY(mesh_poly_deg > 0, "The order of the mesh must be positive.");
mesh->GetBoundingBox(pos_min, pos_max, mesh_poly_deg);
if (myid == 0)
{
cout << "--- Generating equidistant point for:\n"
<< "x in [" << pos_min(0) << ", " << pos_max(0) << "]\n"
<< "y in [" << pos_min(1) << ", " << pos_max(1) << "]\n";
if (dim == 3)
{
cout << "z in [" << pos_min(2) << ", " << pos_max(2) << "]\n";
}
}
// Distribute the mesh.
//mesh->EnsureNCMesh();
ParMesh pmesh(MPI_COMM_WORLD, *mesh);
int nel = pmesh.GetNE();
int nel_min, nel_max;
MPI_Allreduce(&nel, &nel_min, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
MPI_Allreduce(&nel, &nel_max, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
if (myid == 0) {
std::cout << nel_max << " " << nel_min << " METIS-NELMAX-NELMIN\n";
}
// Curve the mesh based on the chosen polynomial degree.
L2_FECollection fecm(0, dim);
ParFiniteElementSpace pfespace(&pmesh, &fecm);
ParGridFunction x(&pfespace);
for (int i = 0; i < pmesh.GetNE(); i++) {
x(i) = myid;
}
if (visualization) {
char vishost[] = "localhost";
int visport = 19916;
socketstream sout;
sout.open(vishost, visport);
sout << "parallel " << num_procs << " " << myid << "\n";
sout.precision(8);
sout << "solution\n" << pmesh << x;
if (myid == 0)
{
sout << "window_title 'Default partitioning'\n"
<< "window_geometry "
<< 00 << " " << 0 << " " << 400 << " " << 400 << "\n"
<< "keys jRmclA" << endl;
}
}
MFEMPARRSB parrsb = MFEMPARRSB(pmesh);
Array<int> partition;
parrsb.GetPartitioningParallel(partition);
for (int i = 0; i < pmesh.GetNE(); i++) {
x(i) = partition[i];
}
if (visualization) {
char vishost[] = "localhost";
int visport = 19916;
socketstream sout;
sout.open(vishost, visport);
sout << "parallel " << num_procs << " " << myid << "\n";
sout.precision(8);
sout << "solution\n" << pmesh << x;
if (myid == 0)
{
sout << "window_title 'ParRSB'\n"
<< "window_geometry "
<< 400 << " " << 0 << " " << 400 << " " << 400 << "\n"
<< "keys jRmclA" << endl;
}
}
MFEMPARRSB parrsb2 = MFEMPARRSB(*mesh);
parrsb2.GetPartitioningSerial(MPI_COMM_WORLD, partition);
ParMesh pmesh2(MPI_COMM_WORLD, *mesh, partition);
ParFiniteElementSpace pfespace2(&pmesh2, &fecm);
ParGridFunction x2(&pfespace2);
for (int i = 0; i < pmesh2.GetNE(); i++) {
x2(i) = myid;
}
if (visualization) {
char vishost[] = "localhost";
int visport = 19916;
socketstream sout;
sout.open(vishost, visport);
sout << "parallel " << num_procs << " " << myid << "\n";
sout.precision(8);
sout << "solution\n" << pmesh2 << x2;
if (myid == 0)
{
sout << "window_title 'ParRSB Serial'\n"
<< "window_geometry "
<< 800 << " " << 0 << " " << 400 << " " << 400 << "\n"
<< "keys jRmclA" << endl;
}
}
//mesh->EnsureNCMesh();
partition.SetSize(mesh->GetNE());
for (int i = 0; i < mesh->GetNE(); i++) {
partition[i] = i % num_procs;
}
ParMesh pmesh3(MPI_COMM_WORLD, *mesh, partition);
MFEMPARRSB parrsb3 = MFEMPARRSB(pmesh3);
parrsb3.GetPartitioningParallel(partition);
ParFiniteElementSpace pfespace3(&pmesh3, &fecm);
ParGridFunction x3(&pfespace3);
for (int i = 0; i < pmesh3.GetNE(); i++) {
x3(i) = partition[i];
}
if (visualization) {
char vishost[] = "localhost";
int visport = 19916;
socketstream sout;
sout.open(vishost, visport);
sout << "parallel " << num_procs << " " << myid << "\n";
sout.precision(8);
sout << "solution\n" << pmesh3 << x3;
if (myid == 0)
{
sout << "window_title 'Manual partition then parRSB'\n"
<< "window_geometry "
<< 400 << " " << 0 << " " << 400 << " " << 400 << "\n"
<< "keys jRmclA" << endl;
}
}
MPI_Finalize();
return 0;
}