87 lines
2.9 KiB
C++
87 lines
2.9 KiB
C++
// Copyright (c) 2010-2025, 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.
|
|
//
|
|
// This file is part of the MFEM library. For more information and source code
|
|
// availability visit https://mfem.org.
|
|
//
|
|
// MFEM is free software; you can redistribute it and/or modify it under the
|
|
// terms of the BSD-3 license. We welcome feedback and contributions, see file
|
|
// CONTRIBUTING.md for details.
|
|
|
|
#include "mfem.hpp"
|
|
#include "unit_tests.hpp"
|
|
|
|
using namespace mfem;
|
|
|
|
#ifdef MFEM_USE_MPI
|
|
|
|
TEST_CASE("ParGridFunction in Serial", "[ParGridFunction][Parallel]")
|
|
{
|
|
const int num_procs = Mpi::WorldSize();
|
|
const int my_rank = Mpi::WorldRank();
|
|
|
|
const int order = 1;
|
|
const int save_rank = 0;
|
|
|
|
const int n = 2 * num_procs;
|
|
Mesh mesh = Mesh::MakeCartesian2D(n, n, Element::QUADRILATERAL);
|
|
mesh.SetCurvature(2);
|
|
|
|
// Define a parallel mesh by a partitioning of the serial mesh.
|
|
ParMesh pmesh(MPI_COMM_WORLD, mesh);
|
|
H1_FECollection fec(order, mesh.Dimension());
|
|
ParFiniteElementSpace pfespace(&pmesh, &fec);
|
|
ParGridFunction px(&pfespace);
|
|
px.Randomize(1);
|
|
// Ensure that the L-DOFs are set consistently on all ranks
|
|
px.SetTrueVector();
|
|
px.SetFromTrueVector();
|
|
|
|
ConstantCoefficient zero(0.0);
|
|
const double l2_norm = px.ComputeL2Error(zero);
|
|
|
|
// Get the ParMesh and ParGridFunction on 1 of the mpi ranks. Check the
|
|
// L2 error on that rank and save grid function.
|
|
Mesh par_to_ser_mesh = pmesh.GetSerialMesh(save_rank);
|
|
GridFunction x_par_to_ser = px.GetSerialGridFunction(
|
|
save_rank, par_to_ser_mesh);
|
|
if (my_rank == save_rank)
|
|
{
|
|
const double par_to_ser_l2_norm = x_par_to_ser.ComputeL2Error(zero);
|
|
REQUIRE(par_to_ser_l2_norm == MFEM_Approx(l2_norm));
|
|
// Save to disk
|
|
par_to_ser_mesh.Save("parallel_in_serial.mesh");
|
|
}
|
|
|
|
{
|
|
FiniteElementSpace &fes = *x_par_to_ser.FESpace();
|
|
GridFunction x_par_to_ser_2 = px.GetSerialGridFunction(save_rank, fes);
|
|
x_par_to_ser_2 -= x_par_to_ser;
|
|
REQUIRE(x_par_to_ser_2.Normlinf() == MFEM_Approx(0.0));
|
|
}
|
|
|
|
// Save the mesh and then load the saved mesh and grid function, and check
|
|
// the L2 error on all ranks.
|
|
px.SaveAsSerial("parallel_in_serial.gf", 16, save_rank);
|
|
|
|
if (my_rank == save_rank)
|
|
{
|
|
Mesh par_to_ser_mesh_read = Mesh("parallel_in_serial.mesh");
|
|
named_ifgzstream gfstream("parallel_in_serial.gf");
|
|
GridFunction x_par_to_ser_read(&par_to_ser_mesh_read, gfstream);
|
|
const double par_to_ser_l2_read_norm = x_par_to_ser_read.ComputeL2Error(zero);
|
|
|
|
REQUIRE(par_to_ser_l2_read_norm == MFEM_Approx(l2_norm));
|
|
}
|
|
|
|
if (my_rank == save_rank)
|
|
{
|
|
// Clean up
|
|
REQUIRE(std::remove("parallel_in_serial.mesh") == 0);
|
|
REQUIRE(std::remove("parallel_in_serial.gf") == 0);
|
|
}
|
|
}
|
|
|
|
#endif // MFEM_USE_MPI
|