Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change datatype of ksp_options to be (lists of) dictionaries #164

Merged
merged 2 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ of the maintenance releases, please take a look at

* The BFGS method can now be used in a damped fashion. This ensures that the inverse Hessian approximation stays positive definite.

* The options for defining parameters which are to be supplied to PETSc KSP objects have changed their datatype: They are now given by (lists of) dictionaries instead of nested lists. For options without a value in the command line (e.g. the option :bash:`-ksp_view`) have a value of :python:`None` in the dictionary (so :python:`'ksp_view': None` can be used inside the dictionary to supply the aforementioned option).

* Changed configuration file parameters

* Section Output
Expand Down
30 changes: 12 additions & 18 deletions cashocs/_constraints/constrained_problems.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,9 @@ def __init__(
constraint_list: Union[List[_typing.Constraint], _typing.Constraint],
config: Optional[io.Config] = None,
initial_guess: Optional[List[fenics.Function]] = None,
ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
] = None,
ksp_options: Optional[Union[_typing.KspOption, List[_typing.KspOption]]] = None,
adjoint_ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
Union[_typing.KspOption, List[_typing.KspOption]]
] = None,
) -> None:
"""Initializes self.
Expand Down Expand Up @@ -88,10 +86,10 @@ def __init__(
initial_guess: List of functions that act as initial guess for the state
variables, should be valid input for :py:func:`fenics.assign`. Defaults
to ``None``, which means a zero initial guess.
ksp_options: A list of strings corresponding to command line options for
ksp_options: A list of dicts corresponding to command line options for
PETSc, used to solve the state systems. If this is ``None``, then the
direct solver mumps is used (default is ``None``).
adjoint_ksp_options: A list of strings corresponding to command line options
adjoint_ksp_options: A list of dicts corresponding to command line options
for PETSc, used to solve the adjoint systems. If this is ``None``, then
the same options as for the state systems are used (default is
``None``).
Expand Down Expand Up @@ -274,11 +272,9 @@ def __init__(
riesz_scalar_products: Optional[Union[ufl.Form, List[ufl.Form]]] = None,
control_constraints: Optional[List[List[Union[float, fenics.Function]]]] = None,
initial_guess: Optional[List[fenics.Function]] = None,
ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
] = None,
ksp_options: Optional[Union[_typing.KspOption, List[_typing.KspOption]]] = None,
adjoint_ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
Union[_typing.KspOption, List[_typing.KspOption]]
] = None,
control_bcs_list: Optional[
Union[
Expand Down Expand Up @@ -322,10 +318,10 @@ def __init__(
initial_guess: List of functions that act as initial guess for the state
variables, should be valid input for :py:func:`fenics.assign`. Defaults
to ``None``, which means a zero initial guess.
ksp_options: A list of strings corresponding to command line options for
ksp_options: A list of dicts corresponding to command line options for
PETSc, used to solve the state systems. If this is ``None``, then the
direct solver mumps is used (default is ``None``).
adjoint_ksp_options: A list of strings corresponding to command line options
adjoint_ksp_options: A list of dicts corresponding to command line options
for PETSc, used to solve the adjoint systems. If this is ``None``, then
the same options as for the state systems are used (default is
``None``).
Expand Down Expand Up @@ -443,11 +439,9 @@ def __init__(
config: Optional[io.Config] = None,
shape_scalar_product: Optional[ufl.Form] = None,
initial_guess: Optional[List[fenics.Function]] = None,
ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
] = None,
ksp_options: Optional[Union[_typing.KspOption, List[_typing.KspOption]]] = None,
adjoint_ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
Union[_typing.KspOption, List[_typing.KspOption]]
] = None,
) -> None:
"""Initializes self.
Expand Down Expand Up @@ -483,10 +477,10 @@ def __init__(
initial_guess: List of functions that act as initial guess for the state
variables, should be valid input for :py:func:`fenics.assign`. Defaults
to ``None``, which means a zero initial guess.
ksp_options: A list of strings corresponding to command line options for
ksp_options: A list of dicts corresponding to command line options for
PETSc, used to solve the state systems. If this is ``None``, then the
direct solver mumps is used (default is ``None``).
adjoint_ksp_options: A list of strings corresponding to command line options
adjoint_ksp_options: A list of dicts corresponding to command line options
for PETSc, used to solve the adjoint systems. If this is ``None``, then
the same options as for the state systems are used (default is
``None``).
Expand Down
4 changes: 2 additions & 2 deletions cashocs/_database/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ def __init__(
config: io.Config,
states: List[fenics.Function],
adjoints: List[fenics.Function],
state_ksp_options: _typing.KspOptions,
adjoint_ksp_options: _typing.KspOptions,
state_ksp_options: List[_typing.KspOption],
adjoint_ksp_options: List[_typing.KspOption],
cost_functional_list: List[_typing.CostFunctional],
state_forms: List[ufl.Form],
bcs_list: List[List[fenics.DirichletBC]],
Expand Down
6 changes: 3 additions & 3 deletions cashocs/_database/parameter_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from __future__ import annotations

from typing import Dict, TYPE_CHECKING
from typing import Dict, List, TYPE_CHECKING

from cashocs import _exceptions
from cashocs import _utils
Expand All @@ -37,8 +37,8 @@ def __init__(
self,
function_db: function_database.FunctionDatabase,
config: io.Config,
state_ksp_options: _typing.KspOptions,
adjoint_ksp_options: _typing.KspOptions,
state_ksp_options: List[_typing.KspOption],
adjoint_ksp_options: List[_typing.KspOption],
) -> None:
"""Initializes the database.

Expand Down
21 changes: 11 additions & 10 deletions cashocs/_forms/shape_form_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from __future__ import annotations

import itertools
from typing import List, Optional, Tuple, TYPE_CHECKING, Union
from typing import List, Optional, Tuple, TYPE_CHECKING

import fenics
import numpy as np
Expand All @@ -37,6 +37,7 @@
if TYPE_CHECKING:
import ufl.core.expr

from cashocs import _typing
from cashocs import io
from cashocs._database import database
from cashocs._optimization import shape_optimization
Expand Down Expand Up @@ -84,7 +85,7 @@ def __init__(

self.A_mu_matrix = fenics.PETScMatrix() # pylint: disable=invalid-name
self.b_mu = fenics.PETScVector()
self.options_mu: List[List[Union[str, int, float]]] = []
self.options_mu: _typing.KspOption = {}

self._setup_mu_computation()

Expand All @@ -98,14 +99,14 @@ def _setup_mu_computation(self) -> None:

self.inhomogeneous_mu = True

self.options_mu = [
["ksp_type", "cg"],
["pc_type", "hypre"],
["pc_hypre_type", "boomeramg"],
["ksp_rtol", 1e-16],
["ksp_atol", 1e-50],
["ksp_max_it", 100],
]
self.options_mu = {
"ksp_type": "cg",
"pc_type": "hypre",
"pc_hypre_type": "boomeramg",
"ksp_rtol": 1e-16,
"ksp_atol": 1e-50,
"ksp_max_it": 100,
}

phi = fenics.TrialFunction(self.cg_function_space)
psi = fenics.TestFunction(self.cg_function_space)
Expand Down
10 changes: 4 additions & 6 deletions cashocs/_optimization/optimal_control/optimal_control_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,9 @@ def __init__(
riesz_scalar_products: Optional[Union[List[ufl.Form], ufl.Form]] = None,
control_constraints: Optional[List[List[Union[float, fenics.Function]]]] = None,
initial_guess: Optional[List[fenics.Function]] = None,
ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
] = None,
ksp_options: Optional[Union[_typing.KspOption, List[_typing.KspOption]]] = None,
adjoint_ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
Union[_typing.KspOption, List[_typing.KspOption]]
] = None,
desired_weights: Optional[List[float]] = None,
control_bcs_list: Optional[
Expand Down Expand Up @@ -118,10 +116,10 @@ def __init__(
initial_guess: List of functions that act as initial guess for the state
variables, should be valid input for :py:func:`fenics.assign`. Defaults
to ``None``, which means a zero initial guess.
ksp_options: A list of strings corresponding to command line options for
ksp_options: A list of dicts corresponding to command line options for
PETSc, used to solve the state systems. If this is ``None``, then the
direct solver mumps is used (default is ``None``).
adjoint_ksp_options: A list of strings corresponding to command line options
adjoint_ksp_options: A list of dicts corresponding to command line options
for PETSc, used to solve the adjoint systems. If this is ``None``, then
the same options as for the state systems are used (default is
``None``).
Expand Down
36 changes: 15 additions & 21 deletions cashocs/_optimization/optimization_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,9 @@ def __init__(
adjoints: Union[List[fenics.Function], fenics.Function],
config: Optional[io.Config] = None,
initial_guess: Optional[Union[List[fenics.Function], fenics.Function]] = None,
ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
] = None,
ksp_options: Optional[Union[_typing.KspOption, List[_typing.KspOption]]] = None,
adjoint_ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
Union[_typing.KspOption, List[_typing.KspOption]]
] = None,
desired_weights: Optional[List[float]] = None,
temp_dict: Optional[Dict] = None,
Expand Down Expand Up @@ -120,10 +118,10 @@ def __init__(
initial_guess: List of functions that act as initial guess for the state
variables, should be valid input for :py:func:`fenics.assign`. Defaults
to ``None``, which means a zero initial guess.
ksp_options: A list of strings corresponding to command line options for
ksp_options: A list of dicts corresponding to command line options for
PETSc, used to solve the state systems. If this is ``None``, then the
direct solver mumps is used (default is ``None``).
adjoint_ksp_options: A list of strings corresponding to command line options
adjoint_ksp_options: A list of dicts corresponding to command line options
for PETSc, used to solve the adjoint systems. If this is ``None``, then
the same options as for the state systems are used (default is
``None``).
Expand Down Expand Up @@ -264,27 +262,25 @@ def _parse_cost_functional_form(
def _parse_optional_inputs(
self,
initial_guess: Optional[Union[List[fenics.Function], fenics.Function]],
ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
],
ksp_options: Optional[Union[_typing.KspOption, List[_typing.KspOption]]],
adjoint_ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
Union[_typing.KspOption, List[_typing.KspOption]]
],
desired_weights: Optional[Union[List[float], float]],
) -> Tuple[
Optional[List[fenics.Function]],
_typing.KspOptions,
_typing.KspOptions,
List[_typing.KspOption],
List[_typing.KspOption],
Optional[List[float]],
]:
"""Initializes the optional input parameters.

Args:
initial_guess: List of functions that act as initial guess for the state
variables, should be valid input for :py:func:`fenics.assign`.
ksp_options: A list of strings corresponding to command line options for
ksp_options: A list of dicts corresponding to command line options for
PETSc, used to solve the state systems.
adjoint_ksp_options: A list of strings corresponding to command line options
adjoint_ksp_options: A list of dicts corresponding to command line options
for PETSc, used to solve the adjoint systems.
desired_weights: A list of values for scaling the cost functional terms. If
this is supplied, the cost functional has to be given as list of
Expand All @@ -298,20 +294,18 @@ def _parse_optional_inputs(
parsed_initial_guess = _utils.enlist(initial_guess)

if ksp_options is None:
parsed_ksp_options: _typing.KspOptions = []
option: List[List[Union[str, int, float]]] = copy.deepcopy(
_utils.linalg.direct_ksp_options
)
parsed_ksp_options: List[_typing.KspOption] = []
option = copy.deepcopy(_utils.linalg.direct_ksp_options)

for _ in range(self.state_dim):
parsed_ksp_options.append(option)
else:
parsed_ksp_options = _utils.check_and_enlist_ksp_options(ksp_options)
parsed_ksp_options = _utils.enlist(ksp_options)

parsed_adjoint_ksp_options: _typing.KspOptions = (
parsed_adjoint_ksp_options: List[_typing.KspOption] = (
parsed_ksp_options[:]
if adjoint_ksp_options is None
else _utils.check_and_enlist_ksp_options(adjoint_ksp_options)
else _utils.enlist(adjoint_ksp_options)
)

if desired_weights is None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,9 @@ def __init__(
config: Optional[io.Config] = None,
shape_scalar_product: Optional[ufl.Form] = None,
initial_guess: Optional[List[fenics.Function]] = None,
ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
] = None,
ksp_options: Optional[Union[_typing.KspOption, List[_typing.KspOption]]] = None,
adjoint_ksp_options: Optional[
Union[_typing.KspOptions, List[List[Union[str, int, float]]]]
Union[_typing.KspOption, List[_typing.KspOption]]
] = None,
desired_weights: Optional[List[float]] = None,
temp_dict: Optional[Dict] = None,
Expand Down Expand Up @@ -124,10 +122,10 @@ def __init__(
initial_guess: List of functions that act as initial guess for the state
variables, should be valid input for :py:func:`fenics.assign`. Defaults
to ``None``, which means a zero initial guess.
ksp_options: A list of strings corresponding to command line options for
ksp_options: A list of dicts corresponding to command line options for
PETSc, used to solve the state systems. If this is ``None``, then the
direct solver mumps is used (default is ``None``).
adjoint_ksp_options: A list of strings corresponding to command line options
adjoint_ksp_options: A list of dicts corresponding to command line options
for PETSc, used to solve the adjoint systems. If this is ``None``, then
the same options as for the state systems are used (default is
``None``).
Expand Down
24 changes: 12 additions & 12 deletions cashocs/_pde_problems/control_gradient_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from __future__ import annotations

import copy
from typing import List, TYPE_CHECKING, Union
from typing import List, TYPE_CHECKING

import fenics

Expand All @@ -33,6 +33,7 @@
from cashocs._pde_problems import pde_problem

if TYPE_CHECKING:
from cashocs import _typing
from cashocs._database import database
from cashocs._pde_problems import adjoint_problem as ap
from cashocs._pde_problems import state_problem as sp
Expand Down Expand Up @@ -71,19 +72,18 @@ def __init__(

gradient_method: str = self.config.get("OptimizationRoutine", "gradient_method")

option: List[List[Union[str, int, float]]] = []
if gradient_method.casefold() == "direct":
option = copy.deepcopy(_utils.linalg.direct_ksp_options)
option: _typing.KspOption = copy.deepcopy(_utils.linalg.direct_ksp_options)
elif gradient_method.casefold() == "iterative":
option = [
["ksp_type", "cg"],
["pc_type", "hypre"],
["pc_hypre_type", "boomeramg"],
["pc_hypre_boomeramg_strong_threshold", 0.7],
["ksp_rtol", gradient_tol],
["ksp_atol", 1e-50],
["ksp_max_it", 250],
]
option = {
"ksp_type": "cg",
"pc_type": "hypre",
"pc_hypre_type": "boomeramg",
"pc_hypre_boomeramg_strong_threshold": 0.7,
"ksp_rtol": gradient_tol,
"ksp_atol": 1e-50,
"ksp_max_it": 250,
}

self.riesz_ksp_options = []
for _ in range(len(self.db.function_db.gradient)):
Expand Down
22 changes: 11 additions & 11 deletions cashocs/_pde_problems/hessian_problems.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

from __future__ import annotations

from typing import List, TYPE_CHECKING, Union
from typing import List, TYPE_CHECKING

import fenics
import numpy as np
Expand Down Expand Up @@ -127,16 +127,16 @@ def __init__(

self.bcs_list_ad = self.adjoint_form_handler.bcs_list_ad

option: List[List[Union[str, int, float]]] = [
["ksp_type", "cg"],
["pc_type", "hypre"],
["pc_hypre_type", "boomeramg"],
["pc_hypre_boomeramg_strong_threshold", 0.7],
["ksp_rtol", 1e-16],
["ksp_atol", 1e-50],
["ksp_max_it", 100],
]
self.riesz_ksp_options: _typing.KspOptions = []
option: _typing.KspOption = {
"ksp_type": "cg",
"pc_type": "hypre",
"pc_hypre_type": "boomeramg",
"pc_hypre_boomeramg_strong_threshold": 0.7,
"ksp_rtol": 1e-16,
"ksp_atol": 1e-50,
"ksp_max_it": 100,
}
self.riesz_ksp_options: List[_typing.KspOption] = []
for _ in range(len(self.db.function_db.controls)):
self.riesz_ksp_options.append(option)

Expand Down
Loading