Exemple #1
0
def assert_is_key(key, dictionary, message=None, key_desc=None, dict_desc=None, checking_obj=None):
    """Asserts dictionary has a certain key

    Parameters
    ----------
    key : ``key``
        key to check
    dictionary : :py:class:`dict`
        dictionary to check
    message : :py:class:`str`
        *(optional)*
        message content of exception raised
    checking_obj : :py:class:`object` or :py:class:`None`
        *(optional)*
        The exception will be raised in the scope of the given object.
        If :py:class:`None` (default) no scope will be displayed.

    Raises
    ------
    ValueError
        if ``key`` is not of a key in ``dictionary``
    """
    if key not in dictionary:
        if not message:
            if not key_desc:
                key_desc = "'{:s}'".format(key)
            if not dict_desc:
                dict_desc = "given dict"
            message = "{:s} is not a key in {:s}.".format(key_desc, dict_desc)
        LOG.critical(func_name(checking_obj) + message)
        LOG.debug(func_name(checking_obj) + "Keys in {:s}: {:s}".format(id(dictionary), ', '.join(dictionary.keys())))
        raise ValueError("{:s}.{:s}(): {:s}".format(checking_obj_name(checking_obj), inspect.stack()[2][3], message))
Exemple #2
0
def assert_is_callable(obj, message=None, descriptor=None, checking_obj=None):
    """Asserts callability of given object

    Parameters
    ----------
    obj : :py:class:`object`
        object to be asserted callable
    message : :py:class:`str` or :py:class:`None`
        *(optional)*
    checking_obj : :py:class:`object` or :py:class:`None`
        *(optional)*
        The exception will be raised in the scope of the given object.
        If :py:class:`None` (default) no scope will be displayed.

    Raises
    ------
    ValueError
        if ``obj`` is not :py:class:`Callable`
    """
    if not isinstance(obj, Callable):
        if not message:
            if descriptor:
                message = "{:s} must be callable.".format(descriptor)
            else:
                message = "Required a callable: NOT {:s}.".format(class_name(obj))
        LOG.critical(func_name(checking_obj) + message)
        raise ValueError("{:s}.{:s}(): {:s}".format(checking_obj_name(checking_obj), inspect.stack()[2][3], message))
Exemple #3
0
 def definalize(self):
     if self._finalized:
         self._solution = self.solution.__class__()
         self._finalized = False
         self.reset_to_start()
     else:
         LOG.debug("This {} wasn't finalized.".format(class_name(self)))
Exemple #4
0
 def __init__(self, *args, **kwargs):
     if "file_name" in kwargs and isinstance(kwargs["file_name"], str) and len(kwargs["file_name"]) > 0:
         self._file_name = kwargs["file_name"]
         LOG.debug("Non-interactive plotting. Saving to '{:s}'".format(self._file_name))
         plt.ioff()
     else:
         self._file_name = None
         LOG.debug("Interactive plotting.")
         plt.ion()
Exemple #5
0
    def __init__(self, *args, **kwargs):
        super(self.__class__, self).__init__(*args, **kwargs)
        assert_condition(kwargs['num_fine_points'] % 2 != 0, ValueError,
                         message="Number of fine level points needs to be odd: %d" % kwargs['num_fine_points'],
                         checking_obj=self)

        self._n_coarse_points = int((self.num_fine_points + 1) / 2)
        self.restringation_operator = np.zeros([self.num_coarse_points, self.num_fine_points])
        self.prolongation_operator = np.zeros([self.num_fine_points, self.num_coarse_points])
        self._construct_transform_matrices()
        LOG.debug("Restringation operator: {}".format(self.restringation_operator))
        LOG.debug("Prolongation operator: {}".format(self.prolongation_operator))
