Skip to content

Commit 54677cb

Browse files
authored
Remove tests without taping from adjoint test directory. (#4870)
1 parent 8ba4657 commit 54677cb

File tree

2 files changed

+367
-357
lines changed

2 files changed

+367
-357
lines changed
Lines changed: 3 additions & 357 deletions
Original file line numberDiff line numberDiff line change
@@ -1,235 +1,11 @@
11
import pytest
2-
import numpy as np
3-
from scipy.sparse import csr_matrix
4-
import petsctools
52
from firedrake import *
63
from firedrake.adjoint import *
74

85

9-
def petsc2numpy_vec(petsc_vec):
10-
"""Allgather a PETSc.Vec."""
11-
gvec = petsc_vec
12-
gather, lvec = PETSc.Scatter().toAll(gvec)
13-
gather(gvec, lvec, addv=PETSc.InsertMode.INSERT_VALUES)
14-
return lvec.array_r.copy()
15-
16-
17-
def petsc2numpy_mat(petsc_mat):
18-
"""Allgather a PETSc.Mat."""
19-
comm = petsc_mat.getComm()
20-
local_mat = petsc_mat.getRedundantMatrix(
21-
comm.size, PETSc.COMM_SELF)
22-
return csr_matrix(
23-
local_mat.getValuesCSR()[::-1],
24-
shape=local_mat.getSize()
25-
).todense()
26-
27-
28-
@pytest.fixture
29-
def rng():
30-
return RandomGenerator(PCG64(seed=13))
31-
32-
33-
@pytest.mark.skipcomplex
34-
@pytest.mark.parallel([1, 2])
35-
@pytest.mark.parametrize("degree", (1, 2), ids=["degree1", "degree2"])
36-
@pytest.mark.parametrize("dim", (0, 2, (2, 2)), ids=["scalar", "vec2", "tensor22"])
37-
@pytest.mark.parametrize("family", ("CG", "DG"))
38-
@pytest.mark.parametrize("mesh_type", ("interval", "square"))
39-
@pytest.mark.parametrize("backend_type", (PyOP2NoiseBackend, PetscNoiseBackend), ids=("pyop2", "petsc"))
40-
def test_white_noise(family, degree, mesh_type, dim, backend_type, rng):
41-
"""Test that white noise generator converges to a mass matrix covariance.
42-
"""
43-
44-
nx = 10
45-
# Mesh dimension
46-
if mesh_type == 'interval':
47-
mesh = UnitIntervalMesh(nx)
48-
elif mesh_type == 'square':
49-
mesh = UnitSquareMesh(nx, nx)
50-
51-
# Variable rank
52-
if not isinstance(dim, int):
53-
V = TensorFunctionSpace(mesh, family, degree, shape=dim)
54-
elif dim > 0:
55-
V = VectorFunctionSpace(mesh, family, degree, dim=dim)
56-
else:
57-
V = FunctionSpace(mesh, family, degree)
58-
59-
# Finite element white noise has mass matrix covariance
60-
M = inner(TrialFunction(V), TestFunction(V))*dx
61-
covmat = petsc2numpy_mat(
62-
assemble(M, mat_type='aij').petscmat)
63-
64-
generator = WhiteNoiseGenerator(
65-
V, backend=backend_type(V, rng=rng))
66-
67-
# Test convergence as sample size increases
68-
nsamples = [50, 100, 200, 400, 800]
69-
70-
samples = np.empty((V.dim(), nsamples[-1]))
71-
for i in range(nsamples[-1]):
72-
with generator.sample().dat.vec_ro as bv:
73-
samples[:, i] = petsc2numpy_vec(bv)
74-
75-
covariances = [np.cov(samples[:, :ns]) for ns in nsamples]
76-
77-
# Measured covariance matrix should converge at a rate of sqrt(n).
78-
# The number of samples is fairly small to keep the test cost
79-
# lower so we only test the mean rate to a low tolerance.
80-
81-
errors = [np.linalg.norm(cov-covmat) for cov in covariances]
82-
rate = -np.diff(np.log(errors))/np.diff(np.log(nsamples))
83-
84-
assert np.mean(rate) > 0.4
85-
86-
87-
@pytest.mark.skipcomplex
88-
@pytest.mark.parallel([1, 2])
89-
@pytest.mark.parametrize("dim", (0, 2, (2, 2)), ids=["scalar", "vec2", "tensor22"])
90-
@pytest.mark.parametrize("mesh_type", ("interval", "square"))
91-
def test_vom_white_noise(dim, mesh_type, rng):
92-
"""Test that white noise generator converges to a mass matrix covariance.
93-
"""
94-
95-
nx = 10
96-
nv = 10
97-
np.random.seed(13)
98-
# Mesh dimension
99-
if mesh_type == 'interval':
100-
mesh = UnitIntervalMesh(nx)
101-
points = np.random.random_sample((nv, 1))
102-
elif mesh_type == 'square':
103-
mesh = UnitSquareMesh(nx, nx)
104-
points = np.random.random_sample((nv, 2))
105-
106-
vom = VertexOnlyMesh(mesh, points)
107-
108-
# Variable rank
109-
if not isinstance(dim, int):
110-
V = TensorFunctionSpace(vom, "DG", 0, shape=dim)
111-
elif dim > 0:
112-
V = VectorFunctionSpace(vom, "DG", 0, dim=dim)
113-
else:
114-
V = FunctionSpace(vom, "DG", 0)
115-
116-
# Finite element white noise has mass matrix covariance
117-
M = inner(TrialFunction(V), TestFunction(V))*dx
118-
covmat = petsc2numpy_mat(
119-
assemble(M, mat_type='aij').petscmat)
120-
121-
backend = VOMNoiseBackend(V, rng)
122-
generator = WhiteNoiseGenerator(V, backend=backend)
123-
124-
# Test convergence as sample size increases
125-
nsamples = [50, 100, 200, 400, 800]
126-
127-
samples = np.empty((V.dim(), nsamples[-1]))
128-
for i in range(nsamples[-1]):
129-
with generator.sample().dat.vec_ro as bv:
130-
samples[:, i] = petsc2numpy_vec(bv)
131-
132-
covariances = [np.cov(samples[:, :ns]) for ns in nsamples]
133-
134-
# Measured covariance matrix should converge at a rate of sqrt(n).
135-
# The number of samples is fairly small to keep the test cost
136-
# lower so we only test the mean rate to a low tolerance.
137-
138-
errors = [np.linalg.norm(cov-covmat) for cov in covariances]
139-
rate = -np.diff(np.log(errors))/np.diff(np.log(nsamples))
140-
141-
assert np.mean(rate) > 0.4
142-
143-
144-
@pytest.mark.skipcomplex
145-
@pytest.mark.parallel([1, 2])
146-
@pytest.mark.parametrize("m", (0, 2, 4))
147-
@pytest.mark.parametrize("dim", (0, 2), ids=["scalar", "vector2"])
148-
@pytest.mark.parametrize("family", ("CG", "DG"))
149-
@pytest.mark.parametrize("mesh_type", ("interval", "square"))
150-
def test_covariance_inverse_action(m, family, mesh_type, dim):
151-
"""Test that covariance operator action and inverse are opposites.
152-
"""
153-
154-
nx = 20
155-
if mesh_type == 'interval':
156-
mesh = PeriodicUnitIntervalMesh(nx)
157-
x, = SpatialCoordinate(mesh)
158-
wexpr = cos(2*pi*x)
159-
elif mesh_type == 'square':
160-
mesh = PeriodicUnitSquareMesh(nx, nx)
161-
x, y = SpatialCoordinate(mesh)
162-
wexpr = cos(2*pi*x)*cos(4*pi*y)
163-
elif mesh_type == 'cube':
164-
mesh = PeriodicUnitCubeMesh(nx, nx, nx)
165-
x, y, z = SpatialCoordinate(mesh)
166-
wexpr = cos(2*pi*x)*cos(4*pi*y)*cos(pi*z)
167-
if dim > 0:
168-
V = VectorFunctionSpace(mesh, family, 1, dim=dim)
169-
wexpr = as_vector([-1**(j+1)*wexpr for j in range(dim)])
170-
else:
171-
V = FunctionSpace(mesh, family, 1)
172-
173-
L = 0.1
174-
sigma = 0.9
175-
176-
solver_parameters = {
177-
'ksp_type': 'preonly',
178-
'pc_type': 'lu',
179-
'pc_factor_mat_solver_type': 'mumps'
180-
}
181-
182-
form = 'IP' if family == 'DG' else 'CG'
183-
184-
B = AutoregressiveCovariance(
185-
V, L, sigma, m, form=form,
186-
solver_parameters=solver_parameters,
187-
options_prefix="")
188-
189-
w = Function(V).project(wexpr)
190-
wcheck = B.apply_action(B.apply_inverse(w))
191-
192-
tol = 1e-10
193-
194-
assert errornorm(w, wcheck) < tol
195-
196-
197-
@pytest.mark.skipcomplex
198-
@pytest.mark.parallel([1, 2])
199-
@pytest.mark.parametrize("m", (0, 2, 4))
200-
def test_covariance_inverse_action_hdiv(m):
201-
"""Test that covariance operator action and inverse are opposites
202-
for hdiv spaces.
203-
"""
204-
205-
nx = 20
206-
mesh = PeriodicUnitSquareMesh(nx, nx)
207-
x, y = SpatialCoordinate(mesh)
208-
wexpr = cos(2*pi*x)*cos(4*pi*x)
209-
210-
V = FunctionSpace(mesh, "BDM", 1)
211-
wexpr = as_vector([-1**(j+1)*wexpr for j in range(2)])
212-
213-
L = 0.1
214-
sigma = 0.9
215-
216-
solver_parameters = {
217-
'ksp_type': 'preonly',
218-
'pc_type': 'lu',
219-
'pc_factor_mat_solver_type': 'mumps'
220-
}
221-
222-
B = AutoregressiveCovariance(
223-
V, L, sigma, m, form='IP',
224-
solver_parameters=solver_parameters,
225-
options_prefix="")
226-
227-
w = Function(V).project(wexpr)
228-
wcheck = B.apply_action(B.apply_inverse(w))
229-
230-
tol = 1e-8
231-
232-
assert errornorm(w, wcheck) < tol
6+
@pytest.fixture(autouse=True)
7+
def autouse_set_test_tape(set_test_tape):
8+
pass
2339

23410

23511
@pytest.mark.skipcomplex
@@ -269,133 +45,3 @@ def test_covariance_adjoint_norm(m, family):
26945
assert min(taylor['R0']['Rate']) > 0.95, taylor['R0']
27046
assert min(taylor['R1']['Rate']) > 1.95, taylor['R1']
27147
assert min(taylor['R2']['Rate']) > 2.95, taylor['R2']
272-
273-
274-
@pytest.mark.skipcomplex
275-
@pytest.mark.parallel([1, 2])
276-
@pytest.mark.parametrize("m", (0, 2, 4))
277-
@pytest.mark.parametrize("family", ("CG", "DG"))
278-
@pytest.mark.parametrize("operation", ("action", "inverse"))
279-
def test_covariance_mat(m, family, operation):
280-
"""Test that covariance mat and pc apply correct and opposite actions.
281-
"""
282-
nx = 20
283-
L = 0.2
284-
sigma = 0.9
285-
286-
mesh = UnitIntervalMesh(nx)
287-
coords, = SpatialCoordinate(mesh)
288-
289-
V = FunctionSpace(mesh, family, 1)
290-
291-
form = 'IP' if family == 'DG' else 'CG'
292-
293-
B = AutoregressiveCovariance(V, L, sigma, m, form=form)
294-
295-
mat = CovarianceMat(B, operation=operation)
296-
297-
expr = 2*pi*coords
298-
299-
if operation == 'action':
300-
x = Function(V).project(expr).riesz_representation()
301-
y = Function(V)
302-
xcheck = x.copy(deepcopy=True)
303-
ycheck = y.copy(deepcopy=True)
304-
305-
B.apply_action(xcheck, tensor=ycheck)
306-
307-
elif operation == 'inverse':
308-
x = Function(V).project(expr)
309-
y = Function(V.dual())
310-
xcheck = x.copy(deepcopy=True)
311-
ycheck = y.copy(deepcopy=True)
312-
313-
B.apply_inverse(xcheck, tensor=ycheck)
314-
315-
with x.dat.vec as xv, y.dat.vec as yv:
316-
mat.mult(xv, yv)
317-
318-
# flip to primal space to calculate norms
319-
if operation == 'inverse':
320-
y = y.riesz_representation()
321-
ycheck = ycheck.riesz_representation()
322-
323-
assert errornorm(ycheck, y)/norm(ycheck) < 1e-12
324-
325-
if operation == 'inverse':
326-
y = y.riesz_representation()
327-
ycheck = ycheck.riesz_representation()
328-
329-
ksp = PETSc.KSP().create()
330-
ksp.setOperators(mat)
331-
332-
tol = 1e-8
333-
334-
petsctools.set_from_options(
335-
ksp, options_prefix=str(operation),
336-
parameters={
337-
'ksp_monitor': None,
338-
'ksp_type': 'richardson',
339-
'ksp_max_it': 2,
340-
'ksp_rtol': tol,
341-
'pc_type': 'python',
342-
'pc_python_type': 'firedrake.adjoint.CovariancePC',
343-
}
344-
)
345-
x.zero()
346-
347-
with x.dat.vec as xv, y.dat.vec as yv:
348-
with petsctools.inserted_options(ksp):
349-
ksp.solve(yv, xv)
350-
351-
# CovarianceOperator operations should
352-
# be exact inverses of each other.
353-
assert ksp.its == 1
354-
355-
if operation == 'action':
356-
x = x.riesz_representation()
357-
xcheck = xcheck.riesz_representation()
358-
359-
assert errornorm(xcheck, x)/norm(xcheck) < 10*tol
360-
361-
362-
@pytest.mark.skipcomplex
363-
@pytest.mark.parametrize("family", ("CG", "DG"))
364-
def test_diffusion_form(family):
365-
"""Test that the provided diffusion forms converge to a known solution at the expected rate.
366-
"""
367-
from firedrake.adjoint.covariance_operator import diffusion_form
368-
369-
def poisson_error(mesh, family):
370-
V = FunctionSpace(mesh, family, 1)
371-
x, y = SpatialCoordinate(mesh)
372-
373-
f = Function(V).interpolate((1+8*pi*pi)*cos(x*pi*2)*cos(y*pi*2))
374-
uexact = cos(x*pi*2)*cos(y*pi*2)
375-
376-
nu = Constant(1)
377-
u = TrialFunction(V)
378-
v = TestFunction(V)
379-
380-
formulation = AutoregressiveCovariance.DiffusionForm(
381-
"CG" if family == "CG" else "IP")
382-
383-
a = diffusion_form(u, v, nu, formulation)
384-
L = inner(f, v)*dx
385-
386-
u = Function(V)
387-
solve(a == L, u)
388-
389-
return errornorm(uexact, u)
390-
391-
base_nx = 16
392-
nrefs = 3
393-
base_mesh = UnitSquareMesh(base_nx, base_nx)
394-
mh = MeshHierarchy(base_mesh, nrefs)
395-
396-
errors = [poisson_error(m, family) for m in mh]
397-
398-
# second order convergence
399-
nxs = [base_nx*(2**n) for n in range(nrefs+1)]
400-
rate = - np.diff(np.log(errors))/np.diff(np.log(nxs))
401-
assert (rate > 1.9).all()

0 commit comments

Comments
 (0)