Skip to content

Commit b287079

Browse files
authored
Merge branch 'master' into dham/AIMS
2 parents 65d2cca + abd9e35 commit b287079

File tree

20 files changed

+252
-310
lines changed

20 files changed

+252
-310
lines changed

.github/workflows/build.yml

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jobs:
3939
FIREDRAKE_CI: 1
4040
PYOP2_CI_TESTS: 1
4141
PYOP2_SPMD_STRICT: 1
42-
EXTRA_PYTEST_ARGS: --splitting-algorithm least_duration --timeout=600 --timeout-method=thread -o faulthandler_timeout=660 firedrake-repo/tests/firedrake
42+
EXTRA_PYTEST_ARGS: --splitting-algorithm least_duration --timeout=600 --timeout-method=thread -o faulthandler_timeout=660
4343
PYTEST_MPI_MAX_NPROCS: 8
4444
steps:
4545
- name: Fix HOME
@@ -98,63 +98,85 @@ jobs:
9898
firedrake-check
9999
timeout-minutes: 5
100100

101-
- name: Run tests (nprocs = 1)
101+
- name: Run TSFC tests
102102
# Run even if earlier tests failed
103-
if: ${{ success() || steps.install.conclusion == 'success' }}
103+
if: success() || steps.install.conclusion == 'success'
104+
run: |
105+
. venv/bin/activate
106+
: # Use pytest-xdist here so we can have a single collated output (not possible
107+
: # for parallel tests)
108+
firedrake-run-split-tests 1 1 -n 8 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/tsfc
109+
timeout-minutes: 60
110+
111+
- name: Run PyOP2 tests
112+
if: success() || steps.install.conclusion == 'success'
113+
run: |
114+
. venv/bin/activate
115+
: # Use pytest-xdist here so we can have a single collated output (not possible
116+
: # for parallel tests)
117+
firedrake-run-split-tests 1 1 -n 8 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/pyop2
118+
firedrake-run-split-tests 2 4 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/pyop2
119+
firedrake-run-split-tests 3 2 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/pyop2
120+
firedrake-run-split-tests 4 2 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/pyop2
121+
timeout-minutes: 15
122+
123+
124+
- name: Run Firedrake tests (nprocs = 1)
125+
if: success() || steps.install.conclusion == 'success'
104126
run: |
105127
. venv/bin/activate
106128
: # Use pytest-xdist here so we can have a single collated output (not possible
107129
: # for parallel tests)
108-
firedrake-run-split-tests 1 1 "-n 8 $EXTRA_PYTEST_ARGS"
130+
firedrake-run-split-tests 1 1 -n 8 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/firedrake
109131
timeout-minutes: 60
110132

111133
- name: Run tests (nprocs = 2)
112-
if: ${{ success() || steps.install.conclusion == 'success' }}
134+
if: success() || steps.install.conclusion == 'success'
113135
run: |
114136
. venv/bin/activate
115-
firedrake-run-split-tests 2 4 "$EXTRA_PYTEST_ARGS"
137+
firedrake-run-split-tests 2 4 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/firedrake
116138
timeout-minutes: 30
117139

118140
- name: Run tests (nprocs = 3)
119-
if: ${{ success() || steps.install.conclusion == 'success' }}
141+
if: success() || steps.install.conclusion == 'success'
120142
run: |
121143
. venv/bin/activate
122-
firedrake-run-split-tests 3 2 "$EXTRA_PYTEST_ARGS"
144+
firedrake-run-split-tests 3 2 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/firedrake
123145
timeout-minutes: 60
124146

125147
- name: Run tests (nprocs = 4)
126-
if: ${{ success() || steps.install.conclusion == 'success' }}
148+
if: success() || steps.install.conclusion == 'success'
127149
run: |
128150
. venv/bin/activate
129-
firedrake-run-split-tests 4 2 "$EXTRA_PYTEST_ARGS"
151+
firedrake-run-split-tests 4 2 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/firedrake
130152
timeout-minutes: 15
131153

