@@ -82,42 +82,48 @@ namespace aspect
8282 ExcMessage (" The surface diffusion mesh deformation plugin only works for Box geometries." ));
8383
8484 unsigned int rank = Utilities::MPI::this_mpi_process (this ->get_mpi_communicator ());
85- if (rank >= n_landlab_ranks)
86- return ;
8785
86+ this_rank_runs_landlab = (rank < n_landlab_ranks);
87+ const int color = this_rank_runs_landlab?1 :0 ;
88+ int ierr = MPI_Comm_split (this ->get_mpi_communicator (), color, rank, &landlab_communicator);
89+ AssertThrow (ierr == MPI_SUCCESS, ExcMessage (" Failed to split MPI communicator for Landlab simulation" ));
90+
91+ if (this_rank_runs_landlab)
92+ {
8893#ifdef ASPECT_WITH_PYTHON
89- // Append script dirs so env packages (venv site-packages, PYTHONPATH) are found first
90- // for "import landlab":
91- PyRun_SimpleString (" import sys" );
92- PyRun_SimpleString (" sys.path.append(\" " ASPECT_SOURCE_DIR " /tests\" )" );
93- PyRun_SimpleString (" sys.path.append(\" .\" )" );
94+ // Append script dirs so env packages (venv site-packages, PYTHONPATH) are found first
95+ // for "import landlab":
96+ PyRun_SimpleString (" import sys" );
97+ PyRun_SimpleString (" sys.path.append(\" " ASPECT_SOURCE_DIR " /tests\" )" );
98+ PyRun_SimpleString (" sys.path.append(\" .\" )" );
9499
95- // avoid floating point exceptions in Landlab Python code:
100+ // avoid floating point exceptions in Landlab Python code:
96101#ifdef ASPECT_USE_FP_EXCEPTIONS
97- fedisableexcept (FE_DIVBYZERO|FE_INVALID);
102+ fedisableexcept (FE_DIVBYZERO|FE_INVALID);
98103#endif
99104
100- std::cout << " importing '" << script_module_name << " ' ..." << std::endl;
101- pModule = PyImport_ImportModule (script_module_name.c_str ());
102- if (PyErr_Occurred ())
103- PyErr_Print ();
104- AssertThrow (pModule, ExcMessage (" Failed to load Python module" ));
105+ std::cout << " importing '" << script_module_name << " ' ..." << std::endl;
106+ pModule = PyImport_ImportModule (script_module_name.c_str ());
107+ if (PyErr_Occurred ())
108+ PyErr_Print ();
109+ AssertThrow (pModule, ExcMessage (" Failed to load Python module" ));
105110
106- // Call Python initialize() function with communicator handle
107- PyObject *pArgs;
108- if (n_landlab_ranks == 1 )
109- pArgs = PyTuple_Pack (1 , Py_None);
110- else
111- pArgs = PyTuple_Pack (1 , PyLong_FromLong (MPI_Comm_c2f (this -> get_mpi_communicator () )));
112- PyObject *pValue = call_python_function (pModule, " initialize" , pArgs);
111+ // Call Python initialize() function with communicator handle
112+ PyObject *pArgs;
113+ if (n_landlab_ranks == 1 )
114+ pArgs = PyTuple_Pack (1 , Py_None);
115+ else
116+ pArgs = PyTuple_Pack (1 , PyLong_FromLong (MPI_Comm_c2f (landlab_communicator )));
117+ PyObject *pValue = call_python_function (pModule, " initialize" , pArgs);
113118
114- Py_DECREF (pArgs);
115- Py_DECREF (pValue);
119+ Py_DECREF (pArgs);
120+ Py_DECREF (pValue);
116121
117122#else
118- AssertThrow (false , ExcMessage (" ASPECT needs to be configure with Python support "
119- " (ASPECT_WITH_PYTHON=ON in CMake) to be able to use the Landlab mesh deformation model." ));
123+ AssertThrow (false , ExcMessage (" ASPECT needs to be configure with Python support "
124+ " (ASPECT_WITH_PYTHON=ON in CMake) to be able to use the Landlab mesh deformation model." ));
120125#endif
126+ }
121127 }
122128
123129
@@ -130,8 +136,7 @@ namespace aspect
130136#ifdef ASPECT_WITH_PYTHON
131137 if (!this ->remote_point_evaluator )
132138 {
133- unsigned int rank = Utilities::MPI::this_mpi_process (this ->get_mpi_communicator ());
134- if (rank >= n_landlab_ranks)
139+ if (!this_rank_runs_landlab)
135140 {
136141 // This rank does not participate, so we don't own any evaluation points:
137142 std::vector<Point<dim>> surface_points;
@@ -200,7 +205,7 @@ namespace aspect
200205 Assert (current_solution_at_points.size () == this ->evaluation_points .size (), ExcInternalError ());
201206 std::vector<Tensor<1 ,dim>> velocities (current_solution_at_points.size (), Tensor<1 ,dim>());
202207
203- if (pModule )
208+ if (this_rank_runs_landlab )
204209 {
205210 // Build a dictionary with solution values for each variable to pass to Python:
206211 PyObject *pDict = PyDict_New ();
@@ -282,7 +287,7 @@ namespace aspect
282287
283288 // 1. Grab initial deformation from Landlab:
284289 std::vector<Tensor<1 ,dim>> initial_deformation (this ->evaluation_points .size (), Tensor<1 ,dim>());
285- if (pModule )
290+ if (this_rank_runs_landlab )
286291 {
287292 Tensor<1 ,dim> topography_direction;
288293 topography_direction[dim-1 ] = 1.0 ;
@@ -344,7 +349,8 @@ namespace aspect
344349 {
345350 prm.declare_entry (" MPI ranks for Landlab" , " 1" ,
346351 Patterns::Integer (1 ),
347- " Number of ranks to use for the Landlab simulation. If set to 1, the Landlab simulation will run sequentially without MPI." );
352+ " Number of ranks to use for the Landlab simulation. If set to 1, the Landlab simulation will run sequentially "
353+ " without MPI. If set to -1, the Landlab simulation will run on all ranks." );
348354 prm.declare_entry (" Script path" , " " ,
349355 Patterns::Anything (),
350356 " Path to the Python script to execute. Relative paths and the placeholders "
@@ -371,7 +377,12 @@ namespace aspect
371377 {
372378 prm.enter_subsection (" Landlab" );
373379 {
374- n_landlab_ranks = prm.get_integer (" MPI ranks for Landlab" );
380+ const int ranks = prm.get_integer (" MPI ranks for Landlab" );
381+ if (ranks == -1 )
382+ n_landlab_ranks = Utilities::MPI::n_mpi_processes (this ->get_mpi_communicator ());
383+ else
384+ n_landlab_ranks = ranks;
385+
375386 script_path = prm.get (" Script path" );
376387 script_module_name = prm.get (" Script name" );
377388 script_argument = prm.get (" Script argument" );
0 commit comments