11import cgen as c
22import numpy as np
33from functools import cached_property
4- from sympy import Not
54
65from devito.passes.iet.engine import iet_pass
76from devito.ir.iet import (Transformer, MapNodes, Iteration, BlankLine,
87 DummyExpr, CallableBody, List, Call, Callable,
9- FindNodes, Section, Conditional )
8+ FindNodes, Section)
109from devito.symbolics import Byref, FieldFromPointer, Macro
1110from devito.types import Symbol, Scalar
1211from devito.types.basic import DataSymbol
1716 PointerIS, Mat, CallbackVec, Vec, CallbackMat, SNES,
1817 DummyArg, PetscInt, PointerDM, PointerMat, MatReuse,
1918 CallbackPointerIS, CallbackPointerDM, JacobianStruct,
20- SubMatrixStruct, Initialize, Finalize, ArgvSymbol,
21- CharPtr, PetscBool)
19+ SubMatrixStruct, Initialize, Finalize, ArgvSymbol)
2220from devito.petsc.types.macros import petsc_func_begin_user, Null
23- from devito.petsc.iet.nodes import PetscMetaData, PETScCallable
21+ from devito.petsc.iet.nodes import PetscMetaData
2422from devito.petsc.utils import core_metadata, petsc_languages
2523from devito.petsc.iet.routines import (CBBuilder, CCBBuilder, BaseObjectBuilder,
2624 CoupledObjectBuilder, BaseSetup, CoupledSetup,
@@ -71,16 +69,19 @@ def lower_petsc(iet, **kwargs):
7169 # Map PETScSolve to its Section (for logging)
7270 section_mapper = MapNodes(Section, PetscMetaData, 'groupby').visit(iet)
7371
74- # Generate a shared callback used by all PETScSolve instances to set
75- # individual PetscOptions
76- # set_solver_option(efuncs)
77- # List of all callbacks that clear PetscOptions
72+ # prefixes within a single Operator should not be duplicated
73+ prefixes = [d.expr.rhs.user_prefix for d in data if d.expr.rhs.user_prefix]
74+ duplicates = {p for p in prefixes if prefixes.count(p) > 1}
7875
79- # TODO: throw a warning/error if the user passes a solver in with the same options_prefix
80- # it's going to lead to weird solver option behaviour. Note, if you use the options_prefix across
81- # different Operator runs, it will not be an issue
82- clear_options = []
76+ # TODO: How to avoid the other exception raised given it is an iet_pass?
77+ if duplicates:
78+ dup_list = ", ".join(sorted(duplicates))
79+ raise ValueError(
80+ f"The following `options_prefix` values are duplicated "
81+ f"among your PETScSolves. Ensure each one is unique: {dup_list}"
82+ )
8383
84+ clear_options = []
8485 for iters, (inject_solve,) in inject_solve_mapper.items():
8586
8687 builder = Builder(inject_solve, iters, comm, section_mapper, **kwargs)
@@ -99,7 +100,6 @@ def lower_petsc(iet, **kwargs):
99100 populate_matrix_context(efuncs)
100101
101102 iet = Transformer(subs).visit(iet)
102- # from IPython import embed; embed()
103103 body = core + tuple(setup) + iet.body.body + tuple(clear_options)
104104 body = iet.body._rebuild(body=body)
105105 iet = iet._rebuild(body=body)
@@ -231,32 +231,6 @@ def populate_matrix_context(efuncs):
231231 )
232232
233233
234- def set_solver_option(efuncs):
235-
236- option = CharPtr(name='option', is_const=True)
237- value = CharPtr(name='value', is_const=True)
238- set = PetscBool(name='set')
239-
240- body = List(body=[
241- petsc_call('PetscOptionsHasName', [Null, Null, option, Byref(set)]),
242- Conditional(Not(set), petsc_call('PetscOptionsSetValue', [Null, option, value]))
243- ])
244-
245- body = CallableBody(
246- body,
247- init=(petsc_func_begin_user,),
248- retstmt=(Call('PetscFunctionReturn', arguments=[0]),)
249- )
250-
251- cb = PETScCallable(
252- 'SetPetscOption',
253- body,
254- retval=objs['err'],
255- parameters=(option, value)
256- )
257- efuncs[cb.name] = cb
258-
259-
260234subdms = PointerDM(name='subdms')
261235fields = PointerIS(name='fields')
262236submats = PointerMat(name='submats')
0 commit comments