diff --git a/asQ/preconditioners/base.py b/asQ/preconditioners/base.py index 15dafd51..0a845880 100644 --- a/asQ/preconditioners/base.py +++ b/asQ/preconditioners/base.py @@ -9,17 +9,6 @@ from asQ.allatonce import AllAtOnceFunction, AllAtOnceCofunction -def get_default_options(default_prefix, custom_suffixes, options=PETSc.Options()): - custom_prefixes = (default_prefix + str(suffix) for suffix in custom_suffixes) - default_options = { - k.removeprefix(default_prefix): v - for k, v in options.getAll().items() - if k.startswith(default_prefix) - and not any(k.startswith(prefix) for prefix in custom_prefixes) - } - return default_options - - class AllAtOncePCBase(TimePartitionMixin): """ Base class for preconditioners for the all-at-once system. diff --git a/asQ/preconditioners/circulantpc.py b/asQ/preconditioners/circulantpc.py index 1d64cb8a..10475834 100644 --- a/asQ/preconditioners/circulantpc.py +++ b/asQ/preconditioners/circulantpc.py @@ -10,7 +10,7 @@ from asQ.common import get_option_from_list, get_deprecated_option from asQ.allatonce.function import time_average as time_average_function -from asQ.preconditioners.base import AllAtOnceBlockPCBase, get_default_options +from asQ.preconditioners.base import AllAtOnceBlockPCBase from functools import partial @@ -209,24 +209,6 @@ def initialize(self, pc): # user appctx for the blocks block_appctx = appctx.get('block_appctx', {}) - # Block i has prefix 'circulant_block_{i}', but we want to be able - # to set default options for all blocks using 'circulant_block'. - # LinearVariationalSolver will prioritise options it thinks are from - # the command line (including those in the `inserted_options` database - # of the AllAtOnceSolver) over the ones passed to __init__, so we pull - # the default options off the global dict and pass these explicitly to LVS. - - default_block_prefix = f"{prefix}block_" - deprecated_block_prefix = f"{self.deprecated_prefix}block_" - for k, v in PETSc.Options().getAll().items(): - if k.startswith(f"{deprecated_block_prefix}"): - msg = "Prefix 'diagfft' is deprecated and will be removed in the future. Use 'circulant' instead." - warn(msg) - default_block_prefix = deprecated_block_prefix - - default_block_options = get_default_options( - default_block_prefix, range(self.ntimesteps)) - # building the block problem solvers for i in range(self.nlocal_timesteps): ii = aaofunc.transform_index(i, from_range='slice', to_range='window') @@ -239,6 +221,7 @@ def initialize(self, pc): A = M + K # The rhs + v = fd.TestFunction(self.CblockV) L = self.block_rhs # pass parameters into PC: @@ -252,14 +235,31 @@ def initialize(self, pc): "form_mass": self.form_mass, "form_function": self.form_function, } + appctx_h.update(block_appctx) + # Options with prefix 'diagfft_block_' apply to all blocks by default + # If any options with prefix 'diagfft_block_{i}' exist, where i is the + # block number, then this prefix is used instead (like pc fieldsplit) + + block_prefix = f"{prefix}block_" + deprecated_block_prefix = f"{self.deprecated_prefix}block_" + for k, v in PETSc.Options().getAll().items(): + if k.startswith(f"{deprecated_block_prefix}"): + msg = "Prefix 'diagfft' is deprecated and will be removed in the future. Use 'circulant' instead." + warn(msg) + block_prefix = deprecated_block_prefix + + for k, v in PETSc.Options().getAll().items(): + if k.startswith(f"{block_prefix}{str(ii)}_"): + block_prefix = f"{block_prefix}{str(ii)}_" + break + block_problem = fd.LinearVariationalProblem(A, L, self.block_sol, bcs=self.block_bcs) - block_solver = fd.LinearVariationalSolver( - block_problem, appctx=appctx_h, - options_prefix=default_block_prefix+str(ii), - solver_parameters=default_block_options) + block_solver = fd.LinearVariationalSolver(block_problem, + appctx=appctx_h, + options_prefix=block_prefix) self.block_solvers.append(block_solver) diff --git a/asQ/preconditioners/jacobipc.py b/asQ/preconditioners/jacobipc.py index 17768d92..c4b475c7 100644 --- a/asQ/preconditioners/jacobipc.py +++ b/asQ/preconditioners/jacobipc.py @@ -5,8 +5,7 @@ from asQ.parallel_arrays import SharedArray from asQ.allatonce import (time_average, LinearSolver, AllAtOnceFunction, AllAtOnceCofunction) -from asQ.preconditioners.base import (AllAtOnceBlockPCBase, AllAtOncePCBase, - get_default_options) +from asQ.preconditioners.base import AllAtOnceBlockPCBase, AllAtOncePCBase __all__ = ['JacobiPC', 'SliceJacobiPC'] @@ -95,16 +94,6 @@ def initialize(self, pc): dt1 = fd.Constant(1/self.dt) tht = fd.Constant(self.theta) - # Block i has prefix 'aaojacobi_block_{i}', but we want to be able - # to set default options for all blocks using 'aaojacobi_block'. - # LinearVariationalSolver will prioritise options it thinks are from - # the command line (including those in the `inserted_options` database - # of the AllAtOnceSolver) over the ones passed to __init__, so we pull - # the default options off the global dict and pass these explicitly to LVS. - default_block_prefix = f"{self.full_prefix}block_" - default_block_options = get_default_options( - default_block_prefix, range(self.ntimesteps)) - # building the block problem solvers for i in range(self.nlocal_timesteps): @@ -134,17 +123,29 @@ def initialize(self, pc): appctx_h.update(block_appctx) - # the global index of this block + # Options with prefix 'aaojacobi_block_' apply to all blocks by default + # If any options with prefix 'aaojacobi_block_{i}' exist, where i is the + # block number, then this prefix is used instead (like pc fieldsplit) + ii = aaofunc.transform_index(i, from_range='slice', to_range='window') + block_prefix = f"{self.full_prefix}block_" + for k, v in PETSc.Options().getAll().items(): + if k.startswith(f"{block_prefix}{str(ii)}_"): + block_prefix = f"{block_prefix}{str(ii)}_" + break + # The block rhs/solution are the timestep i of the # input/output AllAtOnceCofunction/Function block_problem = fd.LinearVariationalProblem(A, self._x[i], self._y[i], bcs=self.block_bcs) - block_solver = fd.LinearVariationalSolver( - block_problem, appctx=appctx_h, - options_prefix=default_block_prefix+str(ii), - solver_parameters=default_block_options) + block_solver = fd.LinearVariationalSolver(block_problem, + appctx=appctx_h, + options_prefix=block_prefix) + # multigrid transfer manager + if f'{self.full_prefix}transfer_managers' in self.appctx: + tm = self.appctx[f'{self.prefix}transfer_managers'][i] + block_solver.set_transfer_manager(tm) self.block_solvers.append(block_solver)