Skip to content

Commit 7ec8bf0

Browse files
committed
compiler: Drop petscgetargs callback and add more functions to logging/get_info
1 parent 0189eb1 commit 7ec8bf0

13 files changed

Lines changed: 93 additions & 96 deletions

File tree

devito/ir/iet/visitors.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ def _gen_struct_decl(self, obj, masked=()):
292292
for i, (n, ct) in zip(fields, ctype._fields_):
293293
try:
294294
entries.append(self._gen_value(i, 0, masked=('const',)))
295+
295296
except AttributeError:
296297
cstr = self.ccode(ct)
297298
if ct is c_restrict_void_p:

devito/petsc/iet/logging.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ def __init__(self, level, get_info=None, **kwargs):
2727
'kspgetiterationnumber',
2828
'kspgettolerances',
2929
'kspgetconvergedreason',
30+
'kspgettype',
3031
# SNES specific
3132
'snesgetiterationnumber',
3233
]

devito/petsc/iet/passes.py

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from devito.ir.iet import (Transformer, MapNodes, Iteration, BlankLine,
77
DummyExpr, CallableBody, List, Call, Callable,
88
FindNodes, Section)
9-
from devito.symbolics import Byref, FieldFromPointer, Macro
9+
from devito.symbolics import Byref, FieldFromPointer, Macro, Null
1010
from devito.types import Symbol, Scalar
1111
from devito.types.basic import DataSymbol
1212
from devito.tools import frozendict
@@ -16,9 +16,8 @@
1616
PointerIS, Mat, CallbackVec, Vec, CallbackMat, SNES,
1717
DummyArg, PetscInt, PointerDM, PointerMat, MatReuse,
1818
CallbackPointerIS, CallbackPointerDM, JacobianStruct,
19-
SubMatrixStruct, Initialize, Finalize, ArgvSymbol,
20-
GetArgs, ArgvSymbolPtr, ArgcPtr)
21-
from devito.petsc.types.macros import petsc_func_begin_user, Null
19+
SubMatrixStruct, Initialize, Finalize, ArgvSymbol)
20+
from devito.petsc.types.macros import petsc_func_begin_user
2221
from devito.petsc.iet.nodes import PetscMetaData
2322
from devito.petsc.utils import core_metadata, petsc_languages
2423
from devito.petsc.iet.routines import (CBBuilder, CCBBuilder, BaseObjectBuilder,
@@ -52,9 +51,6 @@ def lower_petsc(iet, **kwargs):
5251
if any(filter(lambda i: isinstance(i.expr.rhs, Finalize), data)):
5352
return finalize(iet), core_metadata()
5453

55-
if any(filter(lambda i: isinstance(i.expr.rhs, GetArgs), data)):
56-
return get_args(iet), core_metadata()
57-
5854
unique_grids = {i.expr.rhs.grid for (i,) in inject_solve_mapper.values()}
5955
# Assumption is that all solves are on the same grid
6056
if len(unique_grids) > 1:
@@ -138,18 +134,6 @@ def finalize(iet):
138134
return iet._rebuild(body=finalize_body)
139135

140136

141-
def get_args(iet):
142-
argc = ArgcPtr(name='argc', dtype=np.int32)
143-
argv = ArgvSymbolPtr(name='argv')
144-
145-
body = petsc_call('PetscGetArgs', [argc, argv])
146-
body = CallableBody(
147-
body=(petsc_func_begin_user, body),
148-
retstmt=(Call('PetscFunctionReturn', arguments=[0]),)
149-
)
150-
return iet._rebuild(body=body)
151-
152-
153137
def make_core_petsc_calls(objs, comm):
154138
call_mpi = petsc_call_mpi('MPI_Comm_size', [comm, Byref(objs['size'])])
155139
return call_mpi, BlankLine

devito/petsc/iet/routines.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
retrieve_iteration_tree, filter_iterations, Iteration,
88
PointerCast)
99
from devito.symbolics import (Byref, FieldFromPointer, cast, VOID,
10-
FieldFromComposite, IntDiv, Deref, Mod, String)
10+
FieldFromComposite, IntDiv, Deref, Mod, String, Null)
1111
from devito.symbolics.unevaluation import Mul
1212
from devito.types.basic import AbstractFunction
1313
from devito.types import Temp, Dimension
@@ -21,8 +21,7 @@
2121
KSP, PC, SNES, PetscInt, StartPtr, PointerIS, PointerDM,
2222
VecScatter, DMCast, JacobianStruct, SubMatrixStruct,
2323
CallbackDM)
24-
from devito.petsc.types.macros import petsc_func_begin_user, Null
25-
# from devito.petsc.initialize import PetscGetArgs
24+
from devito.petsc.types.macros import petsc_func_begin_user
2625

