Skip to content

Commit 048f693

Browse files
committed
misc: Docstrings, stop list output for PETScSolve, tests
1 parent 312c826 commit 048f693

6 files changed

Lines changed: 119 additions & 54 deletions

File tree

devito/petsc/iet/routines.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,13 @@ def _make_core(self):
129129
def _make_matvec(self, jacobian, prefix='MatMult'):
130130
# Compile matvec `eqns` into an IET via recursive compilation
131131
matvecs = jacobian.matvecs
132-
irs, _ = self.rcompile(matvecs,
133-
options={'mpi': False}, sregistry=self.sregistry,
134-
concretize_mapper=self.concretize_mapper)
135-
body = self._create_matvec_body(List(body=irs.uiet.body),
136-
jacobian)
132+
irs, _ = self.rcompile(
133+
matvecs, options={'mpi': False}, sregistry=self.sregistry,
134+
concretize_mapper=self.concretize_mapper
135+
)
136+
body = self._create_matvec_body(
137+
List(body=irs.uiet.body), jacobian
138+
)
137139

138140
objs = self.objs
139141
cb = PETScCallable(

devito/petsc/solve.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def build_expr(self):
7373
time_mapper=self.time_mapper,
7474
localinfo=localinfo
7575
)
76-
return [PetscEq(target, linear_solve)]
76+
return PetscEq(target, linear_solve)
7777

7878
def linear_solve_args(self):
7979
target, exprs = next(iter(self.target_exprs.items()))
@@ -98,14 +98,16 @@ def linear_solve_args(self):
9898
)
9999

100100
return target, tuple(funcs), field_data
101-
101+
102102
def generate_arrays(self, *targets):
103103
return {
104104
t: {
105-
p: PETScArray(name=f'{p}_{t.name}',
106-
target=t,
107-
liveness='eager',
108-
localinfo=localinfo)
105+
p: PETScArray(
106+
name=f'{p}_{t.name}',
107+
target=t,
108+
liveness='eager',
109+
localinfo=localinfo
110+
)
109111
for p in prefixes
110112
}
111113
for t in targets

devito/petsc/types/types.py

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -138,19 +138,19 @@ def eval(cls, *args):
138138

139139
class FieldData:
140140
"""
141-
Metadata class passed to `LinearSolveExpr`. Encapsulates metadata for a single
142-
`target` field needed to interface with PETSc SNES solvers.
141+
Metadata for a single `target` field passed to `LinearSolveExpr`.
142+
Used to interface with PETSc SNES solvers at the IET level.
143143

144144
Parameters
145145
----------
146146

147147
target : Function-like
148148
The target field to solve into, which is a Function-like object.
149149
jacobian : Jacobian
150-
Defines the matrix-vector product for the linear system, where the vector is
150+
Defines the matrix-vector product for the linear system, where the vector is
151151
the PETScArray representing the `target`.
152152
residual : Residual
153-
Defines the nonlinear residual function F(target) = 0.
153+
Defines the residual function F(target) = 0.
154154
initialguess : InitialGuess
155155
Defines the initial guess for the solution, which satisfies
156156
essential boundary conditions.
@@ -212,7 +212,8 @@ def targets(self):
212212
class MultipleFieldData(FieldData):
213213
"""
214214
Metadata class passed to `LinearSolveExpr`, for mixed-field problems,
215-
where the solution vector spans multiple `targets`.
215+
where the solution vector spans multiple `targets`. Used to interface
216+
with PETSc SNES solvers at the IET level.
216217

217218
Parameters
218219
----------
@@ -221,7 +222,7 @@ class MultipleFieldData(FieldData):
221222
jacobian : MixedJacobian
222223
Defines the matrix-vector products for the full system Jacobian.
223224
residual : MixedResidual
224-
Defines the nonlinear residual function F(targets) = 0.
225+
Defines the residual function F(targets) = 0.
225226
initialguess : InitialGuess
226227
Defines the initial guess metadata, which satisfies
227228
essential boundary conditions.
@@ -272,13 +273,17 @@ def space_order(self):
272273
def targets(self):
273274
return self._targets
274275

275-
276+
276277
class BaseJacobian:
277278
def __init__(self, arrays, target=None):
278279
self.arrays = arrays
279280
self.target = target
280281

281282
def _scale_non_bcs(self, matvecs, target=None):
283+
"""
284+
Scale the symbolic expressions `matvecs` by the grid cell volume,
285+
excluding EssentialBCs.
286+
"""
282287
target = target or self.target
283288
vol = target.grid.symbolic_volume_cell
284289

@@ -287,8 +292,20 @@ def _scale_non_bcs(self, matvecs, target=None):
287292
for m in matvecs
288293
]
289294

295+
def _scale_bcs(self, matvecs, scdiag):
296+
"""
297+
Scale the EssentialBCs in `matvecs` by `scdiag`.
298+
"""
299+
return [
300+
m._rebuild(rhs=m.rhs * scdiag) if isinstance(m, ZeroRow) else m
301+
for m in matvecs
302+
]
303+
290304
def _compute_scdiag(self, matvecs, col_target=None):
291305
"""
306+
Compute the diagonal scaling factor from the symbolic matrix-vector
307+
expressions in `matvecs`. If the centre stencil (i.e. the diagonal term of the
308+
matrix) is not unique, defaults to 1.0.
292309
"""
293310
x = self.arrays[col_target or self.target]['x']
294311

@@ -298,15 +315,6 @@ def _compute_scdiag(self, matvecs, col_target=None):
298315
}
299316
return centres.pop() if len(centres) == 1 else 1.0
300317

