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