compiler: Rework /petsc/iet and PETScArrays#38
compiler: Rework /petsc/iet and PETScArrays#38ZoeLeibowitz merged 20 commits intoFieldFromPointerfrom
Conversation
841a8da to
727e77c
Compare
mloubout
left a comment
There was a problem hiding this comment.
Mostly minor comments.
The iet layer could use more docstring and comments for maintainability but it can wait for later updates.
devito/petsc/iet/passes.py
Outdated
| for iters, (injectsolve,) in injectsolve_mapper.items(): | ||
|
|
||
| builder = PETScCallbackBuilder(**kwargs) | ||
| builder_classes = get_builder_classes(injectsolve) |
There was a problem hiding this comment.
Could make it an object or namedtuple so you can can have buillder.objbuilder and such, might make it easier to extend/maintain as well.
There was a problem hiding this comment.
I've now created the Builder class inside petsc/iet/passes to encapsulate this. What do you think?
devito/petsc/iet/passes.py
Outdated
| solver_objs = build_solver_objs(injectsolve, iters, **kwargs) | ||
| time_dep = dep(injectsolve, **kwargs) | ||
|
|
||
| solver_objs = ObjBuilder(dep=time_dep, **kwargs).build(injectsolve, iters) |
There was a problem hiding this comment.
They all seem to take the same input so you'd be able to just init the builder with all its components at once
devito/petsc/iet/passes.py
Outdated
| subs.update({space_iter: List(body=runsolve)}) | ||
| # Transform the spatial iteration loop with the calls to execute the solver | ||
| space_iter, = spatial_loop_nest(iters, injectsolve) | ||
| runsolve = SolverRun(dep=time_dep).runsolve( |
There was a problem hiding this comment.
personal nitpicking: i'd avoid using "run"
devito/petsc/iet/passes.py
Outdated
| mapper = {solver_objs['dummyctx']: solver_objs['localctx']} | ||
| return Uxreplace(mapper).visit(efunc) | ||
|
|
||
| return {k: replace(v) for k, v in efuncs.items()} |
There was a problem hiding this comment.
why define an inner function instead of a plain loop
mapper = {}
vistor = Uxreplace({solver_objs['dummyctx']: solver_objs['localctx']})
for k, v in efuncs.items():
mapper.update(vistor.visit(v))
return mapper
Either way Uxreplace(mapper) is the same for all efuncs so should only need to make it once
devito/petsc/iet/routines.py
Outdated
| obj = object.__new__(cls) | ||
| obj.rcompile = rcompile | ||
| obj.sregistry = sregistry | ||
| obj.concretize_mapper = kwargs.get('concretize_mapper', {}) |
There was a problem hiding this comment.
So this is tied to the OSS PR right?
There was a problem hiding this comment.
I've actually dropped it now since I use the same SymbolRegistry throughout, even with rcompile
devito/petsc/iet/routines.py
Outdated
| } | ||
|
|
||
|
|
||
| class SetupSolver: |
There was a problem hiding this comment.
Does this really need to be a class if it's stateless instead of three plain functions?
There was a problem hiding this comment.
I've now added a hook for subclasses to add additional setup calls
devito/petsc/iet/routines.py
Outdated
| if not time_iter: | ||
| return mapper | ||
|
|
||
| for d in time_iter[0].dimensions: |
There was a problem hiding this comment.
I've corrected this now
|
|
||
| @classmethod | ||
| def __indices_setup__(cls, *args, **kwargs): | ||
| dimensions = kwargs['target'].space_dimensions |
There was a problem hiding this comment.
why not just dimensions ?
There was a problem hiding this comment.
PETScArray objects correspond to PETSc Vec objects, which represent the spatial domain and are used at each time step.
| 'ksp_type': 'gmres', | ||
| 'pc_type': 'jacobi', | ||
| 'ksp_rtol': 1e-7, # Relative tolerance | ||
| 'ksp_rtol': 1e-5, # Relative tolerance |
There was a problem hiding this comment.
These need to be documented in docstring
|
|
||
| matvecs, formfuncs, formrhs = ( | ||
| [eq.subs(time_mapper) for eq in lst] for lst in (matvecs, formfuncs, formrhs) | ||
| [eq.xreplace(time_mapper) for eq in lst] for lst in (matvecs, formfuncs, formrhs) |
There was a problem hiding this comment.
out of curiosity why this change?
There was a problem hiding this comment.
I think both work fine. I can't remember exactly why I changed it. Should it stay as subs?
There was a problem hiding this comment.
not worth another spin of CI imho -- up to you :)
There was a problem hiding this comment.
xreplace is what introduced a bug with custom coeff legacy API, it sometimes only replaces the first occurrence it finds instead of all so if there is more than one occurrence it's likely to break
There was a problem hiding this comment.
Oh ok, will change it back in my next PR.
| calls = [call_struct_callback] + calls_set_app_ctx | ||
| def _spatial_loop_nest(self, iters, injectsolve): | ||
| spatial_body = [] | ||
| for tree in retrieve_iteration_tree(iters[0]): |
There was a problem hiding this comment.
What is special about iters[0] here?
| These are not set in the `PopulateMatContext` callback. | ||
| """ | ||
| return [f for f in self.fields | ||
| if isinstance(f, (ModuloDimension, TimeDimension))] |
There was a problem hiding this comment.
if isinstance(f, (ModuloDimension, TimeDimension))]
could be replaced with
if f.is_Time
?
| matvec_callback, formfunc_callback, formrhs_callback = self.make_all( | ||
| injectsolve, objs, solver_objs | ||
| ) | ||
| @property |
There was a problem hiding this comment.
Nitpick: should be cached_property
|
|
||
| # Global dimensions | ||
| args.extend(list(grid.shape)[::-1]) | ||
| # No.of processors in each dimension |
There was a problem hiding this comment.
Nitpick: missing space in comment
| - Modulo dimensions are updated in the matrix context struct at each time | ||
| step and can be accessed in the callback functions where needed. | ||
| """ | ||
| @property |
There was a problem hiding this comment.
Nitpick: should probably be cached_property, but tbh is so cheap it doesn't really matter
| } | ||
| subs = {symb: true_dims[time_mapper[symb]] for symb in time_mapper} | ||
| return Uxreplace(subs).visit(body) | ||
| @property |
There was a problem hiding this comment.
Nitpick: should use cached_property
| target_time = target_time.pop() | ||
| return target_time | ||
|
|
||
| @property |
| @@ -107,11 +115,6 @@ def _C_ctype(self): | |||
| @property | |||
| def symbolic_shape(self): | ||
| field_from_composites = [ | ||
| FieldFromComposite('g%sm' % d.name, self.dmda.info) for d in self.dimensions] | ||
| FieldFromComposite('g%sm' % d.name, self.localinfo) for d in self.dimensions] |
| @@ -160,9 +182,21 @@ def fields(self): | |||
|
|
|||
| @property | |||
There was a problem hiding this comment.
Nitpick: probably should be cached
| return [f for f in self.fields | ||
| if isinstance(f, (ModuloDimension, TimeDimension))] | ||
|
|
||
| @property |
devito/petsc/iet/routines.py
Outdated
|
|
||
| def create_formrhs_body(self, injectsolve, body, solver_objs, objs): | ||
| linsolveexpr = injectsolve.expr.rhs | ||
| def _create_formrhs_body(self, injectsolve, body, solver_objs, objs): |
There was a problem hiding this comment.
| def _create_formrhs_body(self, injectsolve, body, solver_objs, objs): | |
| def _create_form_rhs_body(self, injectsolve, body, solver_objs, objs): |
?
64870de to
579045f
Compare
eec492e to
0106f9a
Compare
e26e832 to
ef7ee34
Compare
petsc/ietby introducing more classes to reduce the number of free functions, and enable flexibility to accommodate different types of solvers with varying setups, callbacks, and other configurations etc. (many free functions insidepetsc/iet/passes.pyhave moved into new classes insidepetsc/iet/routines.py)