132154
- name: Run tests (nprocs = 5)
133-
if: ${{ success() || steps.install.conclusion == 'success' }}
155+
if: success() || steps.install.conclusion == 'success'
134156
run: |
135157
. venv/bin/activate
136-
firedrake-run-split-tests 5 1 "$EXTRA_PYTEST_ARGS"
158+
firedrake-run-split-tests 5 1 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/firedrake
137159
timeout-minutes: 15
138160

139161
- name: Run tests (nprocs = 6)
140-
if: ${{ success() || steps.install.conclusion == 'success' }}
162+
if: success() || steps.install.conclusion == 'success'
141163
run: |
142164
. venv/bin/activate
143-
firedrake-run-split-tests 6 1 "$EXTRA_PYTEST_ARGS"
165+
firedrake-run-split-tests 6 1 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/firedrake
144166
timeout-minutes: 15
145167

146168
- name: Run tests (nprocs = 7)
147-
if: ${{ success() || steps.install.conclusion == 'success' }}
169+
if: success() || steps.install.conclusion == 'success'
148170
run: |
149171
. venv/bin/activate
150-
firedrake-run-split-tests 7 1 "$EXTRA_PYTEST_ARGS"
172+
firedrake-run-split-tests 7 1 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/firedrake
151173
timeout-minutes: 15
152174

153175
- name: Run tests (nprocs = 8)
154-
if: ${{ success() || steps.install.conclusion == 'success' }}
176+
if: success() || steps.install.conclusion == 'success'
155177
run: |
156178
. venv/bin/activate
157-
firedrake-run-split-tests 8 1 "$EXTRA_PYTEST_ARGS"
179+
firedrake-run-split-tests 8 1 "$EXTRA_PYTEST_ARGS" firedrake-repo/tests/firedrake
158180
timeout-minutes: 15
159181

160182
- name: Run Gusto smoke tests
@@ -170,6 +192,15 @@ jobs:
170192
gusto-repo/integration-tests/transport/test_embedded_dg_advection.py
171193
timeout-minutes: 10
172194

195+
- name: Run Thetis smoke tests
196+
if: (success() || steps.install.conclusion == 'success') && matrix.arch == 'default'
197+
run: |
198+
. venv/bin/activate
199+
git clone --depth 1 https://github.com/thetisproject/thetis.git thetis-repo
200+
pip install --verbose ./thetis-repo
201+
python -m pytest -n 8 --verbose thetis-repo/test_adjoint/test_swe_adjoint.py
202+
timeout-minutes: 10
203+
173204
- name: Run spyro smoke tests
174205
if: (success() || steps.install.conclusion == 'success') && matrix.arch == 'default'
175206
run: |
@@ -251,7 +282,7 @@ jobs:
251282
- name: Setup Python
252283
uses: actions/setup-python@v5
253284
with:
254-
python-version: '3.12'
285+
python-version: "3.12"
255286
- name: Install deps
256287
run: pip install requests packaging
257288
- name: Zenodo API canary
@@ -260,5 +291,5 @@ jobs:
260291
uses: actions/upload-artifact@v4
261292
if: failure()
262293
with:
263-
name: "zenodo-canary"
294+
name: zenodo-canary
264295
path: firedrake-install.log

.github/workflows/pyop2.yml

Lines changed: 0 additions & 92 deletions
This file was deleted.