Exemple #6
0
def assert_named_argument(name, kwargs, types=None, message=None, descriptor=None, checking_obj=None):
    if name not in kwargs:
        if not message:
            if descriptor:
                message = "%s ('%s') is a required argument." % (descriptor, name)
            else:
                message = "'%s' is a required argument." % name
        LOG.critical(func_name(checking_obj) + message)
        LOG.debug(func_name(checking_obj) + "Named arguments were: %s" % ', '.join(kwargs.keys()))
        raise ValueError("{:s}.{:s}(): {:s}".format(checking_obj_name(checking_obj), inspect.stack()[2][3], message))

    if types:
        assert_is_instance(kwargs[name], types, descriptor=descriptor, checking_obj=checking_obj)
 def _plot_residuals_reductions(self):
     plt.hold(True)
     for _state in range(0, self._states.size):
         self._add_solution_plot(_state)
     LOG.debug("Plotting within {:s} x {:s}".format(self.__residual_limits, self.__reduction_limits))
     _limits = [0.0, 0.0]
     _limits[0] = min(self.__residual_limits[0], self.__reduction_limits[0])
     _limits[1] = max(self.__residual_limits[0], self.__reduction_limits[1])
     plt.xlabel("residual")
     plt.xlim(_limits)
     plt.ylabel("reduction")
     plt.ylim(_limits)
     #plt.legend(loc=4)
     plt.grid(True)
    def run(self, state, **kwargs):
        """Explicit Euler step method.

        .. math::

            u_{m+1}^{k+1} = u_m^{k+1} + \\Delta_\\tau \\left( F(t_m, u_m^{k+1}) - F(t_m, u_m^k) \\right)
                                      + \\Delta_t I_m^{m+1} \\left( F(\\vec{u}^k) \\right)

        Parameters
        ----------
        solver_state : :py:class:`.MlSdcSolverState`
        """
        super(ExplicitMlSdcCore, self).run(state, **kwargs)

        assert_is_instance(state, MlSdcSolverState, descriptor="State", checking_obj=self)
        assert_named_argument('problem', kwargs, types=IProblem, descriptor="Problem", checking_obj=self)

        _problem = kwargs['problem']

        _previous_step = state.previous_step

        if not state.current_iteration.on_finest_level:
            LOG.debug("taking restringated or coarse-corrected value")
            if state.current_step != state.current_level.first:
                _previous_iteration_previous_step = state.current_iteration.current_level.previous_step.initial
            else:
                _previous_iteration_previous_step = state.current_iteration.current_level.initial
        else:
            _previous_iteration_previous_step = self._previous_iteration_previous_step(state)

        if not _previous_step.rhs_evaluated:
            _previous_step.rhs = _problem.evaluate_wrt_time(state.current_step.time_point, _previous_step.value)
        if not _previous_iteration_previous_step.rhs_evaluated:
            _previous_iteration_previous_step.rhs = \
                _problem.evaluate_wrt_time(state.current_step.time_point, _previous_iteration_previous_step.value)

        _fas = np.zeros(_previous_step.rhs.shape, dtype=_previous_step.rhs.dtype)
        if _previous_step.has_fas_correction():
            # LOG.debug("   previous step has FAS")
            _fas = _previous_step.fas_correction

        # Note: \Delta_t is always 1.0 as it's part of the integral
        # using step-wise formula
        # Formula:
        #   u_{m+1}^{k+1} = u_m^{k+1} + \Delta_\tau [ F(u_m^{k+1}) - F(u_m^k) ] + \Delta_t I_m^{m+1}(F(u^k))
        state.current_step.value = \
            (_previous_step.value
             + state.current_step.delta_tau * (_previous_step.rhs - _previous_iteration_previous_step.rhs)
             + state.current_step.integral + _fas)
Exemple #9
0
    def implicit_solve(self, next_x, func, method="hybr", **kwargs):
        """A solver for implicit equations.

        Finds the implicitly defined :math:`x_{i+1}` for the given right hand side function :math:`f(x_{i+1})`, such
        that :math:`x_{i+1}=f(x_{i+1})`.


        Parameters
        ----------
        next_x : :py:class:`numpy.ndarray`
            A starting guess for the implicitly defined value.
        rhs_call : :py:class:`callable`
            The right hand side function depending on the implicitly defined new value.
        method : :py:class:`str`
            *(optional, default=``hybr``)*
            Method fo the root finding algorithm. See `scipy.optimize.root
            <http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.root.html#scipy.optimize.root>` for
            details.

        Returns
        -------
        next_x : :py:class:`numpy.ndarray`
            The calculated new value.

        Raises
        ------
        ValueError :

            * if ``next_x`` is not a :py:class:`numpy.ndarray` of shape :py:attr:`.IProblem.dim`
            * if ``fun`` is not :py:class:`callable`
            * if computed solution is not a `:py:class:`numpy.ndarray`

        UserWarning :
            If the implicit solver did not converged, i.e. the solution object's ``success`` is not :py:class:`True`.
        """
        assert_is_instance(next_x, np.ndarray, descriptor="Initial Guess", checking_obj=self)
        assert_is_callable(func, descriptor="Function of RHS for Implicit Solver", checking_obj=self)
        sol = find_root(fun=func, x0=next_x.reshape(-1), method=method)
        if not sol.success:
            warnings.warn("Implicit solver did not converged.")
            LOG.debug("sol.x: %s" % sol.x)
            LOG.error("Implicit solver failed: %s" % sol.message)
        else:
            assert_is_instance(sol.x, np.ndarray, descriptor="Solution", checking_obj=self)
        return sol.x.reshape(self.dim_for_time_solver)
