@@ -280,6 +280,7 @@ def get_default_options(default_options_set: DefaultOptionSet,
280280 return default_options
281281
282282
283+ # TODO: Add note about how we 'freeze' options at instantiation
283284class OptionsManager :
284285 """Class that helps with managing setting PETSc options.
285286
@@ -405,76 +406,62 @@ class OptionsManager:
405406 AppContextManager
406407 """
407408
408- count = itertools . count ()
409+ count = 0
409410
410411 def __init__ (self , parameters : dict ,
411412 options_prefix : str | None = None ,
412413 default_prefix : str | None = None ,
413414 default_options_set : DefaultOptionSet | None = None ,
414415 appmngr : AppContextManager | None = None ):
415- super ().__init__ ()
416416 if parameters is None :
417417 parameters = {}
418418 else :
419419 # Convert nested dicts
420420 parameters = flatten_parameters (parameters )
421421
422422 # If no prefix is provided generate a default prefix
423- # and ignore any command line options
424423 if options_prefix is None :
425424 default_prefix = default_prefix or "petsctools_"
426425 default_prefix = _validate_prefix (default_prefix )
427- self .options_prefix = f"{ default_prefix } { next (self .count )} _"
428- self .parameters = parameters
429- self .to_delete = set (parameters )
430-
426+ options_prefix = f"{ default_prefix } { self .count } _"
427+ self .count += 1
428+ unsafe_prefix = True
431429 else :
432430 options_prefix = _validate_prefix (options_prefix )
433- self .options_prefix = options_prefix
434-
435- # Are we part of a solver set sharing defaults?
436- if default_options_set :
437- if options_prefix not in default_options_set .custom_prefixes :
438- raise ValueError (
439- f"The options_prefix { options_prefix } must be one"
440- f" of the custom_prefixes of the DefaultOptionSet"
441- f" { default_options_set .custom_prefixes } " )
442- default_options = get_default_options (
443- default_options_set , self .options_object )
444- else :
445- default_options = {}
446-
447- # Note: we need to know which parameters to_delete
448- # so we need to exclude the relevant command line
449- # options when combining the parameters from the
450- # defaults and the source code.
451-
452- # Start building parameters from the defaults so
453- # that they will overwritten by any other source.
454- self .parameters = {
455- k : v
456- for k , v in default_options .items ()
457- if options_prefix + k not in get_commandline_options ()
458- }
459-
460- # Update using the parameters passed in the code but
461- # exclude those options from the dict that were passed
462- # on the commandline because those have global scope and are
463- # not under the control of the options manager.
464- self .parameters .update ({
465- k : v
466- for k , v in parameters .items ()
467- if options_prefix + k not in get_commandline_options ()
468- })
469- self .to_delete = set (self .parameters )
470-
471- # Now update parameters from options, so that they're
472- # available to solver setup (for, e.g., matrix-free).
473- # Can't ask for the prefixed guy in the options object,
474- # since that does not DTRT for flag options.
475- for k , v in self .options_object .getAll ().items ():
476- if k .startswith (self .options_prefix ):
477- self .parameters [k [len (self .options_prefix ):]] = v
431+ unsafe_prefix = False
432+
433+ # Are we part of a solver set sharing defaults?
434+ if default_options_set :
435+ if options_prefix not in default_options_set .custom_prefixes :
436+ raise ValueError (
437+ f"The options_prefix { options_prefix } must be one"
438+ f" of the custom_prefixes of the DefaultOptionSet"
439+ f" { default_options_set .custom_prefixes } " )
440+ default_options = get_default_options (
441+ default_options_set , self .options_object )
442+ else :
443+ default_options = {}
444+
445+ # Start building parameters from the defaults so
446+ # that they will overwritten by any other source.
447+ parameters = default_options | parameters
448+
449+ # The parameters to drop from the global options when we leave the
450+ # inserted_options context. This is everything except for options
451+ # passed on the command line.
452+ to_delete = set (parameters .keys ())
453+ for k , v in self .options_object .getAll ().items ():
454+ if k .startswith (options_prefix ):
455+ if unsafe_prefix :
456+ print ("WARN" )
457+ parameters [k [len (options_prefix ):]] = v
458+ if k in to_delete :
459+ # option is set globally, don't drop when we leave the context
460+ to_delete .delete (k )
461+
462+ self .parameters = parameters
463+ self .to_delete = to_delete
464+ self .options_prefix = options_prefix
478465
479466 self ._setfromoptions = False
480467
@@ -562,12 +549,13 @@ def inserted_options(self):
562549 for k in self .to_delete :
563550 if self .options_object .used (self .options_prefix + k ):
564551 self ._used_options .add (k )
565- del self .options_object [self . options_prefix + k ]
552+ del self .options_object [k ]
566553
567554 @functools .cached_property
568555 def options_object (self ):
569556 from petsc4py import PETSc
570557
558+ # We can't pass the prefix here because that doesn't DTRT for flag options
571559 return PETSc .Options ()
572560
573561
0 commit comments