feat(initial): added portable mfem build system
This commit is contained in:
35
examples/meson.build
Normal file
35
examples/meson.build
Normal file
@@ -0,0 +1,35 @@
|
||||
example_deps = [mfem_dep, template_include_dep]
|
||||
example_build_rpath = mfem_runtime_prefix == '' ? '' : mfem_runtime_prefix / 'lib'
|
||||
example_install_rpath = ''
|
||||
if mfem_runtime_prefix != '' and not is_windows and not is_wasm
|
||||
example_install_rpath = host_machine.system() == 'darwin' ? '@loader_path/../lib' : '$ORIGIN/../lib'
|
||||
endif
|
||||
|
||||
serial_example = []
|
||||
parallel_example = []
|
||||
|
||||
if get_option('build_examples')
|
||||
serial_example = executable(
|
||||
'mfem-serial-poisson',
|
||||
'serial_poisson.cpp',
|
||||
dependencies: example_deps,
|
||||
override_options: ['cpp_std=' + mfem_consumer_cpp_std],
|
||||
build_rpath: example_build_rpath,
|
||||
install_rpath: example_install_rpath,
|
||||
install: true,
|
||||
install_tag: 'examples',
|
||||
)
|
||||
|
||||
if mfem_has_mpi
|
||||
parallel_example = executable(
|
||||
'mfem-parallel-hypre',
|
||||
'parallel_hypre.cpp',
|
||||
dependencies: example_deps,
|
||||
override_options: ['cpp_std=' + mfem_consumer_cpp_std],
|
||||
build_rpath: example_build_rpath,
|
||||
install_rpath: example_install_rpath,
|
||||
install: true,
|
||||
install_tag: 'examples',
|
||||
)
|
||||
endif
|
||||
endif
|
||||
80
examples/parallel_hypre.cpp
Normal file
80
examples/parallel_hypre.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include <meson_mfem_template/config.hpp>
|
||||
#include <mfem.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#if !MESON_MFEM_HAS_MPI || !MESON_MFEM_HAS_HYPRE
|
||||
#error "This example requires the MPI/Hypre capability"
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
mfem::Mpi::Init(argc, argv);
|
||||
mfem::Hypre::Init();
|
||||
const int rank = mfem::Mpi::WorldRank();
|
||||
const char *device_name = argc > 1 ? argv[1] : "cpu";
|
||||
mfem::Device device(device_name);
|
||||
|
||||
mfem::Mesh serial_mesh = mfem::Mesh::MakeCartesian2D(
|
||||
8, 8, mfem::Element::QUADRILATERAL, true, 1.0, 1.0);
|
||||
mfem::ParMesh mesh(MPI_COMM_WORLD, serial_mesh);
|
||||
serial_mesh.Clear();
|
||||
|
||||
mfem::H1_FECollection elements(2, mesh.Dimension());
|
||||
mfem::ParFiniteElementSpace space(&mesh, &elements);
|
||||
mfem::Array<int> essential_boundary(mesh.bdr_attributes.Max());
|
||||
essential_boundary = 1;
|
||||
mfem::Array<int> essential_dofs;
|
||||
space.GetEssentialTrueDofs(essential_boundary, essential_dofs);
|
||||
|
||||
mfem::ConstantCoefficient one(1.0);
|
||||
mfem::ParLinearForm rhs(&space);
|
||||
rhs.AddDomainIntegrator(new mfem::DomainLFIntegrator(one));
|
||||
rhs.Assemble();
|
||||
|
||||
mfem::ParGridFunction solution(&space);
|
||||
solution = 0.0;
|
||||
mfem::ParBilinearForm diffusion(&space);
|
||||
diffusion.AddDomainIntegrator(new mfem::DiffusionIntegrator(one));
|
||||
diffusion.Assemble();
|
||||
|
||||
mfem::OperatorPtr matrix;
|
||||
mfem::Vector linear_rhs;
|
||||
mfem::Vector linear_solution;
|
||||
diffusion.FormLinearSystem(
|
||||
essential_dofs, solution, rhs, matrix, linear_solution, linear_rhs);
|
||||
|
||||
mfem::HypreBoomerAMG boomer_amg;
|
||||
boomer_amg.SetPrintLevel(0);
|
||||
mfem::CGSolver solver(MPI_COMM_WORLD);
|
||||
solver.SetPreconditioner(boomer_amg);
|
||||
solver.SetOperator(*matrix);
|
||||
solver.SetRelTol(1e-10);
|
||||
solver.SetAbsTol(0.0);
|
||||
solver.SetMaxIter(300);
|
||||
solver.SetPrintLevel(0);
|
||||
solver.Mult(linear_rhs, linear_solution);
|
||||
diffusion.RecoverFEMSolution(linear_solution, rhs, solution);
|
||||
|
||||
#if MESON_MFEM_HAS_GSLIB
|
||||
mfem::FindPointsGSLIB find_points(MPI_COMM_WORLD);
|
||||
#endif
|
||||
#if MESON_MFEM_HAS_SUNDIALS
|
||||
mfem::CVODESolver cvode(MPI_COMM_WORLD, CV_BDF);
|
||||
#endif
|
||||
|
||||
const double local_norm = solution.Norml2();
|
||||
double global_norm = 0.0;
|
||||
MPI_Allreduce(&local_norm, &global_norm, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
|
||||
if (rank == 0)
|
||||
{
|
||||
std::cout << "MFEM parallel Poisson: ranks=" << mfem::Mpi::WorldSize()
|
||||
<< " global_dofs=" << space.GlobalTrueVSize()
|
||||
<< " norm_sum=" << global_norm
|
||||
<< " device=" << device_name << '\n';
|
||||
}
|
||||
return solver.GetConverged() && std::isfinite(global_norm) && global_norm > 0.0
|
||||
? 0
|
||||
: 2;
|
||||
}
|
||||
81
examples/serial_poisson.cpp
Normal file
81
examples/serial_poisson.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
#include <meson_mfem_template/config.hpp>
|
||||
#include <mfem.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *device_name = argc > 1 ? argv[1] :
|
||||
#if MESON_MFEM_HAS_CEED && !defined(__EMSCRIPTEN__)
|
||||
"ceed-cpu";
|
||||
#else
|
||||
"cpu";
|
||||
#endif
|
||||
mfem::Device device(device_name);
|
||||
|
||||
mfem::Mesh mesh = mfem::Mesh::MakeCartesian2D(
|
||||
6, 6, mfem::Element::QUADRILATERAL, true, 1.0, 1.0);
|
||||
const int dimension = mesh.Dimension();
|
||||
mfem::H1_FECollection elements(2, dimension);
|
||||
mfem::FiniteElementSpace space(&mesh, &elements);
|
||||
|
||||
mfem::Array<int> essential_boundary(mesh.bdr_attributes.Max());
|
||||
essential_boundary = 1;
|
||||
mfem::Array<int> essential_dofs;
|
||||
space.GetEssentialTrueDofs(essential_boundary, essential_dofs);
|
||||
|
||||
mfem::ConstantCoefficient one(1.0);
|
||||
mfem::LinearForm rhs(&space);
|
||||
rhs.AddDomainIntegrator(new mfem::DomainLFIntegrator(one));
|
||||
rhs.Assemble();
|
||||
|
||||
mfem::GridFunction solution(&space);
|
||||
solution = 0.0;
|
||||
|
||||
mfem::BilinearForm diffusion(&space);
|
||||
diffusion.AddDomainIntegrator(new mfem::DiffusionIntegrator(one));
|
||||
if (mfem::Device::Allows(mfem::Backend::CEED_MASK))
|
||||
{
|
||||
diffusion.SetAssemblyLevel(mfem::AssemblyLevel::PARTIAL);
|
||||
}
|
||||
diffusion.Assemble();
|
||||
|
||||
mfem::OperatorPtr matrix;
|
||||
mfem::Vector linear_rhs;
|
||||
mfem::Vector linear_solution;
|
||||
diffusion.FormLinearSystem(
|
||||
essential_dofs, solution, rhs, matrix, linear_solution, linear_rhs);
|
||||
|
||||
mfem::CGSolver solver;
|
||||
solver.SetOperator(*matrix);
|
||||
solver.SetRelTol(1e-12);
|
||||
solver.SetAbsTol(0.0);
|
||||
solver.SetMaxIter(200);
|
||||
solver.SetPrintLevel(0);
|
||||
solver.Mult(linear_rhs, linear_solution);
|
||||
diffusion.RecoverFEMSolution(linear_solution, rhs, solution);
|
||||
|
||||
#if MESON_MFEM_HAS_FMS
|
||||
mfem::FMSDataCollection fms_collection("meson-mfem-smoke", &mesh);
|
||||
fms_collection.SetProtocol("ascii");
|
||||
#endif
|
||||
|
||||
#if MESON_MFEM_HAS_ALGOIM
|
||||
mfem::FunctionCoefficient level_set(
|
||||
[](const mfem::Vector &point) { return point[0] + point[1] - 0.2; });
|
||||
mfem::AlgoimIntegrationRules algoim_rules(2, level_set, 2);
|
||||
mfem::IntegrationRule cut_rule;
|
||||
algoim_rules.GetVolumeIntegrationRule(
|
||||
*mesh.GetElementTransformation(0), cut_rule);
|
||||
if (cut_rule.GetNPoints() == 0)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
#endif
|
||||
|
||||
const double norm = solution.Norml2();
|
||||
std::cout << "MFEM serial Poisson: dofs=" << space.GetTrueVSize()
|
||||
<< " l2=" << norm << " device=" << device_name << '\n';
|
||||
return solver.GetConverged() && std::isfinite(norm) && norm > 0.0 ? 0 : 2;
|
||||
}
|
||||
Reference in New Issue
Block a user