Exemple #10
0
def assert_is_instance(obj, instances, message=None, descriptor=None, checking_obj=None):
    """Asserts element is of certain type

    Parameters
    ----------
    obj : :py:class:`object`
        object to check type
    instances : :py:class:`type` of ``classes`` or :py:class:`class`
        types to check
    message : :py:class:`str`
        *(optional)*
        message content of exception raised
    checking_obj : :py:class:`object` or :py:class:`None`
        *(optional)*
        The exception will be raised in the scope of the given object.
        If :py:class:`None` (default) no scope will be displayed.

    Raises
    ------
    ValueError
        if ``obj`` is not of type ``instances``
    """
    if not isinstance(obj, instances):
        if not message:
            _instances_str = set()
            if isinstance(instances, (tuple, set, frozenset)):
                for _i in instances:
                    _instances_str.add("'%s'" % _i.__name__)
            else:
                _instances_str.add("'%s'" % instances.__name__)

            if descriptor:
                if len(_instances_str) > 1:
                    message = "{:s} must be one of {:s}: NOT {:s}"\
                              .format(descriptor, ', '.join(_instances_str), class_name(obj))
                else:
                    message = "{:s} must be a {:s}: NOT {:s}"\
                              .format(descriptor, ', '.join(_instances_str), class_name(obj))
            else:
                if len(_instances_str) > 1:
                    message = "Required one of {:s}: NOT {:s}.".format(', '.join(_instances_str), class_name(obj))
                else:
                    message = "Required a {:s}: NOT {:s}.".format(', '.join(_instances_str), class_name(obj))
        LOG.critical(func_name(checking_obj) + message)
        raise ValueError("{:s}.{:s}(): {:s}".format(checking_obj_name(checking_obj), inspect.stack()[2][3], message))
Exemple #11
0
    def transform(self, interval):
        """Transforms computed integration nodes to fit a new given interval.

        Based on the old interval the computed integration nodes are transformed fitting the newly given interval using
        standard linear interval scaling.
        In case no interval was previously given, the standard interval of the used nodes method, e.g. :math:`[-1, 1]`
        for Gauss-Lobatto, is used.

        Parameters
        ----------
        interval : :py:class:`numpy.ndarray(size=2)`
            New interval to transform nodes onto.

        Raises
        ------
        ValueError
            If the standard interval is not suited for transformation, i.e. it is not a :py:class:`numpy.ndarray` of
            size 2 and not positive.

        Notes
        -----
        It may be this transformation is numerically inconvenient because of the loss of significance.
        """
        assert_is_instance(interval, np.ndarray, descriptor="Interval", checking_obj=self)
        assert_condition(interval.size == 2,
                         ValueError,
                         message="Intervals must be of size 2: {} ({:s})".format(interval, class_name(interval)),
                         checking_obj=self)
        assert_condition(interval[0] < interval[1],
                         ValueError,
                         message="Interval must be positive: {:.2f} > {:.2f}".format(interval[0], interval[1]),
                         checking_obj=self)
        _old_interval = self.interval
        self._interval = interval
        self._nodes = (self.nodes - _old_interval[0]) * (interval[1] - interval[0]) / \
                      (_old_interval[1] - _old_interval[0]) + interval[0]
        assert_condition(self._nodes[0] - self._interval[0] <= 1e-16 and self._nodes[-1] - self._interval[1] <= 1e-16,
                         RuntimeError,
                         message="Newly computed nodes do not match new interval: {} NOT IN {}"
                                 .format(self._nodes, self._interval),
                         checking_obj=self)
        LOG.debug("Nodes: %s" % self._nodes.tolist())