2726

2827
class CBBuilder:
@@ -150,10 +149,10 @@ def _make_options_callback(self):
150149
for k, v in params.items():
151150
option = f'-{prefix}{k}'
152151

153-
# TODO: drop the global variable _petsc_clargs..
154-
# from devito.petsc.initialize import PetscGetArgs
155-
# PetscGetArgs()
156-
152+
# TODO: Revisit use of a global variable here.
153+
# Consider replacing this with a call to `PetscGetArgs`, though
154+
# initial attempts failed, possibly because the argv pointer is
155+
# created in Python?..
157156
import devito.petsc.initialize
158157
if option in devito.petsc.initialize._petsc_clargs:
159158
# Ensures that the command line args take priority

devito/petsc/initialize.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import os
22
import sys
3-
from ctypes import POINTER, cast, c_char, c_int, c_char_p, byref
3+
from ctypes import POINTER, cast, c_char
44
import atexit
55

66
from devito import Operator, switchconfig
77
from devito.types import Symbol
88
from devito.types.equation import PetscEq
9-
from devito.petsc.types import Initialize, Finalize, GetArgs
9+
from devito.petsc.types import Initialize, Finalize
1010

1111
global _petsc_initialized
1212
_petsc_initialized = False
@@ -26,7 +26,6 @@ def PetscInitialize(clargs=sys.argv):
2626
if clargs is not sys.argv:
2727
clargs = [sys.argv[0], *clargs]
2828

29-
# TODO: Drop this global variable
3029
_petsc_clargs = clargs
3130

3231
# TODO: Potentially just use cgen + the compiler machinery in Devito
@@ -43,24 +42,19 @@ def PetscInitialize(clargs=sys.argv):
4342
name='kernel_finalize', opt='noop'
4443
)
4544

45+
# Convert each string to a bytes object (e.g: '-ksp_type' -> b'-ksp_type')
4646
# `argv_bytes` must be a list so the memory address persists
4747
# `os.fsencode` should be preferred over `string().encode('utf-8')`
4848
# in case there is some system specific encoding in use
4949
argv_bytes = list(map(os.fsencode, clargs))
50+
51+
# POINTER(c_char) is equivalent to char * in C
52+
# (POINTER(c_char) * len(clargs)) creates a C array type: char *[len(clargs)]
53+
# Instantiating it with (*map(...)) casts each bytes object to a char * and
54+
# fills the array. The result is a char *argv[]
5055
argv_pointer = (POINTER(c_char)*len(clargs))(
5156
*map(lambda s: cast(s, POINTER(c_char)), argv_bytes)
5257
)
5358
op_init.apply(argc=len(clargs), argv=argv_pointer)
5459
atexit.register(op_finalize.apply)
5560
_petsc_initialized = True
56-
57-
58-
def PetscGetArgs():
59-
with switchconfig(language='petsc'):
60-
op_get_args = Operator(
61-
[PetscEq(dummy, GetArgs(dummy))],
62-
name='kernel_get_args', opt='noop'
63-
)
64-
argc_ptr = c_int()
65-
argv_ptr = (POINTER(c_char_p))()
66-
op_get_args.apply(argc=byref(argc_ptr), argv=byref(argv_ptr))

devito/petsc/logging.py

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
from collections import namedtuple, OrderedDict
22
from dataclasses import dataclass
3+
from functools import cached_property
4+
from cgen import Struct, Value
35

46
from devito.types import CompositeObject
57

6-
from devito.petsc.types import PetscInt, PetscScalar
7-
from devito.petsc.utils import petsc_type_mappings
8+
from devito.petsc.types import PetscInt, PetscScalar, KSPType
9+
from devito.petsc.utils import petsc_type_mappings, fixed_petsc_type_mappings
810

911