docs/source/visualisation.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Creating output files
1818
Output for visualisation purposes is managed with a
1919
:class:`~.vtk_output.VTKFile` object. To create one, first import the
2020
class from `firedrake.output, then we just need to pass the name of the
21-
output file on disk. The file Firedrake creates is in PVD_ and
21+
output file on disk. The file Firedrake creates is in PVD and
2222
therefore the requested file name must end in ``.pvd``.
2323

2424
.. code-block:: python3
@@ -67,7 +67,7 @@ and call :meth:`~.vtk_output.VTKFile.write` inside.
6767
t += dt
6868
6969
70-
The PVD_ data format supports specifying the timestep value for
70+
The PVD data format supports specifying the timestep value for
7171
time-dependent data. We do not have to provide it to
7272
:meth:`~.vtk_output.VTKFile.write`, by default an integer counter is
7373
used that is incremented by 1 each time
@@ -329,7 +329,6 @@ matplotlib.
329329

330330
.. _Paraview: http://www.paraview.org
331331
.. _VTK: http://www.vtk.org
332-
.. _PVD: http://www.paraview.org/Wiki/ParaView/Data_formats#PVD_File_Format
333332
.. _matplotlib: http://matplotlib.org
334333
.. _Arbitrary: https://www.kitware.com/modeling-arbitrary-order-lagrange-finite-elements-in-the-visualization-toolkit/
335334
__ Arbitrary_

firedrake/adjoint_utils/blocks/function.py

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -197,50 +197,71 @@ class SubfunctionBlock(Block):
197197
def __init__(self, func, idx, ad_block_tag=None):
198198
super().__init__(ad_block_tag=ad_block_tag)
199199
self.add_dependency(func)
200-
self.idx = idx
200+
self.sub_idx = idx
201201

202202
def evaluate_adj_component(self, inputs, adj_inputs, block_variable, idx,
203203
prepared=None):
204204
eval_adj = firedrake.Cofunction(block_variable.output.function_space().dual())
205205
if type(adj_inputs[0]) is firedrake.Cofunction:
206-
eval_adj.sub(self.idx).assign(adj_inputs[0])
206+
eval_adj.sub(self.sub_idx).assign(adj_inputs[0])
207207
else:
208-
eval_adj.sub(self.idx).assign(adj_inputs[0].function)
208+
eval_adj.sub(self.sub_idx).assign(adj_inputs[0].function)
209209
return eval_adj
210210

211211
def evaluate_tlm_component(self, inputs, tlm_inputs, block_variable, idx,
212212
prepared=None):
213-
return firedrake.Function.sub(tlm_inputs[0], self.idx)
213+
return firedrake.Function.sub(tlm_inputs[0], self.sub_idx)
214214

215215
def evaluate_hessian_component(self, inputs, hessian_inputs, adj_inputs,
216216
block_variable, idx,
217217
relevant_dependencies, prepared=None):
218218
eval_hessian = firedrake.Cofunction(block_variable.output.function_space().dual())
219-
eval_hessian.sub(self.idx).assign(hessian_inputs[0])
219+
eval_hessian.sub(self.sub_idx).assign(hessian_inputs[0])
220220
return eval_hessian
221221

222222
def recompute_component(self, inputs, block_variable, idx, prepared):
223223
return maybe_disk_checkpoint(
224-
firedrake.Function.sub(inputs[0], self.idx)
224+
firedrake.Function.sub(inputs[0], self.sub_idx)
225225
)
226226

227227
def __str__(self):
228-
return f"{self.get_dependencies()[0]}[{self.idx}]"
228+
return f"{self.get_dependencies()[0]}[{self.sub_idx}]"
229229

230230

231231
class FunctionMergeBlock(Block):
232232
def __init__(self, func, idx, ad_block_tag=None):
233233
super().__init__(ad_block_tag=ad_block_tag)
234234
self.add_dependency(func)
235-
self.idx = idx
235+
self.sub_idx = idx
236236
for output in func._ad_outputs:
237237
self.add_dependency(output)
238238

239239
def evaluate_adj_component(self, inputs, adj_inputs, block_variable, idx,
240240
prepared=None):
241+
# The merge block appears whenever a subfunction is the output of a block.
242+
# This means that the subfunction has been modified, so we need to make
243+
# sure that this modification is accounted for when evaluating the adjoint.
244+
#
245+
# When recomputing the merge block, the indexed subfunction in the full
246+
# Function is completely overwritten, meaning that the pre-existing value
247+
# of the subfunction in the full function is ignored.
248+
# The equivalent adjoint operation is to:
249+
# 1. send the subfunction component of the adjoint value back up
250+
# the branch of the tape corresponding to the subfunction
251+
# dependency (idx=0).
252+
# 2. zero out the subfunction component of the adjoint value sent
253+
# back up the full Function branch of the tape (idx=1).
254+
# This means that when the adjoint values of each branch are combined
255+
# after the SubfunctionBlock only the adjoint value from the subfunction
256+
# branch is used.
257+
#
258+
# See https://github.com/firedrakeproject/firedrake/pull/4177 for more
259+
# detail and for diagrams of the tape produced when accessing subfunctions.
260+
241261
if idx == 0:
242-
return adj_inputs[0].subfunctions[self.idx]
262+
return adj_inputs[0].subfunctions[self.sub_idx].copy(deepcopy=True)
243263
else:
264+
adj_inputs[0].subfunctions[self.sub_idx].zero()
244265
return adj_inputs[0]
245266

246267
def evaluate_tlm(self, markings=False):
@@ -253,7 +274,7 @@ def evaluate_tlm(self, markings=False):
253274
fs = output.output.function_space()
254275
f = type(output.output)(fs)
255276
output.add_tlm_output(
256-
type(output.output).assign(f.sub(self.idx), tlm_input)
277+
type(output.output).assign(f.sub(self.sub_idx), tlm_input)
257278
)
258279

259280
def evaluate_hessian_component(self, inputs, hessian_inputs, adj_inputs,
@@ -265,12 +286,12 @@ def recompute_component(self, inputs, block_variable, idx, prepared):
265286
sub_func = inputs[0]
266287
parent_in = inputs[1]
267288
parent_out = type(parent_in)(parent_in)
268-
parent_out.sub(self.idx).assign(sub_func)
289+
parent_out.sub(self.sub_idx).assign(sub_func)
269290
return maybe_disk_checkpoint(parent_out)
270291

271292
def __str__(self):
272293
deps = self.get_dependencies()
273-
return f"{deps[1]}[{self.idx}].assign({deps[0]})"
294+
return f"{deps[1]}[{self.sub_idx}].assign({deps[0]})"
274295

275296

276297
class CofunctionAssignBlock(Block):

firedrake/configuration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77
def setup_cache_dirs():
8-
root = Path(os.environ.get("VIRTUAL_ENV", "~")).joinpath(".cache")
8+
root = Path(os.environ.get("VIRTUAL_ENV", Path.home())).joinpath(".cache")
99
if "PYOP2_CACHE_DIR" not in os.environ:
1010
os.environ["PYOP2_CACHE_DIR"] = str(root.joinpath("pyop2"))
1111
if 'FIREDRAKE_TSFC_KERNEL_CACHE_DIR' not in os.environ:

firedrake/mesh.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4676,6 +4676,6 @@ def Submesh(mesh, subdim, subdomain_id, label_name=None, name=None):
46764676
submesh = Mesh(subplex, name=name, distribution_parameters={"partition": False,
46774677
"overlap_type": (DistributedMeshOverlapType.NONE, 0)})
46784678
submesh.topology.submesh_parent = mesh.topology
4679-
submesh.submesh_parent = mesh
46804679
submesh.init()
4680+
submesh.submesh_parent = mesh
46814681
return submesh

firedrake/pyplot/mpl.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -628,9 +628,9 @@ def streamplot(function, resolution=None, min_length=None, max_time=None,
628628
area = assemble(Constant(1) * dx(mesh))
629629
average_speed = np.sqrt(assemble(inner(function, function) * dx) / area)
630630
if np.isclose(average_speed, 0.0):
631-
max_time = 50 * min_length / average_speed
632-
else:
633631
max_time = 0.
632+
else:
633+
max_time = 50 * min_length / average_speed
634634

635635
streamplotter = Streamplotter(function, resolution, min_length, max_time,
636636
tolerance, loc_tolerance,

0 commit comments

Comments
 (0)