Exemple #12
0
def assert_is_in(element, test_list, message=None, elem_desc=None, list_desc=None, checking_obj=None):
    """Asserts element in list or sequence

    Parameters
    ----------
    element : :py:class:`object`
        element to check membership
    test_list : ``Sequence``
        sequence to check
    message : :py:class:`str`
        *(optional)*
        message content of exception raised
    checking_obj : :py:class:`object` or :py:class:`None`
        *(optional)*
        The exception will be raised in the scope of the given object.
        If :py:class:`None` (default) no scope will be displayed.

    Raises
    ------
    ValueError
        if ``element`` is not in ``test_list``

    Examples
    --------
    assert_is_in(True, bool_list, elem_desc='', list_desc='', checking_obj=self)

    """
    if element not in test_list:
        if not message:
            if not list_desc:
                list_desc = class_name(test_list)
            if not elem_desc:
                elem_desc = "Element {:r}".format(element)
            message = "{:s} is not in {:s}.".format(elem_desc, list_desc)
        LOG.critical(func_name(checking_obj) + message)
        LOG.debug(func_name(checking_obj) +
                  "Elements in {:s}: {:s}".format(class_name(test_list), ', '.join(test_list)))
        raise ValueError("{:s}.{:s}(): {:s}".format(checking_obj_name(checking_obj), inspect.stack()[2][3], message))
Exemple #13
0
    def compute_reduction(self, state):
        """Computes the reduction of the error and solution

        With respect to the supremum nomr of the given state's current iteration (see
        :py:attr:`.ISolverState.current_iteration` and :py:class:`.IIterationState`).
        In case no previous iteration is available, it immediatly returns.
        """
        if not state.previous_iteration:
            # there is no previous iteration to compare with
            LOG.debug("Skipping computation of reduction: No previous iteration available.")
            return

        if state.current_iteration.final_step.solution.error:
            # error is given; computing reduction of it
            _previous_error = supremum_norm(state.previous_iteration.final_step.solution.error)
            _current_error = supremum_norm(state.current_iteration.final_step.solution.error)
            state.solution.set_error_reduction(state.current_iteration_index,
                                               abs((_previous_error - _current_error) / _previous_error * 100))

        # computing reduction of solution
        _previous_solution = supremum_norm(state.previous_iteration.final_step.solution.value)
        _current_solution = supremum_norm(state.current_iteration.final_step.solution.value)
        state.solution.set_solution_reduction(state.current_iteration_index,
                                              abs((_previous_solution - _current_solution) / _previous_solution * 100))
Exemple #14
0
    def _check(self, operator, name, value):
        _value = supremum_norm(value) if isinstance(value, (IDiagnosisValue, np.ndarray)) else value

        if name in self._conditions and self._conditions[name] is not None:
            assert_condition(_value is not None,
                             ValueError, message="'{:s}' is a termination condition but not available to check."
                                                 .format(name[0].capitalize() + name[1:]),
                             checking_obj=self)

            if operator == "min":
                if _value <= self._conditions[name]:
                    LOG.debug("Minimum of {:s} reached: {:.2e} <= {:.2e}"
                              .format(name, _value, self._conditions[name]))
                    self._reason.append(name)
            elif operator == "max":
                if _value >= self._conditions[name]:
                    LOG.debug("Maximum of {:s} exceeded: {:d} >= {:d}"
                              .format(name, _value, self._conditions[name]))
                    self._reason.append(name)
            else:
                raise ValueError("Given operator '{:s}' is invalid.".format(operator))
        else:
            # $name is not a condition
            pass
Exemple #15
0
def assert_condition(condition, exception_type, message, checking_obj=None):
    """Asserts trueness of arbitrary condition

    Parameters
    ----------
    condition : :py:class:`bool` or ``boolean expression``
        expression to be asserted
    exception_type : :py:class:`Exception`
        type of exception to be raised if ``condition`` evaluates to :py:class:`False`
    message : :py:class:`str`
        message content of exception raised
    checking_obj : :py:class:`object` or :py:class:`None`
        The exception will be raised in the scope of the given object.
        If :py:class:`None` (default) no scope will be displayed.

    Raises
    ------
    exception_type
        if ``condition`` evaluates to :py:class:`False`
    """
    if not condition:
        LOG.critical(func_name(checking_obj) + message)
        raise exception_type("{:s}.{:s}(): {:s}"
                             .format(checking_obj_name(checking_obj), inspect.stack()[1][3], message))
