Skip to content

Commit 1d8de25

Browse files
committed
misc: Add tests
1 parent c5cb7ee commit 1d8de25

8 files changed

Lines changed: 203 additions & 93 deletions

File tree

.github/workflows/pytest-petsc.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,13 @@ jobs:
7272
run: |
7373
${{ env.RUN_CMD }} python3 -c "from devito import configuration; print(''.join(['%s: %s \n' % (k, v) for (k, v) in configuration.items()]))"
7474
75-
- name: Test with pytest
75+
- name: Test with pytest - non parallel
7676
run: |
77-
${{ env.RUN_CMD }} mpiexec -n 1 pytest --cov --cov-config=.coveragerc --cov-report=xml ${{ env.TESTS }}
77+
${{ env.RUN_CMD }} mpiexec -n 1 pytest -m "not parallel" --cov --cov-config=.coveragerc --cov-report=xml ${{ env.TESTS }}
78+
79+
- name: Test with pytest - parallel
80+
run: |
81+
${{ env.RUN_CMD }} mpiexec -n 1 pytest -m parallel --cov --cov-config=.coveragerc --cov-report=xml ${{ env.TESTS }}
7882
7983
- name: Test examples
8084
run: |

devito/petsc/iet/passes.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
DummyArg, PetscInt, PointerDM, PointerMat, MatReuse,
1919
CallbackPointerIS, CallbackPointerDM, JacobianStruct,
2020
SubMatrixStruct, Initialize, Finalize, ArgvSymbol,
21-
ConstCharPtr, PetscBool)
21+
CharPtr, PetscBool)
2222
from devito.petsc.types.macros import petsc_func_begin_user, Null
2323
from devito.petsc.iet.nodes import PetscMetaData, PETScCallable
2424
from devito.petsc.utils import core_metadata, petsc_languages
@@ -71,7 +71,8 @@ def lower_petsc(iet, **kwargs):
7171
# Map PETScSolve to its Section (for logging)
7272
section_mapper = MapNodes(Section, PetscMetaData, 'groupby').visit(iet)
7373

74-
# Callback used to set a PetscOption - used by all PETScSolves
74+
# Generate a shared callback used by all PETScSolve instances to set
75+
# individual PetscOptions
7576
set_solver_option(efuncs)
7677

7778
for iters, (inject_solve,) in inject_solve_mapper.items():
@@ -222,8 +223,8 @@ def populate_matrix_context(efuncs):
222223

223224
def set_solver_option(efuncs):
224225

225-
option = ConstCharPtr(name='option', is_const=True)
226-
value = ConstCharPtr(name='value', is_const=True)
226+
option = CharPtr(name='option', is_const=True)
227+
value = CharPtr(name='value', is_const=True)
227228
set = PetscBool(name='set')
228229