1012
class PetscEntry:
@@ -140,13 +142,26 @@ def __init__(self, name, pname, petsc_option_mapper, sobjs, section_mapper,
140142

141143
mapper = {v: k for k, v in petsc_type_mappings.items()}
142144

143-
fields = []
145+
pfields = []
146+
self._tmp_fields = []
147+
148+
# obj_mapper is e.g {'kspits': kspits0}
149+
# TODO: think this can just be for (x,y) in ....
144150
for obj_mapper in petsc_option_mapper.values():
145151
for petsc_option in obj_mapper.values():
146-
ctype = mapper[str(petsc_option._C_ctype)]
147-
fields.append((petsc_option.name, ctype))
152+
self._tmp_fields.append(petsc_option)
153+
# petsc_type is e.g. 'PetscInt', 'PetscScalar', 'KSPType'
154+
petsc_type = str(petsc_option.dtype)
155+
if petsc_type in mapper:
156+
ctype = mapper[petsc_type]
157+
else:
158+
ctype = fixed_petsc_type_mappings[petsc_type]
159+
pfields.append((petsc_option.name, ctype))
160+
super().__init__(name, pname, pfields)
148161

149-
super().__init__(name, pname, fields)
162+
@property
163+
def fields(self):
164+
return self._tmp_fields
150165

151166
@property
152167
def section(self):
@@ -177,9 +192,9 @@ def __getattr__(self, attr):
177192
# - If the function returns multiple values (e.g., KSPGetTolerances),
178193
# return a dictionary mapping each output name to its value,
179194
# e.g., {'rtol': val0, 'atol': val1, ...}.
180-
if len(obj_mapper) == 1:
181-
return get_val(next(iter(obj_mapper.values())))
182-
return {k: get_val(v) for k, v in obj_mapper.items()}
195+
if len(obj_mapper) > 1:
196+
return {k: get_val(v) for k, v in obj_mapper.items()}
197+
return get_val(next(iter(obj_mapper.values())))
183198

184199

185200
@dataclass
@@ -217,6 +232,12 @@ class PetscReturnVariable:
217232
input_params='ksp',
218233
output_param=('reason',),
219234
),
235+
'kspgettype': PetscReturnVariable(
236+
name='KSPGetType',
237+
variable_type=(KSPType,),
238+
input_params='ksp',
239+
output_param=('ksptype',),
240+
),
220241
# SNES specific
221242
'snesgetiterationnumber': PetscReturnVariable(
222243
name='SNESGetIterationNumber',

devito/petsc/solve.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,35 @@ def PETScSolve(target_exprs, target=None, solver_parameters=None,
4646
solver_parameters : dict, optional
4747
PETSc solver options.
4848
49+
Descriptions (not exhaustive):
50+
- 'ksp_type': Specifies the Krylov method (e.g., 'gmres', 'cg').
51+
- 'pc_type': Specifies the preconditioner type (e.g., ...).
52+
- 'ksp_rtol': Relative convergence tolerance for KSP solvers.
53+
- 'ksp_atol': Absolute convergence tolerance for KSP solvers.
54+
- 'ksp_divtol': Divergence tolerance, amount residual norm can increase before
55+
`KSPConvergedDefault()` concludes that the method is diverging.
56+
- 'ksp_max_it': Maximum number of KSP iterations to use.
57+
- 'snes_type': Type of SNES solver; 'ksponly' is used for linear solves.
58+
59+
References:
60+
- KSP types: https://petsc.org/main/manualpages/KSP/KSPType/
61+
- PC types: https://petsc.org/main/manualpages/PC/PCType/
62+
- KSP tolerances: https://petsc.org/main/manualpages/KSP/KSPSetTolerances/
63+
- SNES type: https://petsc.org/main/manualpages/SNES/SNESType/
64+
4965
options_prefix : str, optional
5066
Prefix for the solver, used to configure options via the command line. If not
5167
provided, a default prefix is generated by Devito.
5268
5369
get_info : list[str], optional
5470
A list of PETSc API functions to collect statistics from the solver.
55-
For example, `['kspgetiterationnumber', 'kspgettolerances']`.
71+
For example, `['kspgetiterationnumber', 'kspgettolerances']`.
72+
Capitalisation does not matter; e.g. `'KSPGetIterationNumber'` and
73+
`'kspgetiterationnumber'` are treated the same.
74+
75+
List of available functions:
76+
- ['kspgetiterationnumber', 'kspgettolerances', 'kspgetconvergedreason',
77+
'snesgetiterationnumber']
5678
5779
Returns
5880
-------
@@ -76,7 +98,7 @@ def __init__(self, solver_parameters=None, target_exprs=None, options_prefix=Non
7698
self.target_exprs = target_exprs
7799
self.user_prefix = options_prefix
78100
self.formatted_prefix = format_options_prefix(options_prefix)
79-
self.get_info = get_info
101+
self.get_info = [f.lower() for f in get_info]
80102

81103
def build_expr(self):
82104
target, funcs, field_data = self.linear_solve_args()

devito/petsc/solver_parameters.py

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,6 @@
11
from petsctools import flatten_parameters
22
import itertools
33

4-
"""
5-
Parameter descriptions:
6-
- 'ksp_type': Specifies the Krylov method (e.g., 'gmres', 'cg').
7-
- 'pc_type': Specifies the preconditioner type (e.g., ...).
8-
- 'ksp_rtol': Relative convergence tolerance for KSP solvers.
9-
- 'ksp_atol': Absolute convergence tolerance for KSP solvers.
10-
- 'ksp_divtol': Divergence tolerance, amount residual norm can increase before
11-
`KSPConvergedDefault()` concludes that the method is diverging.
12-
- 'ksp_max_it': Maximum number of KSP iterations to use.
13-
- 'snes_type': Type of SNES solver; 'ksponly' is used for linear solves.
14-
15-
References:
16-
- KSP types: https://petsc.org/main/manualpages/KSP/KSPType/
17-
- PC types: https://petsc.org/main/manualpages/PC/PCType/
18-
- KSP tolerances: https://petsc.org/main/manualpages/KSP/KSPSetTolerances/
19-
- SNES type: https://petsc.org/main/manualpages/SNES/SNESType/
20-
"""
21-
224

235
# NOTE: Will be extended, the default preconditioner is not going to be 'none'
246
base_solve_defaults = {
@@ -51,9 +33,9 @@ def linear_solver_parameters(solver_parameters):
5133

5234
def format_options_prefix(options_prefix):
5335
# NOTE: Modified from the `OptionsManager` inside petsctools
54-
if options_prefix is None:
36+
if not options_prefix:
5537
options_prefix = f"devito_{next(_options_prefix_counter)}_"
5638
else:
57-
if len(options_prefix) and not options_prefix.endswith("_"):
39+
if not options_prefix.endswith("_"):
5840
options_prefix += "_"
5941
return options_prefix

devito/petsc/types/macros.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import cgen as c
2-
from devito.symbolics import Macro
32

43

5-
Null = Macro('NULL')
6-
74
# TODO: Don't use c.Line here?
85
petsc_func_begin_user = c.Line('PetscFunctionBeginUser;')

devito/petsc/types/object.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from ctypes import POINTER, c_char, c_char_p, c_int
1+
from ctypes import POINTER, c_char, c_char_p
22

33
from devito.tools import CustomDtype, dtype_to_ctype, as_tuple, CustomIntType
44
from devito.types import (LocalObject, LocalCompositeObject, ModuloDimension,
@@ -113,6 +113,10 @@ class KSP(PetscObject):
113113
dtype = CustomDtype('KSP')
114114

115115

116+
class KSPType(PetscObject):
117+
dtype = CustomDtype('KSPType')
118+
119+
116120
class CallbackSNES(PetscObject):
117121
"""
118122
PETSc SNES : Non-Linear Systems Solvers.
@@ -305,22 +309,10 @@ def _C_ctype(self):
305309
return POINTER(POINTER(c_char))
306310

307311

308-
class ArgvSymbolPtr(DataSymbol):
309-
@property
310-
def _C_ctype(self):
311-
return POINTER(POINTER(c_char_p))
312-
313-
314-
class ArgcPtr(DataSymbol):
315-
@property
316-
def _C_ctype(self):
317-
return POINTER(c_int)
318-
319-
320-
class CharPtr(DataSymbol):
321-
@property
322-
def _C_ctype(self):
323-
return c_char_p
312+
# class CharPtr(DataSymbol):
313+
# @property
314+
# def _C_ctype(self):
315+
# return c_char_p
324316

325317

326318
FREE_PRIORITY = {

0 commit comments

Comments
 (0)