Exemple #16
0
    def transform_interval(self, interval):
        """Transforms nodes onto new interval

        See Also
        --------
        :py:meth:`.IntegratorBase.transform_interval` : overridden method
        """
        if interval is not None:
            if interval[1] - interval[0] != self.nodes[-1] - self.nodes[0]:
                LOG.debug("Size of interval changed. Recalculating weights.")
                super(SdcIntegrator, self).transform_interval(interval)
                self._construct_s_matrix()
            else:
                super(SdcIntegrator, self).transform_interval(interval)
                LOG.debug("Size of interval did not change. Don't need to recompute S and Q matrices")
        else:
            LOG.debug("Cannot transform interval to None. Skipping.")
Exemple #17
0
# coding=utf-8
"""
.. moduleauthor:: Torbjörn Klatt <*****@*****.**>
.. moduleauthor:: Dieter Moser <*****@*****.**>
"""
from collections import OrderedDict

import numpy as np

dt = 0.001

from pypint.utilities.logging import LOG, print_logging_message_tree, VERBOSITY_LVL1, SEPARATOR_LVL1, SEPARATOR_LVL2

LOG.info("%sSetting Up Multigrid Space Solver" % VERBOSITY_LVL1)
from pypint.plugins.multigrid.stencil import Stencil
laplace_stencil = Stencil(np.array([1.0, -2.0, 1.0]), None, 2)
LOG.info("%s  Laplace Discretization Stencil: %s" % (VERBOSITY_LVL1, laplace_stencil.arr))

LOG.info(SEPARATOR_LVL2)

LOG.info("%sSetting Up 1D Heat Equation" % VERBOSITY_LVL1)

LOG.info("%s  Setting Up Geometry" % VERBOSITY_LVL1)
geo = np.asarray([[0, 1]])

