Skip to content

Commit 3879d0a

Browse files
committed
Merge remote-tracking branch 'upstream/master' into HEAD
2 parents 86f58ef + 51aa701 commit 3879d0a

34 files changed

+3704
-444
lines changed

.github/workflows/ci_pipeline.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ jobs:
173173
user_firedrake_tests:
174174
runs-on: ubuntu-latest
175175
container:
176-
image: firedrakeproject/firedrake-vanilla:2025-01
176+
image: firedrakeproject/firedrake-vanilla:latest
177177
options: --user root
178178
volumes:
179179
- ${{ github.workspace }}:/repositories
@@ -205,7 +205,7 @@ jobs:
205205
firedrake-clean
206206
cd ./pySDC
207207
coverage run -m pytest --continue-on-collection-errors -v --durations=0 /repositories/pySDC/pySDC/tests -m firedrake
208-
timeout-minutes: 120
208+
timeout-minutes: 45
209209
- name: Make coverage report
210210
run: |
211211
. /home/firedrake/firedrake/bin/activate

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ implemented.
1919

2020
- Variants of SDC: explicit, implicit, IMEX, multi-implicit, Verlet,
2121
multi-level, diagonal, multi-step
22-
- Variants of PFASST: virtual parallel or MPI-based parallel,
23-
classical of multigrid perspective
22+
- Variants of PFASST: virtually parallel or MPI-based parallel,
23+
classical or multigrid perspective
2424
- 8 tutorials: from setting up a first collocation problem to SDC,
2525
PFASST and advanced topics
2626
- Projects: many documented projects with defined and tested outcomes
@@ -43,12 +43,11 @@ The code is hosted on GitHub, see
4343
will give you a core version of `pySDC` to work with,
4444
working with the developer version is most often the better choice. We
4545
thus recommend to checkout the code from GitHub and install the
46-
dependencies e.g. by using a [conda](https://conda.io/en/latest/)
47-
environment. For this, `pySDC` ships with environment files
48-
which can be found in the folder `etc/`. Use these as e.g.
46+
dependencies e.g. by using [micromamba](https://mamba.readthedocs.io/en/latest/user_guide/micromamba.html). For this, `pySDC` ships with environment files
47+
which can be found in the folder `etc/` or within the projects. Use these as e.g.
4948

5049
``` bash
51-
conda env create -f etc/environment-base.yml
50+
micromamba create -f etc/environment-base.yml
5251
```
5352

5453
If you want to install the developer version using `pip` directly from the GitHub repository, use this:

etc/environment-petsc.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ dependencies:
99
- matplotlib>=3.0
1010
- dill>=0.2.6
1111
- mpich
12-
- petsc4py
12+
- petsc4py<3.22
1313
- mpi4py>=3.0.0
1414
- pip
1515
- pip:

pySDC/helpers/firedrake_ensemble_communicator.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ def Isend(self, buf, dest, tag=MPI.ANY_TAG):
6767
return self.ensemble.ensemble_comm.Isend(buf=buf, dest=dest, tag=tag)
6868
return self.ensemble.isend(buf, dest, tag=tag)[0]
6969

70+
def Free(self):
71+
del self
72+
7073

7174
def get_ensemble(comm, space_size):
7275
return fd.Ensemble(comm, space_size)

pySDC/implementations/problem_classes/GrayScott_MPIFFT.py

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class grayscott_imex_diffusion(IMEX_Laplacian_MPIFFT):
1919
\frac{\partial u}{\partial t} = D_u \Delta u - u v^2 + A (1 - u),
2020
2121
.. math::
22-
\frac{\partial v}{\partial t} = D_v \Delta v + u v^2 - B u
22+
\frac{\partial v}{\partial t} = D_v \Delta v + u v^2 - B v
2323
2424
in :math:`x \in \Omega:=[-L/2, L/2]^N` with :math:`N=2,3`. Spatial discretization is done by using
2525
Fast Fourier transformation for solving the linear parts provided by ``mpi4py-fft`` [2]_, see also
@@ -222,7 +222,7 @@ def u_exact(self, t, seed=10700000):
222222

223223
for _ in range(-self.num_blobs):
224224
x0 = rng.random(size=self.ndim) * self.L[0] - self.L[0] / 2
225-
l = rng.random(size=self.ndim) * self.L[0] / self.nvars[0] * 30
225+
l = rng.random(size=self.ndim) * self.L[0] / self.nvars[0] * 80
226226

227227
masks = [xp.logical_and(self.X[i] > x0[i], self.X[i] < x0[i] + l[i]) for i in range(self.ndim)]
228228
mask = masks[0]
@@ -236,33 +236,54 @@ def u_exact(self, t, seed=10700000):
236236
"""
237237
Blobs as in https://www.chebfun.org/examples/pde/GrayScott.html
238238
"""
239-
assert self.ndim == 2, 'The initial conditions are 2D for now..'
240-
241239
inc = self.L[0] / (self.num_blobs + 1)
242240

243241
for i in range(1, self.num_blobs + 1):
244242
for j in range(1, self.num_blobs + 1):
245-
signs = (-1) ** rng.integers(low=0, high=2, size=2)
246-
247-
# This assumes that the box is [-L/2, L/2]^2
248-
_u[...] += -xp.exp(
249-
-80.0
250-
* (
251-
(self.X[0] + self.x0 + inc * i + signs[0] * 0.05) ** 2
252-
+ (self.X[1] + self.x0 + inc * j + signs[1] * 0.02) ** 2
243+
signs = (-1) ** rng.integers(low=0, high=2, size=self.ndim)
244+
245+
if self.ndim == 2:
246+
# This assumes that the box is [-L/2, L/2]^2
247+
_u[...] += -xp.exp(
248+
-80.0
249+
* (
250+
(self.X[0] + self.x0 + inc * i + signs[0] * 0.05) ** 2
251+
+ (self.X[1] + self.x0 + inc * j + signs[1] * 0.02) ** 2
252+
)
253+
)
254+
_v[...] += xp.exp(
255+
-80.0
256+
* (
257+
(self.X[0] + self.x0 + inc * i - signs[0] * 0.05) ** 2
258+
+ (self.X[1] + self.x0 + inc * j - signs[1] * 0.02) ** 2
259+
)
260+
)
261+
elif self.ndim == 3:
262+
z_pos = self.x0 + rng.random() * self.L[2]
263+
# This assumes that the box is [-L/2, L/2]^3
264+
_u[...] += -xp.exp(
265+
-80.0
266+
* (
267+
(self.X[0] + self.x0 + inc * i + signs[0] * 0.05) ** 2
268+
+ (self.X[1] + self.x0 + inc * j + signs[1] * 0.02) ** 2
269+
+ (self.X[2] - z_pos + signs[2] * 0.035) ** 2
270+
)
253271
)
254-
)
255-
_v[...] += xp.exp(
256-
-80.0
257-
* (
258-
(self.X[0] + self.x0 + inc * i - signs[0] * 0.05) ** 2
259-
+ (self.X[1] + self.x0 + inc * j - signs[1] * 0.02) ** 2
272+
_v[...] += xp.exp(
273+
-80.0
274+
* (
275+
(self.X[0] + self.x0 + inc * i - signs[0] * 0.05) ** 2
276+
+ (self.X[1] + self.x0 + inc * j - signs[1] * 0.02) ** 2
277+
+ (self.X[2] - z_pos - signs[2] * 0.035) ** 2
278+
)
260279
)
261-
)
280+
else:
281+
raise NotImplementedError
262282

263283
_u += 1
264284
else:
265-
raise NotImplementedError
285+
_u[...] = rng.random(_u.shape)
286+
_v[...] = rng.random(_v.shape)
266287

267288
u = self.u_init
268289
if self.spectral:

pySDC/implementations/problem_classes/TestEquation_0D.py

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import scipy.sparse as nsp
33

44
from pySDC.core.problem import Problem, WorkCounter
5-
from pySDC.implementations.datatype_classes.mesh import mesh
5+
from pySDC.implementations.datatype_classes.mesh import mesh, imex_mesh
66

77

88
class testequation0d(Problem):
@@ -145,3 +145,118 @@ def u_exact(self, t, u_init=None, t_init=None):
145145
me = self.dtype_u(self.init)
146146
me[:] = u_init * self.xp.exp((t - t_init) * self.lambdas)
147147
return me
148+
149+
150+
class test_equation_IMEX(Problem):
151+
dtype_f = imex_mesh
152+
dtype_u = mesh
153+
xp = np
154+
xsp = nsp
155+
156+
def __init__(self, lambdas_implicit=None, lambdas_explicit=None, u0=0.0):
157+
"""Initialization routine"""
158+
159+
if lambdas_implicit is None:
160+
re = self.xp.linspace(-30, 19, 50)
161+
im = self.xp.linspace(-50, 49, 50)
162+
lambdas_implicit = self.xp.array(
163+
[[complex(re[i], im[j]) for i in range(len(re))] for j in range(len(im))]
164+
).reshape((len(re) * len(im)))
165+
if lambdas_explicit is None:
166+
re = self.xp.linspace(-30, 19, 50)
167+
im = self.xp.linspace(-50, 49, 50)
168+
lambdas_implicit = self.xp.array(
169+
[[complex(re[i], im[j]) for i in range(len(re))] for j in range(len(im))]
170+
).reshape((len(re) * len(im)))
171+
lambdas_implicit = self.xp.asarray(lambdas_implicit)
172+
lambdas_explicit = self.xp.asarray(lambdas_explicit)
173+
174+
assert lambdas_implicit.ndim == 1, f'expect flat list here, got {lambdas_implicit}'
175+
assert lambdas_explicit.shape == lambdas_implicit.shape
176+
nvars = lambdas_implicit.size
177+
assert nvars > 0, 'expect at least one lambda parameter here'
178+
179+
# invoke super init, passing number of dofs, dtype_u and dtype_f
180+
super().__init__(init=(nvars, None, self.xp.dtype('complex128')))
181+
182+
self.A = self.xsp.diags(lambdas_implicit)
183+
self._makeAttributeAndRegister(
184+
'nvars', 'lambdas_implicit', 'lambdas_explicit', 'u0', localVars=locals(), readOnly=True
185+
)
186+
self.work_counters['rhs'] = WorkCounter()
187+
188+
def eval_f(self, u, t):
189+
"""
190+
Routine to evaluate the right-hand side of the problem.
191+
192+
Parameters
193+
----------
194+
u : dtype_u
195+
Current values of the numerical solution.
196+
t : float
197+
Current time of the numerical solution is computed.
198+
199+
Returns
200+
-------
201+
f : dtype_f
202+
The right-hand side of the problem.
203+
"""
204+
205+
f = self.dtype_f(self.init)
206+
f.impl[:] = u * self.lambdas_implicit
207+
f.expl[:] = u * self.lambdas_explicit
208+
self.work_counters['rhs']()
209+
return f
210+
211+
def solve_system(self, rhs, factor, u0, t):
212+
r"""
213+
Simple linear solver for :math:`(I-factor\cdot A)\vec{u}=\vec{rhs}`.
214+
215+
Parameters
216+
----------
217+
rhs : dtype_f
218+
Right-hand side for the linear system.
219+
factor : float
220+
Abbrev. for the local stepsize (or any other factor required).
221+
u0 : dtype_u
222+
Initial guess for the iterative solver.
223+
t : float
224+
Current time (e.g. for time-dependent BCs).
225+
226+
Returns
227+
-------
228+
me : dtype_u
229+
The solution as mesh.
230+
"""
231+
me = self.dtype_u(self.init)
232+
L = 1 - factor * self.lambdas_implicit
233+
L[L == 0] = 1 # to avoid potential divisions by zeros
234+
me[:] = rhs
235+
me /= L
236+
return me
237+
238+
def u_exact(self, t, u_init=None, t_init=None):
239+
"""
240+
Routine to compute the exact solution at time t.
241+
242+
Parameters
243+
----------
244+
t : float
245+
Time of the exact solution.
246+
u_init : pySDC.problem.testequation0d.dtype_u
247+
Initial solution.
248+
t_init : float
249+
The initial time.
250+
251+
Returns
252+
-------
253+
me : dtype_u
254+
The exact solution.
255+
"""
256+
257+
u_init = (self.u0 if u_init is None else u_init) * 1.0
258+
t_init = 0.0 if t_init is None else t_init * 1.0
259+
260+
me = self.dtype_u(self.init)
261+
me[:] = u_init * self.xp.exp((t - t_init) * (self.lambdas_implicit + self.lambdas_explicit))
262+
return me

pySDC/implementations/problem_classes/generic_MPIFFT_Laplacian.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ def __init__(
8585
collapse=True,
8686
backend=self.fft_backend,
8787
comm_backend=self.fft_comm_backend,
88+
grid=(-1,),
8889
)
8990

9091
# get test data to figure out type and dimensions

pySDC/projects/GPU/README.rst

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,84 @@ For instance, use
4545

4646
.. code-block:: bash
4747
48-
srun -n 4 python work_precision.py --config=GS_USkate --procs=1/1/4 --useGPU=True --mode=run
49-
mpirun -np 8 python work_precision.py --config=GS_USkate --procs=1/1/4 --useGPU=True --mode=plot
50-
python work_precision.py --config=GS_USkate --procs=1/1/4 --useGPU=True --mode=video
48+
srun -n 4 python run_experiment.pyy --config=GS_USkate --procs=1/1/4 --useGPU=True --mode=run
49+
mpirun -np 8 python run_experiment.py --config=GS_USkate --procs=1/1/4 --useGPU=True --mode=plot
50+
python run_experiment.py --config=GS_USkate --procs=1/1/4 --useGPU=True --mode=video
5151
5252
to first run the problem, then make plots and then make a video for Gray-Scott with the U-Skate configuration (see arXiv:1501.01990).
5353

5454
To do a parallel scaling test, you can go to JUWELS Booster and use, for instance,
5555

5656
.. code-block:: bash
57-
python analysis_scripts/parallel_scaling.py --mode=run --scaling=strong --space_time=True --XPU=GPU --problem=GS
58-
srun python analysis_scripts/parallel_scaling.py --mode=plot --scaling=strong --space_time=True --XPU=GPU --problem=GS
57+
58+
python analysis_scripts/parallel_scaling.py --mode=run --space_time=True --XPU=GPU --problem=GS3D
59+
python analysis_scripts/parallel_scaling.py --mode=plot --space_time=True --XPU=GPU --problem=GS3D
5960
6061
This will generate jobscripts and submit the jobs. Notice that you have to wait for the jobs to complete before you can plot them.
6162

6263
To learn more about the options for the scripts, run them with `--help`.
64+
65+
Reproducing plots in Thomas Baumann's thesis
66+
--------------------------------------------
67+
Keep in mind that the results of the experiments are specific to the hardware that was used in the experiments.
68+
To record the data for space-time parallel scaling experiments with Gray-Scott and RBC, run the following commands on the specified machines within the directory that contains this README.
69+
70+
.. code-block:: bash
71+
72+
# run on JUWELS
73+
python analysis_scripts/parallel_scaling.py --mode=run --problem=GS3D --XPU=CPU --space_time=False
74+
python analysis_scripts/parallel_scaling.py --mode=run --problem=GS3D --XPU=CPU --space_time=True
75+
76+
# run on JUWELS booster
77+
python analysis_scripts/parallel_scaling.py --mode=run --problem=GS3D --XPU=GPU --space_time=False
78+
python analysis_scripts/parallel_scaling.py --mode=run --problem=GS3D --XPU=GPU --space_time=True
79+
80+
# run on JURECA DC
81+
python analysis_scripts/parallel_scaling.py --mode=run --problem=RBC --XPU=CPU --space_time=False
82+
python analysis_scripts/parallel_scaling.py --mode=run --problem=RBC --XPU=CPU --space_time=True
83+
84+
# run on JUWELS booster
85+
python analysis_scripts/parallel_scaling.py --mode=run --problem=RBC --XPU=GPU --space_time=False
86+
python analysis_scripts/parallel_scaling.py --mode=run --problem=RBC --XPU=GPU --space_time=True
87+
88+
These commands will submit a bunch of jobscripts with the individual runs.
89+
Keep in mind that these are specific to a compute project and some paths are account-specific.
90+
Most likely, you will have to change options at the top of the file `./etc/generate_jobscript.py` before you can run anything.
91+
Also, notice that you may not be allowed to request all resources needed for the largest Gray-Scott GPU run during normal operation of JUWELS booster.
92+
93+
After all jobs have run to completion, you have recorded all scaling data and may plot the results with the following command:
94+
95+
.. code-block:: bash
96+
97+
python paper_plots.py --target=thesis
98+
99+
In order to run the production runs, modify the `path` class attribute of `LargeSim` in `analysis_scripts/large_simulations.py`.
100+
Then use the following commands on the specified machines:
101+
102+
.. code-block:: bash
103+
104+
# run on JUWELS booster
105+
python analysis_scripts/large_simulations.py --mode=run --problem=GS --XPU=GPU
106+
107+
# run on JURECA DC
108+
python analysis_scripts/large_simulations.py --mode=run --problem=RBC --XPU=CPU
109+
110+
Plotting the results of the Gray-Scott simulation requires a lot of memory and will take very long.
111+
Modify the paths in `analysis_scripts/plot_large_simulations.py` and then run:
112+
113+
.. code-block:: bash
114+
115+
python analysis_scripts/3d_plot_GS_large.py --base_path=<path>
116+
python analysis_scripts/plot_large_simulations.py --problem=GS
117+
118+
Plotting the results of the Rayleigh-Benard production run is more easy.
119+
After modifying the paths as earlier, run the following commands:
120+
121+
.. code-block:: bash
122+
123+
python analysis_scripts/large_simulations.py --mode=plot --problem=RBC --XPU=CPU
124+
python analysis_scripts/large_simulations.py --mode=video --problem=RBC --XPU=CPU
125+
python analysis_scripts/plot_large_simulations.py --problem=RBC
126+
127+
Run scripts with `--help` to learn more about parameters.
128+
Keep in mind that not all features are supported with all problems.

0 commit comments

Comments
 (0)