229230
body = List(body=[

devito/petsc/iet/routines.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -107,33 +107,31 @@ def target(self):
107107
return self.field_data.target
108108

109109
def _make_core(self):
110-
self._petsc_options_callback()
110+
self._make_options_callback()
111111
self._make_matvec(self.field_data.jacobian)
112112
self._make_formfunc()
113113
self._make_formrhs()
114114
if self.field_data.initial_guess.exprs:
115115
self._make_initial_guess()
116116
self._make_user_struct_callback()
117117

118-
def _petsc_options_callback(self):
118+
def _make_options_callback(self):
119119
objs = self.objs
120120
params = self.solver_parameters
121121
prefix = self.inject_solve.expr.rhs.formatted_prefix
122122

123-
body = [
124-
petsc_call(
125-
'SetPetscOption', [String(f"-{prefix}{k}"), String(str(v))]
126-
)
127-
for k, v in params.items()
128-
]
123+
body = []
124+
for k, v in params.items():
125+
option_key = String(f"-{prefix}{k}")
126+
option_value = Null if v is None else String(str(v))
127+
body.append(petsc_call('SetPetscOption', [option_key, option_value]))
129128

130129
body = CallableBody(
131130
List(body=body),
132131
init=(petsc_func_begin_user,),
133132
retstmt=(Call('PetscFunctionReturn', arguments=[0]),)
134133
)
135134

136-
objs = self.objs
137135
cb = PETScCallable(
138136
self.sregistry.make_name(prefix='SetPetscOptions'),
139137
body,
@@ -694,7 +692,7 @@ def _make_core(self):
694692
for sm in self.field_data.jacobian.nonzero_submatrices:
695693
self._make_matvec(sm, prefix=f'{sm.name}_MatMult')
696694

697-
self._petsc_options_callback()
695+
self._make_options_callback()
698696
self._make_whole_matvec()
699697
self._make_whole_formfunc()
700698
self._make_user_struct_callback()
@@ -1289,7 +1287,7 @@ def _setup(self):
12891287
local_size = math.prod(
12901288
v for v, dim in zip(target.shape_allocated, target.dimensions) if dim.is_Space
12911289
)
1292-
# TODO: Check, maybe this should be VecCreateSeqWithArray
1290+
# TODO: Check - VecCreateSeqWithArray
12931291
local_x = petsc_call('VecCreateMPIWithArray',
12941292
[sobjs['comm'], 1, local_size, 'PETSC_DECIDE',
12951293
field_from_ptr, Byref(sobjs['xlocal'])])

devito/petsc/types/object.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ def _C_ctype(self):
303303
return POINTER(POINTER(c_char))
304304

305305

306-
class ConstCharPtr(DataSymbol):
306+
class CharPtr(DataSymbol):
307307
@property
308308
def _C_ctype(self):
309309
return c_char_p

devito/petsc/types/types.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,8 @@ def eval(cls, *args):
115115

116116
class LinearSolveExpr(SolveExpr):
117117
"""
118-
Linear problems are handled with
119-
`SNESSetType(snes, KSPONLY)`, enabling a unified interface for both
120-
linear and nonlinear solvers.
118+
Linear problems are handled by setting the SNESType to 'ksponly',
119+
enabling a unified interface for both linear and nonlinear solvers.
121120
"""
122121
pass
123122

examples/petsc/solver_options.py

Lines changed: 28 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
switchconfig)
66
from devito.petsc import PETScSolve
77
from devito.petsc.initialize import PetscInitialize
8-
import petsctools
9-
from petsctools import get_commandline_options, OptionsManager, flatten_parameters
108
configuration['compiler'] = 'custom'
119
os.environ['CC'] = 'mpicc'
1210

@@ -34,79 +32,38 @@
3432

3533
eq = Eq(v, u.laplace, subdomain=grid.interior)
3634

37-
solver = PETScSolve([eq], u, solver_parameters={'ksp_rtol': 1e-8}, options_prefix='poisson')
35+
solver = PETScSolve([eq], u)
3836

39-
with switchconfig(language='petsc'):
37+
with switchconfig(language='petsc', opt='noop'):
4038
op = Operator(solver)
4139
op.apply()
42-
print(op.ccode)
43-
44-
45-
# import sys
46-
# petsctools.options._commandline_options = sys.argv[1:]
47-
# tmp = get_commandline_options()
48-
# print("Command line options:", tmp)
49-
50-
51-
52-
# class DevitoOptionsManager(OptionsManager):
53-
# """
54-
# """
55-
# def __init__(self, parameters, options_prefix):
56-
# if parameters is None:
57-
# parameters = {}
58-
# else:
59-
# # Convert nested dicts
60-
# parameters = flatten_parameters(parameters)
61-
# if options_prefix is None:
62-
# self.options_prefix = "firedrake_%d_" % next(self.count)
63-
# self.parameters = parameters
64-
# self.to_delete = set(parameters)
65-
# else:
66-
# if len(options_prefix) and not options_prefix.endswith("_"):
67-
# options_prefix += "_"
68-
# self.options_prefix = options_prefix
69-
# # Remove those options from the dict that were passed on
70-
# # the commandline.
71-
# self.parameters = {
72-
# k: v
73-
# for k, v in parameters.items()
74-
# if options_prefix + k not in get_commandline_options()
75-
# }
76-
# self.to_delete = set(self.parameters)
77-
# # Now update parameters from options, so that they're
78-
# # available to solver setup (for, e.g., matrix-free).
79-
# # Can't ask for the prefixed guy in the options object,
80-
# # since that does not DTRT for flag options.
81-
# # for k, v in self.options_object.getAll().items():
82-
# # if k.startswith(self.options_prefix):
83-
# # self.parameters[k[len(self.options_prefix):]] = v
84-
85-
# for k, v in get_commandline_options():
86-
# if k.startswith(self.options_prefix):
87-
# self.parameters[k[len(self.options_prefix):]] = v
88-
# self._setfromoptions = False
89-
90-
91-
92-
# options_manager = DevitoOptionsManager(solver.rhs.solver_parameters, solver.rhs.options_prefix)
93-
94-
95-
# nested = {"ksp_type": "cg",
96-
# "pc_type": "fieldsplit",
97-
# "fieldsplit_0": {"ksp_type": "gmres",
98-
# "pc_type": "hypre",
99-
# "ksp_rtol": 1e-5},
100-
# "fieldsplit_1": {"ksp_type": "richardson",
101-
# "pc_type": "ilu"}}
102-
103-
# tmp = flatten_parameters(nested)
104-
# # from IPython import embed; embed()
105-
106-
# # convert all values into strings
107-
108-
# tmp_str = {k: str(v) for k, v in tmp.items()}
40+
# print(op.ccode)
41+
42+
43+
44+
45+
46+
grid = Grid(shape=(11, 11), dtype=np.float64)
47+
functions = [Function(name=n, grid=grid, space_order=2)
48+
for n in ['e', 'f']]
49+
e, f = functions
50+
51+
eq = Eq(e.laplace, f)
52+
53+
petsc = PETScSolve(eq, target=e, solver_parameters={'snes_view': None})
54+
55+
with switchconfig(language='petsc'):
56+
op = Operator(petsc)
57+
op.apply()
58+
59+
assert 'PetscCall(SetPetscOption("-snes_view",NULL));' \
60+
in str(op._func_table['SetPetscOptions0'].root)
61+
62+
from devito.petsc.solver_parameters import linear_solve_defaults
63+
64+
10965

66+
from IPython import embed; embed()
11067

11168

11269

requirements-optional.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ pillow>11,<11.2.2
33
pyrevolve==2.2.4
44
scipy<1.15.3
55
distributed<2025.4.2
6-
click<9.0
6+
click<9.0

0 commit comments

Comments
 (0)