301-
def _scale_bcs(self, matvecs, scdiag):
302-
"""
303-
Scale the essential BCs
304-
"""
305-
return [
306-
m._rebuild(rhs=m.rhs * scdiag) if isinstance(m, ZeroRow) else m
307-
for m in matvecs
308-
]
309-
310318
def _build_matvec_expr(self, expr, **kwargs):
311319
col_target = kwargs.get('col_target', self.target)
312320
row_target = kwargs.get('row_target', self.target)
@@ -356,9 +364,9 @@ def __init__(self, target, exprs, arrays, time_mapper):
356364
def matvecs(self):
357365
# TODO: add shortcut explanation etc
358366
"""
359-
Stores the expressions used to generate the `MatMult`
360-
callback generated at the IET level. This function is
361-
passed to PETSc via `MatShellSetOperation(...,MATOP_MULT,(void (*)(void))MatMult)`.
367+
Stores the expressions used to generate the `MatMult` callback generated
368+
at the IET level. This function is passed to PETSc via
369+
`MatShellSetOperation(...,MATOP_MULT,(void (*)(void))MatMult)`.
362370
"""
363371
return self._matvecs
364372

@@ -517,7 +525,7 @@ def __repr__(self):
517525

518526
class Residual:
519527
"""
520-
Gennerates the metadata needed to define the nonlinear residual function
528+
Generates the metadata needed to define the nonlinear residual function
521529
F(target) = 0 for use with PETSc's SNES interface.
522530

523531
PETSc's SNES interface includes methods for solving nonlinear systems of
@@ -610,6 +618,8 @@ def _scale_bcs(self, eq, scdiag=None):
610618

611619
class MixedResidual(Residual):
612620
"""
621+
Generates the metadata needed to define the nonlinear residual function
622+
F(targets) = 0 for use with PETSc's SNES interface.
613623
"""
614624
def __init__(self, target_exprs, arrays, time_mapper, scdiag):
615625
self.targets = tuple(target_exprs.keys())
@@ -621,6 +631,9 @@ def __init__(self, target_exprs, arrays, time_mapper, scdiag):
621631
@property
622632
def b_exprs(self):
623633
"""
634+
For mixed solvers, a callback to form the RHS vector `b` is not generated,
635+
a single residual callback is generated to compute F(targets).
636+
TODO: Investigate if this is optimal.
624637
"""
625638
return None
626639

@@ -629,10 +642,10 @@ def _build_exprs(self, target_exprs):
629642
for t, exprs in target_exprs.items():
630643

631644
residual_exprs.extend(
632-
chain.from_iterable(self._build_residual(e, t)
633-
for e in as_tuple(exprs)
634-
))
635-
645+
chain.from_iterable(
646+
self._build_residual(e, t) for e in as_tuple(exprs)
647+
)
648+
)
636649
self._F_exprs = tuple(sorted(
637650
residual_exprs, key=lambda e: not isinstance(e, EssentialBC)
638651
))
@@ -671,7 +684,9 @@ def _build_residual(self, expr, target):
671684

672685
class InitialGuess:
673686
"""
674-
Enforce initial guess to satisfy essential BCs.
687+
Metadata passed to `LinearSolveExpr` to define the initial guess
688+
symbolic expressions, enforcing the initial guess to satisfy essential
689+
boundary conditions.
675690
"""
676691
def __init__(self, target, exprs, arrays):
677692
self.target = target
@@ -680,13 +695,12 @@ def __init__(self, target, exprs, arrays):
680695

681696
@property
682697
def exprs(self):
683-
"""
684-
"""
685698
return self._exprs
686699

687700
def _build_exprs(self, exprs):
688701
"""
689-
Return a list of initial guess expressions.
702+
Return a list of initial guess symbolic expressions
703+
that satisfy essential boundary conditions.
690704
"""
691705
self._exprs = tuple([
692706
eq for eq in

examples/petsc/cfd/01_navierstokes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ def neumann_right(eq, subdomain):
288288
tentu = PETScSolve([eq_u1]+bc_petsc_u1, u1.forward)
289289
tentv = PETScSolve([eq_v1]+bc_petsc_v1, v1.forward)
290290

291-
exprs = tentu + tentv + eqn_p + [update_u, update_v] + bc_u1 + bc_v1
291+
exprs = [tentu, tentv, eqn_p, update_u, update_v, bc_u1, bc_v1]
292292

293293
with switchconfig(language='petsc'):
294294
op = Operator(exprs)

examples/petsc/seismic/01_staggered_acoustic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
petsc_p_2 = PETScSolve(p_2, target=p2.forward, solver_parameters={'ksp_rtol': 1e-7})
6666

6767
with switchconfig(language='petsc'):
68-
op_2 = Operator(petsc_v_x_2 + petsc_v_z_2 + petsc_p_2 + src_p_2, opt='noop')
68+
op_2 = Operator([petsc_v_x_2, petsc_v_z_2, petsc_p_2, src_p_2], opt='noop')
6969
op_2(time=src.time_range.num-1, dt=dt)
7070

7171
norm_p2 = norm(p2)
@@ -90,7 +90,7 @@
9090
petsc_p_4 = PETScSolve(p_4, target=p4.forward, solver_parameters={'ksp_rtol': 1e-7})
9191

9292
with switchconfig(language='petsc'):
93-
op_4 = Operator(petsc_v_x_4 + petsc_v_z_4 + petsc_p_4 + src_p_4, opt='noop')
93+
op_4 = Operator([petsc_v_x_4, petsc_v_z_4, petsc_p_4, src_p_4], opt='noop')
9494
op_4(time=src.time_range.num-1, dt=dt)
9595

9696
norm_p4 = norm(p4)

0 commit comments

Comments
 (0)