LOG.info("%s  Setting Up Boundary Functions" % VERBOSITY_LVL1)
boundary_types = ['dirichlet'] * 2
def left_f(x):
    _s = np.zeros(x.shape)
    LOG.debug("Left Bnd Fnc: %s -> %s" % (x.reshape(-1), _s.reshape(-1)))
    return _s
    def __init__(self, *args, **kwargs):
        """
        Parameters
        ----------
        rhs_function_wrt_space : :py:class:`callable`
            function returning the space-dependent values for the right hand side as used by the space solver
        boundaries : :py:class:`None` or :py:class:`list` of :py:class:`str`
            *(optional)*
            defaults to ``periodic`` for each dimension
        boundary_functions : :py:class:`None` or :py:class:`list` of :py:class:`callable`
            *(optional)*
            functions defined on the boundaries of the geometry
        geometry : :py:class:`None` or :py:class:`numpy.ndarray`
            *(optional)*
            specifying the dimension and extend of the geometry
        """
        assert_is_instance(self, IProblem, message="This Mixin is only valid for IProblems.", checking_obj=self)

        assert_named_argument('rhs_function_wrt_space', kwargs, descriptor="RHS for space solver", checking_obj=self)
        assert_is_callable(kwargs['rhs_function_wrt_space'], descriptor="RHS for space solver", checking_obj=self)

        self._rhs_function_wrt_space = kwargs['rhs_function_wrt_space']

        # check if boundary conditions are specified
        if kwargs.get('boundaries') is None:
            self._boundaries = ['periodic'] * len(self.spacial_dim)
        elif isinstance(kwargs['boundaries'], str) \
                and kwargs['boundaries'] in MultigridProblemMixin.valid_boundary_conditions:
            self._boundaries = [kwargs['boundaries']] * len(self.spacial_dim)
        elif isinstance(kwargs['boundaries'], list):
            check = 0
            for bc in kwargs['boundaries']:
                if bc in MultigridProblemMixin.valid_boundary_conditions:
                    check += 1
            if check == len(self.spacial_dim) * 2:
                self._boundaries = kwargs['boundaries']
            else:
                LOG.warning('Boundary specifications are not valid, will use periodic boundaries for each dimension.')
                self._boundaries = ['periodic'] * len(self.spacial_dim)
        else:
            LOG.warning('Boundary specifications are not valid, will use periodic boundaries for each dimension')
            self._boundaries = ['periodic'] * len(self.spacial_dim)

        # assign according to the boundary conditions the right functions
        if kwargs.get('boundary_functions') is None:
            self._boundary_functions = [None] * len(self.spacial_dim)
        else:
            assert_is_instance(kwargs['boundary_functions'], list, descriptor="Boundary Functions", checking_obj=self)
            check = 0
            assert_condition(len(kwargs['boundary_functions']) == len(self.spacial_dim),
                             ValueError, message="Not enough boundary functions given.", checking_obj=self)

            for ftpls in kwargs['boundary_functions']:
                if ftpls is 'dirichlet':
                    assert_is_instance(ftpls, list, message="Dirichlet function list not available", checking_obj=self)
                    assert_condition(len(ftpls) == 2,
                                     ValueError, message="Wrong number of functions", checking_obj=self)
                    assert_is_callable(ftpls[0], "Not a function", self)
                    assert_is_callable(ftpls[1], "Not a function", self)
                check += 1
            self._boundary_functions = kwargs['boundary_functions']

        # construct or save the geometry
        if kwargs.get('geometry') is None:
            self._geometry = np.asarray([[0, 1]] * len(self.spacial_dim))
        else:
            assert_is_instance(kwargs['geometry'], np.ndarray, descriptor="Geometry", checking_obj=self)
            assert_condition(len(kwargs["geometry"].shape) == 2, ValueError,
                             message="Numpy array has the wrong dimensions", checking_obj=self)
            assert_condition(kwargs['geometry'].shape[0] == len(self.spacial_dim) and kwargs['geometry'].shape[1] == 2,
                             ValueError,
                             message="Numpy array has a wrong shape", checking_obj=self)
            self._geometry = kwargs['geometry']

        self._rhs_space_operators = {}

        self._implicit_solve_method = kwargs.get('implicit_solve_method', 'direct')
        self._mg_core = None

        # the Space tensor which is actually used
        self._act_space_tensor = None
        self._act_grid_distances = None
        # the points actually used
        self._act_npoints = None
    def plot(self, *args, **kwargs):
        """Plots the solution and optional also the error for each iteration.

        If ``file_name`` has been specified on initialization (see :py:meth:`.IPlotter.__init__`) the plot is stored
        there.
        Otherwise an interactive plotting session is started.

        Parameters
        ----------
        solvers : :py:class:`.IIterativeTimeSolver`
            solver instances used to calculate the solutions

        states : :py:class:`.ISolverState`
            states of the solvers

        Raises
        ------
        ValueError

            * if ``solvers`` is not given or is not a :py:class:`numpy.ndarray` of :py:class:`.IIterativeTimeSolver`
            * if ``states`` is not given or is not a :py:class:`numpy.ndarray` of :py:class:`.ISolverState`
            * if ``states`` has more than 7 states
            * if the size of ``states`` does not equal the size of ``solvers``
        """
        super(ReductionResidualPlotter, self).plot(args, **kwargs)

        assert_named_argument('solvers', kwargs, types=np.ndarray, descriptor="Solver", checking_obj=self)
        [assert_is_instance(_solver, IIterativeTimeSolver, descriptor="All Solvers", checking_obj=self)
         for _solver in kwargs['solvers']]
        self._solvers = kwargs['solvers']

        assert_named_argument('states', kwargs, types=np.ndarray, descriptor="States", checking_obj=self)
        assert_condition(kwargs['states'].size <= 7,
                         ValueError, "Can only handle up to 7 solutions: %d" % kwargs['states'].size,
                         self)
        [assert_is_instance(_state, ISolverState,
                            descriptor="All States", checking_obj=self) for _state in kwargs['states']]
        self._states = kwargs['states']

        assert_condition(self._solvers.size == self._states.size,
                         ValueError, message="Number of solvers must equal number of states: %d != %d"
                                             % (self._solvers.size, self._states.size),
                         checking_obj=self)

        self._nodes = self._states[0].first.time_points

        if self._solvers[0].problem.time_start != self._nodes[0]:
            self._nodes = np.concatenate(([self._solvers[0].problem.time_start], self._nodes))
        if self._solvers[0].problem.time_end != self._nodes[-1]:
            self._nodes = np.concatenate((self._nodes, [self._solvers[0].problem.time_end]))

        plt.title("Residuals and Reduction per Iteration for different Lambdas")
        self._plot_residuals_reductions()

        if self._file_name is not None:
            fig = plt.gcf()
            fig.set_dpi(300)
            fig.set_size_inches((15., 15.))
            LOG.debug("Plotting figure with size (w,h) {:s} inches and {:d} DPI."
                      .format(fig.get_size_inches(), fig.get_dpi()))
            fig.savefig(self._file_name)

        if is_interactive():
            plt.show(block=True)
        else:
            plt.close('all')
    def run(self, state, **kwargs):
        """Semi-Implicit Euler step method.

        .. math::

            u_{m+1}^{k+1} - \\Delta_\\tau F_I(t_{m+1}, u_{m+1}^{k+1}) =
                u_m^{k+1} &+ \\Delta_\\tau \\left( F_I(t_{m+1}, u_{m+1}^k)
                                                  - F_E(t_m, u_m^{k+1}) + F_E(t_m, u_m^k) \\right) \\\\
                          &+ \\Delta_t I_m^{m+1} \\left( F(\\vec{u}^k) \\right)

        Parameters
        ----------
        state : :py:class:`.MlSdcSolverState`

        Notes
        -----
        This step method requires the given problem to provide partial evaluation of the right-hand side.
        """
        super(SemiImplicitMlSdcCore, self).run(state, **kwargs)

        assert_is_instance(state, MlSdcSolverState, descriptor="State", checking_obj=self)
        assert_named_argument('problem', kwargs, types=IProblem, descriptor="Problem", checking_obj=self)
        _problem = kwargs['problem']

        use_intermediate = kwargs['use_intermediate'] if 'use_intermediate' in kwargs else False

        if use_intermediate:
            # LOG.debug("using intermediate")
            _previous_iteration_current_step = state.current_iteration.current_level.current_step.intermediate
        elif not state.current_iteration.on_finest_level:
            _previous_iteration_current_step = state.current_iteration.current_level.current_step
        else:
            _previous_iteration_current_step = self._previous_iteration_current_step(state)
        if not _previous_iteration_current_step.rhs_evaluated:
            _previous_iteration_current_step.rhs = \
                _problem.evaluate_wrt_time(_previous_iteration_current_step.time_point,
                                           _previous_iteration_current_step.value)

        if not state.current_iteration.on_finest_level:
            _previous_iteration_previous_step = state.current_iteration.current_level.previous_step
        else:
            _previous_iteration_previous_step = self._previous_iteration_previous_step(state)
        if not _previous_iteration_previous_step.rhs_evaluated:
            _previous_iteration_previous_step.rhs = \
                _problem.evaluate_wrt_time(_previous_iteration_previous_step.time_point,
                                           _previous_iteration_previous_step.value)

        _fas = np.zeros(_previous_iteration_current_step.rhs.shape,
                        dtype=_previous_iteration_current_step.rhs.dtype)
        if not use_intermediate and _previous_iteration_current_step.has_fas_correction():
            # LOG.debug("   previous iteration current step has FAS: %s"
            #           % _previous_iteration_current_step.fas_correction)
            _fas = _previous_iteration_current_step.fas_correction

        if problem_has_direct_implicit(_problem, self):
            _sol = _problem.direct_implicit(phis_of_time=[_previous_iteration_previous_step.value,
                                                          _previous_iteration_current_step.value,
                                                          state.previous_step.value],
                                            delta_node=state.current_step.delta_tau,
                                            delta_step=state.delta_interval,
                                            integral=state.current_step.integral,
                                            fas=_fas,
                                            core=self)

        else:
            # Note: \Delta_t is always 1.0 as it's part of the integral
            _Fe_u_cp = _problem.evaluate_wrt_time(state.previous_step.time_point,
                                               state.previous_step.value,
                                               partial="expl")
            _Fe_u_pp = _problem.evaluate_wrt_time(_previous_iteration_previous_step.time_point,
                                                 _previous_iteration_previous_step.value,
                                                 partial="expl")
            _Fe_u_pc = _problem.evaluate_wrt_time(state.current_step.time_point,
                                                 _previous_iteration_current_step.value,
                                                 partial="impl")
            _expl_term = \
                (state.previous_step.value
                 + state.current_step.delta_tau
                 * (_Fe_u_cp - _Fe_u_pp - _Fe_u_pc)
                 + state.current_step.integral + _fas).reshape(-1)
            # LOG.debug("EXPL TERM: %s = %s + %f * (%s - %s - %s) + %s + %s"
            #           % (_expl_term, state.previous_step.value, state.current_step.delta_tau, _Fe_u_cp, _Fe_u_pp,
            #              _Fe_u_pc, state.current_step.integral, _fas))
            _func = lambda x_next: \
                _expl_term \
                + state.current_step.delta_tau * _problem.evaluate_wrt_time(state.current_step.time_point,
                                                                            x_next.reshape(_problem.dim_for_time_solver),
                                                                            partial="impl").reshape(-1) \
                - x_next
            # LOG.debug("shape of value: %s" % (state.current_step.value.shape,))
            # LOG.debug("shape expl term: %s" % (_expl_term.shape,))
            # LOG.debug("shape impl func: %s" % (_func(state.current_step.value.reshape(-1)).shape,))
            _sol = \
                _problem.implicit_solve(
                    state.current_step.value.reshape(-1),
                    _func,
                    expl_term=_expl_term,
                    time_level=state.current_iteration.current_level_index,
                    delta_time=state.current_iteration.current_level.current_step.delta_tau
                ).reshape(state.current_step.value.shape)

        if type(state.current_step.value) == type(_sol):
            state.current_step.value = _sol
        else:
            LOG.debug("Solution Type %s but expected %s" % (type(_sol), type(state.current_step.value)))
            state.current_step.value = _sol[0]
