diff --git a/include/bout/field_factory.hxx b/include/bout/field_factory.hxx index 2a20226b2e..149fe265f0 100644 --- a/include/bout/field_factory.hxx +++ b/include/bout/field_factory.hxx @@ -29,8 +29,6 @@ class FieldFactory; #ifndef BOUT_FIELD_FACTORY_H #define BOUT_FIELD_FACTORY_H -#include "bout/mesh.hxx" - #include "bout/sys/expressionparser.hxx" #include "bout/field2d.hxx" @@ -43,8 +41,9 @@ class FieldFactory; #include #include -// Utility routines to create generators from values +class Mesh; +// Utility routines to create generators from values FieldGeneratorPtr generator(BoutReal value); FieldGeneratorPtr generator(BoutReal* ptr); @@ -95,6 +94,8 @@ public: /// Get the Singleton object static FieldFactory* get(); + /// Set the Mesh on the singleton + static FieldFactory* setMesh(Mesh* mesh); /// clean the cache of parsed strings void cleanCache(); diff --git a/include/bout/mesh.hxx b/include/bout/mesh.hxx index b5a51015df..e4cf520848 100644 --- a/include/bout/mesh.hxx +++ b/include/bout/mesh.hxx @@ -121,13 +121,6 @@ public: /// @param[in] opt Input options. Default is "mesh" section static Mesh* create(Options* opt = nullptr); - /// Loads the mesh values - /// - /// Currently need to create and load mesh in separate calls - /// because creating Fields uses the global "mesh" pointer - /// which isn't created until Mesh is constructed - virtual int load() { return 1; } - /// Add output variables to \p output_options /// These are used for post-processing virtual void outputVars([[maybe_unused]] Options& output_options) {} diff --git a/manual/sphinx/developer_docs/mesh.rst b/manual/sphinx/developer_docs/mesh.rst index ff3e40d4b0..e1eca6172b 100644 --- a/manual/sphinx/developer_docs/mesh.rst +++ b/manual/sphinx/developer_docs/mesh.rst @@ -31,13 +31,11 @@ Loading a mesh The `Mesh constructor ` takes `GridDataSource` and `Options` objects. You can also call `Mesh::create` with just one of these objects, which will call out to the `MeshFactory` singleton to -create a mesh "automatically". This is the way that it is done in -:doc:`bout++.cxx <../_breathe_autogen/file/bout_09_09_8cxx>`. Once you -have instantiated a `Mesh` object, you can then call `Mesh::load` to -read in all the appropriate variables from the `GridDataSource`:: +create a mesh, reading in all the appropriate variables from the +`GridDataSource` and/or `Options`. This is the way that it is done in +:doc:`bout++.cxx <../_breathe_autogen/file/bout_09_09_8cxx>`:: mesh = Mesh::create(); ///< Create the mesh - mesh->load(); ///< Load from sources. Required for Field initialisation For post-processing of the results, it’s useful to have mesh quantities in the dump files along with the results. To do this, diff --git a/src/bout++.cxx b/src/bout++.cxx index 48ab96298b..f7e1810b20 100644 --- a/src/bout++.cxx +++ b/src/bout++.cxx @@ -198,8 +198,6 @@ int BoutInitialise(int& argc, char**& argv) { // Create the mesh bout::globals::mesh = Mesh::create(); - // Load from sources. Required for Field initialisation - bout::globals::mesh->load(); // time_report options are used in BoutFinalise, i.e. after we // check for unused options @@ -312,7 +310,6 @@ template // We might need a global mesh for some types, so best make one bout::globals::mpi = new MpiWrapper(); bout::globals::mesh = Mesh::create(); - bout::globals::mesh->load(); // An empty Options that we'll later check for used values Options help_options; diff --git a/src/field/field_factory.cxx b/src/field/field_factory.cxx index f65f2e7f55..3a143ec321 100644 --- a/src/field/field_factory.cxx +++ b/src/field/field_factory.cxx @@ -485,4 +485,9 @@ FieldFactory* FieldFactory::get() { return &instance; } +FieldFactory* FieldFactory::setMesh(Mesh* mesh) { + get()->fieldmesh = mesh; + return get(); +} + void FieldFactory::cleanCache() { cache.clear(); } diff --git a/src/mesh/impls/bout/boutmesh.cxx b/src/mesh/impls/bout/boutmesh.cxx index 8917fa3753..ce6c6051b1 100644 --- a/src/mesh/impls/bout/boutmesh.cxx +++ b/src/mesh/impls/bout/boutmesh.cxx @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -49,7 +50,11 @@ #define PVEC_REAL_MPI_TYPE MPI_DOUBLE BoutMesh::BoutMesh(GridDataSource* s, Options* opt) : Mesh(s, opt) { + TRACE("BoutMesh::BoutMesh()"); + output_progress << _("Loading mesh") << endl; + OPTION(options, symmetricGlobalX, true); + if (!options->isSet("symmetricGlobalY")) { std::string optionfile = Options::root()["optionfile"].withDefault("BOUT.inp"); output_warn << "WARNING: The default of this option has changed in release 4.1.\n\ @@ -64,6 +69,197 @@ If you want the old setting, you have to specify mesh:symmetricGlobalY=false in comm_outer = MPI_COMM_NULL; mpi = bout::globals::mpi; + + // Use root level options + auto& options = Options::root(); + + FieldFactory::setMesh(this); + ////////////// + // Number of processors + + MPI_Comm_size(BoutComm::get(), &NPES); + MPI_Comm_rank(BoutComm::get(), &MYPE); + + ////////////// + // Grid sizes + + if (Mesh::get(nx, "nx") != 0) { + throw BoutException(_("Mesh must contain nx")); + } + + if (Mesh::get(ny, "ny") != 0) { + throw BoutException(_("Mesh must contain ny")); + } + + if (Mesh::get(nz, "nz") != 0) { + // No "nz" variable in the grid file. Instead read MZ from options + + OPTION(options, MZ, 64); + OPTION(options, nz, MZ); + ASSERT0(nz == MZ); + if (!is_pow2(nz)) { + // Should be a power of 2 for efficient FFTs + output_warn.write( + _("WARNING: Number of toroidal points should be 2^n for efficient " + "FFT performance -- consider changing MZ ({:d}) if using FFTs\n"), + nz); + } + } else { + MZ = nz; + output_info.write(_("\tRead nz from input grid file\n")); + } + + output_info << _("\tGrid size: ") << nx << " x " << ny << " x " << nz << endl; + + // Get guard cell sizes + // Try to read from grid file first, then if not found + // get from options + if (Mesh::get(MXG, "MXG") != 0) { + // Error code returned + MXG = options["MXG"].doc("Number of guard cells on each side in X").withDefault(2); + } + ASSERT0(MXG >= 0); + + if (Mesh::get(MYG, "MYG") != 0) { + MYG = options["MYG"].doc("Number of guard cells on each side in Y").withDefault(2); + } + ASSERT0(MYG >= 0); + + // For now only support no z-guard cells + MZG = 0; + ASSERT0(MZG >= 0); + + // For now don't parallelise z + NZPE = 1; + + output_info << _("\tGuard cells (x,y,z): ") << MXG << ", " << MYG << ", " << MZG + << std::endl; + + // separatrix location + Mesh::get(ixseps1, "ixseps1", nx); + Mesh::get(ixseps2, "ixseps2", nx); + Mesh::get(jyseps1_1, "jyseps1_1", -1); + Mesh::get(jyseps1_2, "jyseps1_2", ny / 2); + Mesh::get(jyseps2_1, "jyseps2_1", jyseps1_2); + Mesh::get(jyseps2_2, "jyseps2_2", ny - 1); + Mesh::get(ny_inner, "ny_inner", jyseps2_1); + + // Check inputs + setYDecompositionIndices(jyseps1_1, jyseps2_1, jyseps1_2, jyseps2_2, ny_inner); + + if (options.isSet("NXPE") or options.isSet("NYPE")) { + chooseProcessorSplit(options); + } else { + findProcessorSplit(); + } + + // Get X and Y processor indices + PE_YIND = MYPE / NXPE; + PE_XIND = MYPE % NXPE; + + // Set the other grid sizes from nx, ny, nz + setDerivedGridSizes(); + + /// Get mesh options + OPTION(options, IncIntShear, false); + periodicX = options["periodicX"].doc("Make grid periodic in X?").withDefault(false); + + async_send = options["async_send"] + .doc("Whether to use asyncronous MPI sends") + .withDefault(false); + + if (options.isSet("zperiod")) { + OPTION(options, zperiod, 1); + ZMIN = 0.0; + ZMAX = 1.0 / static_cast(zperiod); + } else { + OPTION(options, ZMIN, 0.0); + OPTION(options, ZMAX, 1.0); + + zperiod = ROUND(1.0 / (ZMAX - ZMIN)); + } + + ///////////////////// TOPOLOGY ////////////////////////// + /// Call topology to set layout of grid + topology(); + + TwistShift = options["twistshift"] + .doc("Apply a Twist-Shift boundary using ShiftAngle?") + .withDefault(false); + + // Try to read the shift angle from the grid file + // NOTE: All processors should know the twist-shift angle (for invert_parderiv) + // NOTE: Always read ShiftAngle as Coordinates will use hasBranchCutLower and + // hasBranchCutUpper to set zShift for ShiftedMetric + + ShiftAngle.resize(LocalNx); + + if (!source->get(this, ShiftAngle, "ShiftAngle", LocalNx, getGlobalXIndex(0))) { + ShiftAngle.clear(); + } + + if (TwistShift) { + output_info.write("Applying Twist-Shift condition. Interpolation: FFT\n"); + if (ShiftAngle.empty()) { + throw BoutException("ERROR: Twist-shift angle 'ShiftAngle' not found. " + "Required when TwistShift==true."); + } + } + + ////////////////////////////////////////////////////// + /// Communicator + + createCommunicators(); + output_debug << "Got communicators" << endl; + + ////////////////////////////////////////////////////// + // Boundary regions + createXBoundaries(); + createYBoundaries(); + + auto possible_boundaries = BoutMesh::getPossibleBoundaries(); + if (possible_boundaries.empty()) { + output_info.write(_("No boundary regions; domain is periodic\n")); + } else { + output_info.write(_("Possible boundary regions are: ")); + for (const auto& boundary : possible_boundaries) { + output_info.write("{}, ", boundary); + } + } + + if (!boundary.empty()) { + output_info << _("Boundary regions in this processor: "); + for (const auto& bndry : boundary) { + output_info << bndry->label << ", "; + } + output_info << endl; + } else { + output_info << _("No boundary regions in this processor") << endl; + } + + output_info << _("Constructing default regions") << endl; + createDefaultRegions(); + + // Add boundary regions + addBoundaryRegions(); + + // Set cached values + { + int mybndry = static_cast(!(BoutMesh::iterateBndryLowerY().isDone())); + int allbndry = 0; + mpi->MPI_Allreduce(&mybndry, &allbndry, 1, MPI_INT, MPI_BOR, + BoutMesh::getXcomm(yend)); + has_boundary_lower_y = static_cast(allbndry); + } + { + int mybndry = static_cast(!(BoutMesh::iterateBndryUpperY().isDone())); + int allbndry = 0; + mpi->MPI_Allreduce(&mybndry, &allbndry, 1, MPI_INT, MPI_BOR, + BoutMesh::getXcomm(ystart)); + has_boundary_upper_y = static_cast(allbndry); + } + + output_info.write(_("\tdone\n")); } BoutMesh::~BoutMesh() { @@ -430,205 +626,6 @@ void BoutMesh::setDerivedGridSizes() { MapCountZ = MZSUB; } -int BoutMesh::load() { - TRACE("BoutMesh::load()"); - - output_progress << _("Loading mesh") << endl; - - // Use root level options - auto& options = Options::root(); - - ////////////// - // Number of processors - - MPI_Comm_size(BoutComm::get(), &NPES); - MPI_Comm_rank(BoutComm::get(), &MYPE); - - ////////////// - // Grid sizes - - if (Mesh::get(nx, "nx") != 0) { - throw BoutException(_("Mesh must contain nx")); - } - - if (Mesh::get(ny, "ny") != 0) { - throw BoutException(_("Mesh must contain ny")); - } - - if (Mesh::get(nz, "nz") != 0) { - // No "nz" variable in the grid file. Instead read MZ from options - - OPTION(options, MZ, 64); - OPTION(options, nz, MZ); - ASSERT0(nz == MZ); - if (!is_pow2(nz)) { - // Should be a power of 2 for efficient FFTs - output_warn.write( - _("WARNING: Number of toroidal points should be 2^n for efficient " - "FFT performance -- consider changing MZ ({:d}) if using FFTs\n"), - nz); - } - } else { - MZ = nz; - output_info.write(_("\tRead nz from input grid file\n")); - } - - output_info << _("\tGrid size: ") << nx << " x " << ny << " x " << nz << endl; - - // Get guard cell sizes - // Try to read from grid file first, then if not found - // get from options - if (Mesh::get(MXG, "MXG") != 0) { - // Error code returned - MXG = options["MXG"].doc("Number of guard cells on each side in X").withDefault(2); - } - ASSERT0(MXG >= 0); - - if (Mesh::get(MYG, "MYG") != 0) { - MYG = options["MYG"].doc("Number of guard cells on each side in Y").withDefault(2); - } - ASSERT0(MYG >= 0); - - // For now only support no z-guard cells - MZG = 0; - ASSERT0(MZG >= 0); - - // For now don't parallelise z - NZPE = 1; - - output_info << _("\tGuard cells (x,y,z): ") << MXG << ", " << MYG << ", " << MZG - << std::endl; - - // separatrix location - Mesh::get(ixseps1, "ixseps1", nx); - Mesh::get(ixseps2, "ixseps2", nx); - Mesh::get(jyseps1_1, "jyseps1_1", -1); - Mesh::get(jyseps1_2, "jyseps1_2", ny / 2); - Mesh::get(jyseps2_1, "jyseps2_1", jyseps1_2); - Mesh::get(jyseps2_2, "jyseps2_2", ny - 1); - Mesh::get(ny_inner, "ny_inner", jyseps2_1); - - // Check inputs - setYDecompositionIndices(jyseps1_1, jyseps2_1, jyseps1_2, jyseps2_2, ny_inner); - - if (options.isSet("NXPE") or options.isSet("NYPE")) { - chooseProcessorSplit(options); - } else { - findProcessorSplit(); - } - - // Get X and Y processor indices - PE_YIND = MYPE / NXPE; - PE_XIND = MYPE % NXPE; - - // Set the other grid sizes from nx, ny, nz - setDerivedGridSizes(); - - /// Get mesh options - OPTION(options, IncIntShear, false); - periodicX = options["periodicX"].doc("Make grid periodic in X?").withDefault(false); - - async_send = options["async_send"] - .doc("Whether to use asyncronous MPI sends") - .withDefault(false); - - if (options.isSet("zperiod")) { - OPTION(options, zperiod, 1); - ZMIN = 0.0; - ZMAX = 1.0 / static_cast(zperiod); - } else { - OPTION(options, ZMIN, 0.0); - OPTION(options, ZMAX, 1.0); - - zperiod = ROUND(1.0 / (ZMAX - ZMIN)); - } - - ///////////////////// TOPOLOGY ////////////////////////// - /// Call topology to set layout of grid - topology(); - - TwistShift = options["twistshift"] - .doc("Apply a Twist-Shift boundary using ShiftAngle?") - .withDefault(false); - - // Try to read the shift angle from the grid file - // NOTE: All processors should know the twist-shift angle (for invert_parderiv) - // NOTE: Always read ShiftAngle as Coordinates will use hasBranchCutLower and - // hasBranchCutUpper to set zShift for ShiftedMetric - - ShiftAngle.resize(LocalNx); - - if (!source->get(this, ShiftAngle, "ShiftAngle", LocalNx, getGlobalXIndex(0))) { - ShiftAngle.clear(); - } - - if (TwistShift) { - output_info.write("Applying Twist-Shift condition. Interpolation: FFT\n"); - if (ShiftAngle.empty()) { - throw BoutException("ERROR: Twist-shift angle 'ShiftAngle' not found. " - "Required when TwistShift==true."); - } - } - - ////////////////////////////////////////////////////// - /// Communicator - - createCommunicators(); - output_debug << "Got communicators" << endl; - - ////////////////////////////////////////////////////// - // Boundary regions - createXBoundaries(); - createYBoundaries(); - - auto possible_boundaries = getPossibleBoundaries(); - if (possible_boundaries.empty()) { - output_info.write(_("No boundary regions; domain is periodic\n")); - } else { - output_info.write(_("Possible boundary regions are: ")); - for (const auto& boundary : possible_boundaries) { - output_info.write("{}, ", boundary); - } - } - - if (!boundary.empty()) { - output_info << _("Boundary regions in this processor: "); - for (const auto& bndry : boundary) { - output_info << bndry->label << ", "; - } - output_info << endl; - } else { - output_info << _("No boundary regions in this processor") << endl; - } - - output_info << _("Constructing default regions") << endl; - createDefaultRegions(); - - // Add boundary regions - addBoundaryRegions(); - - // Set cached values - { - int mybndry = static_cast(!(iterateBndryLowerY().isDone())); - int allbndry = 0; - mpi->MPI_Allreduce(&mybndry, &allbndry, 1, MPI_INT, MPI_BOR, getXcomm(yend)); - has_boundary_lower_y = static_cast(allbndry); - } - { - int mybndry = static_cast(!(iterateBndryUpperY().isDone())); - int allbndry = 0; - mpi->MPI_Allreduce(&mybndry, &allbndry, 1, MPI_INT, MPI_BOR, getXcomm(ystart)); - has_boundary_upper_y = static_cast(allbndry); - } - - // Initialize default coordinates - getCoordinates(); - - output_info.write(_("\tdone\n")); - - return 0; -} - void BoutMesh::createCommunicators() { MPI_Group group_world{}; MPI_Comm_group(BoutComm::get(), &group_world); // Get the entire group @@ -1542,7 +1539,7 @@ bool BoutMesh::lastX() const { return PE_XIND == NXPE - 1; } int BoutMesh::sendXOut(BoutReal* buffer, int size, int tag) { Timer timer("comms"); - int proc {-1}; + int proc{-1}; if (PE_XIND == NXPE - 1) { if (periodicX) { // Wrap around to first processor in X @@ -1554,8 +1551,7 @@ int BoutMesh::sendXOut(BoutReal* buffer, int size, int tag) { proc = PROC_NUM(PE_XIND + 1, PE_YIND); } - mpi->MPI_Send(buffer, size, PVEC_REAL_MPI_TYPE, proc, tag, - BoutComm::get()); + mpi->MPI_Send(buffer, size, PVEC_REAL_MPI_TYPE, proc, tag, BoutComm::get()); return 0; } @@ -1563,7 +1559,7 @@ int BoutMesh::sendXOut(BoutReal* buffer, int size, int tag) { int BoutMesh::sendXIn(BoutReal* buffer, int size, int tag) { Timer timer("comms"); - int proc {-1}; + int proc{-1}; if (PE_XIND == 0) { if (periodicX) { // Wrap around to last processor in X @@ -1575,8 +1571,7 @@ int BoutMesh::sendXIn(BoutReal* buffer, int size, int tag) { proc = PROC_NUM(PE_XIND - 1, PE_YIND); } - mpi->MPI_Send(buffer, size, PVEC_REAL_MPI_TYPE, proc, tag, - BoutComm::get()); + mpi->MPI_Send(buffer, size, PVEC_REAL_MPI_TYPE, proc, tag, BoutComm::get()); return 0; } @@ -1584,7 +1579,7 @@ int BoutMesh::sendXIn(BoutReal* buffer, int size, int tag) { comm_handle BoutMesh::irecvXOut(BoutReal* buffer, int size, int tag) { Timer timer("comms"); - int proc {-1}; + int proc{-1}; if (PE_XIND == NXPE - 1) { if (periodicX) { // Wrap around to first processor in X @@ -1599,8 +1594,8 @@ comm_handle BoutMesh::irecvXOut(BoutReal* buffer, int size, int tag) { // Get a communications handle. Not fussy about size of arrays CommHandle* ch = get_handle(0, 0); - mpi->MPI_Irecv(buffer, size, PVEC_REAL_MPI_TYPE, proc, tag, - BoutComm::get(), ch->request); + mpi->MPI_Irecv(buffer, size, PVEC_REAL_MPI_TYPE, proc, tag, BoutComm::get(), + ch->request); ch->in_progress = true; @@ -1610,7 +1605,7 @@ comm_handle BoutMesh::irecvXOut(BoutReal* buffer, int size, int tag) { comm_handle BoutMesh::irecvXIn(BoutReal* buffer, int size, int tag) { Timer timer("comms"); - int proc {-1}; + int proc{-1}; if (PE_XIND == 0) { if (periodicX) { // Wrap around to last processor in X @@ -1625,8 +1620,8 @@ comm_handle BoutMesh::irecvXIn(BoutReal* buffer, int size, int tag) { // Get a communications handle. Not fussy about size of arrays CommHandle* ch = get_handle(0, 0); - mpi->MPI_Irecv(buffer, size, PVEC_REAL_MPI_TYPE, proc, tag, - BoutComm::get(), ch->request); + mpi->MPI_Irecv(buffer, size, PVEC_REAL_MPI_TYPE, proc, tag, BoutComm::get(), + ch->request); ch->in_progress = true; diff --git a/src/mesh/impls/bout/boutmesh.hxx b/src/mesh/impls/bout/boutmesh.hxx index a22e0e4473..22e80ea29e 100644 --- a/src/mesh/impls/bout/boutmesh.hxx +++ b/src/mesh/impls/bout/boutmesh.hxx @@ -22,9 +22,6 @@ public: BoutMesh(GridDataSource* s, Options* options = nullptr); ~BoutMesh() override; - /// Read in the mesh from data sources - int load() override; - ///////////////////////////////////////////// // Communicate variables diff --git a/src/sys/options.cxx b/src/sys/options.cxx index 077b2a6d85..a524a00a59 100644 --- a/src/sys/options.cxx +++ b/src/sys/options.cxx @@ -7,6 +7,7 @@ #include "bout/field3d.hxx" #include "bout/field_factory.hxx" // Used for parsing expressions #include "bout/fieldperp.hxx" +#include "bout/mesh.hxx" #include "bout/output.hxx" #include "bout/sys/expressionparser.hxx" #include "bout/sys/gettext.hxx" diff --git a/tests/integrated/test-beuler/test_beuler.cxx b/tests/integrated/test-beuler/test_beuler.cxx index 5a080767dd..d018fdf0b0 100644 --- a/tests/integrated/test-beuler/test_beuler.cxx +++ b/tests/integrated/test-beuler/test_beuler.cxx @@ -66,7 +66,6 @@ int main(int argc, char** argv) { bout::globals::mpi = new MpiWrapper(); bout::globals::mesh = Mesh::create(); - bout::globals::mesh->load(); // Global options root["nout"] = 20; diff --git a/tests/integrated/test-coordinates-initialization/test-coordinates-initialization.cxx b/tests/integrated/test-coordinates-initialization/test-coordinates-initialization.cxx index 080b5d5397..d2c3e35eda 100644 --- a/tests/integrated/test-coordinates-initialization/test-coordinates-initialization.cxx +++ b/tests/integrated/test-coordinates-initialization/test-coordinates-initialization.cxx @@ -15,8 +15,7 @@ int main() { bout::globals::mpi = new MpiWrapper(); // Initialize a mesh - auto mesh = Mesh::create(); - mesh->load(); + auto* mesh = Mesh::create(); // Test CELL_CENTRE Field3D f(0., mesh); diff --git a/tests/integrated/test-solver/test_solver.cxx b/tests/integrated/test-solver/test_solver.cxx index a24db71750..427b206a30 100644 --- a/tests/integrated/test-solver/test_solver.cxx +++ b/tests/integrated/test-solver/test_solver.cxx @@ -76,7 +76,6 @@ int main(int argc, char** argv) { bout::globals::mpi = new MpiWrapper(); bout::globals::mesh = Mesh::create(); - bout::globals::mesh->load(); constexpr BoutReal end = PI / 2.; constexpr int NOUT = 100; diff --git a/tests/unit/mesh/test_boutmesh.cxx b/tests/unit/mesh/test_boutmesh.cxx index fd2ba50d28..e1626b9f42 100644 --- a/tests/unit/mesh/test_boutmesh.cxx +++ b/tests/unit/mesh/test_boutmesh.cxx @@ -242,13 +242,6 @@ BoutMeshParameters createDisconnectedDoubleNull(const BoutMeshGridInfo& grid) { //////////////////////////////////////////////////////////// // Start of tests -TEST(BoutMeshTest, NullOptionsCheck) { - WithQuietOutput info{output_info}; - WithQuietOutput warn{output_warn}; - - EXPECT_NO_THROW(BoutMesh mesh(new FakeGridDataSource, nullptr)); -} - // Not a great test as it's not specific to the thing we want to test, // and can also take a whopping ~300ms! TEST(BoutMeshTest, SingleCoreDecomposition) { @@ -264,10 +257,9 @@ TEST(BoutMeshTest, SingleCoreDecomposition) { options["MXG"] = 1; options["MYG"] = 0; - bout::globals::mpi = new MpiWrapper(); - BoutMesh mesh{new GridFromOptions{&options}, &options}; - EXPECT_NO_THROW(mesh.load()); - delete bout::globals::mpi; + auto mpi_wrapper = MpiWrapper(); + bout::globals::mpi = &mpi_wrapper; + EXPECT_NO_THROW(((BoutMesh{new GridFromOptions{&options}, &options}))); bout::globals::mpi = nullptr; } diff --git a/tools/pylib/_boutpp_build/boutcpp.pxd.jinja b/tools/pylib/_boutpp_build/boutcpp.pxd.jinja index 8f838b864c..b73f4b7138 100644 --- a/tools/pylib/_boutpp_build/boutcpp.pxd.jinja +++ b/tools/pylib/_boutpp_build/boutcpp.pxd.jinja @@ -52,7 +52,6 @@ cdef extern from "bout/mesh.hxx": Mesh() @staticmethod Mesh * create(Options * option) - void load() void communicate(FieldGroup&) int getNXPE() int getNYPE() diff --git a/tools/pylib/_boutpp_build/boutpp.pyx.jinja b/tools/pylib/_boutpp_build/boutpp.pyx.jinja index d6f0601f1c..9912c09552 100644 --- a/tools/pylib/_boutpp_build/boutpp.pyx.jinja +++ b/tools/pylib/_boutpp_build/boutpp.pyx.jinja @@ -735,7 +735,6 @@ cdef options self.cobj = c.Mesh.create(opt) if self.cobj == NULL: raise MemoryError("Not enough memory, allocation failed.") - self.cobj.load() @classmethod def getGlobal(cls):