Exemple #21
0
 def definalize(self):
     if self.finalized:
         self._finalized = False
     else:
         LOG.warning("This Solution is not finalized.")
Exemple #22
0
def right_f(x):
    _s = np.zeros(x.shape)
    LOG.debug("Right Bnd Fnc: %s -> %s" % (x.reshape(-1), _s.reshape(-1)))
    return _s
    def plot(self, *args, **kwargs):
        """Plots the solution and optional also the error for each iteration.

        Parameters
        ----------
        solver : :py:class:`.IIterativeTimeSolver`
            solver instance used to calculate the solution

        state : :py:class:`.ISolverState`
            state containing information to plot

        errplot : :py:class:`bool`
            *(optional)*
            if given and :py:class:`True` also plots the errors for each iteration found in the solution

        residualplot : :py:class:`bool`
            *(optional)*
            if given and :py:class:`True` also plots the residual for each iteration found in the solution

        Raises
        ------
        ValueError

            * if ``solver`` not given and not an :py:class:`.IIterativeTimeSolver`
            * if ``state`` not given and not an :py:class:`.ISolverState`
        """
        super(SingleSolutionPlotter, self).plot(args, **kwargs)

        assert_named_argument('solver', kwargs, types=IIterativeTimeSolver, descriptor="Solver", checking_obj=self)
        assert_named_argument('state', kwargs, types=ISolverState, descriptor="State must be given", checking_obj=self)

        self._solver = kwargs['solver']
        self._state = kwargs['state']
        self._nodes = self._state.first.time_points

        _subplots = 1
        _curr_subplot = 0
        if 'errorplot' in kwargs and kwargs['errorplot']:
            _subplots += 1
            self._errplot = True
        if 'residualplot' in kwargs and kwargs['residualplot']:
            _subplots += 1
            self._residualplot = True

        if self._solver.problem.time_start != self._nodes[0]:
            self._nodes = np.concatenate(([self._solver.problem.time_start], self._nodes))
        if self._solver.problem.time_end != self._nodes[-1]:
            self._nodes = np.concatenate((self._nodes, [self._solver.problem.time_end]))

        if self._errplot or self._residualplot:
            plt.suptitle(r"after {:d} iterations; overall reduction: {:.2e}"
                         .format(len(self._state),
                                 supremum_norm(self._state.solution
                                               .solution_reduction(self._state.last_iteration_index))))
            _curr_subplot += 1
            plt.subplot(_subplots, 1, _curr_subplot)

        self._final_solution()
        plt.title(self._solver.problem.__str__())

        if self._errplot:
            _curr_subplot += 1
            plt.subplot(3, 1, _curr_subplot)
            self._error_plot()

        if self._residualplot:
            _curr_subplot += 1
            plt.subplot(3, 1, _curr_subplot)
            self._residual_plot()

        if self._file_name is not None:
            fig = plt.gcf()
            fig.set_dpi(300)
            fig.set_size_inches((15., 15.))
            LOG.debug("Plotting figure with size (w,h) {:s} inches and {:d} DPI."
                      .format(fig.get_size_inches(), fig.get_dpi()))
            fig.savefig(self._file_name)

        if is_interactive():
            plt.show(block=True)
        else:
            plt.close('all')