Beispiel #1
0
    def _compute_residual(self, finalize=False):
        LOG.debug("Computing Residual")
        self._print_step(1, None, self.state.current_level.initial.time_point,
                         supremum_norm(self.state.current_level.initial.value),
                         None, None)

        _full_integral = 0.0

        self._recompute_rhs_for_level(self.state.current_level)

        for _step_index in range(0, len(self.state.current_level)):
            _step = self.state.current_level[_step_index]

            if not _step.integral_available:
                _step.integral = \
                    self.ml_provider \
                        .integrator(self.state.current_level_index) \
                        .evaluate(self.state.current_level.rhs, from_node=_step_index, target_node=_step_index + 1)
            _full_integral += _step.integral

            self._core.compute_residual(self.state, step=_step, integral=_full_integral)

            if finalize:
                # finalize this step (i.e. StepSolutionData.finalize())
                _step.done()

        for _step_index in range(0, len(self.state.current_level)):
            _step = self.state.current_level[_step_index]
            if _step_index > 0:
                _previous_time = self.state.current_level[_step_index - 1].time_point
            else:
                _previous_time = self.state.current_level.initial.time_point

            _fas = _step.fas_correction if not self.state.current_iteration.on_finest_level else None
            _cc = _step.coarse_correction if not self.state.current_iteration.on_finest_level else None

            if problem_has_exact_solution(self.problem, self):
                self._print_step(_step_index + 2,
                                 _previous_time,
                                 _step.time_point,
                                 supremum_norm(_step.value),
                                 _step.solution.residual,
                                 _step.solution.error,
                                 _fas,
                                 _cc)
            else:
                self._print_step(_step_index + 2,
                                 _previous_time,
                                 _step.time_point,
                                 supremum_norm(_step.value),
                                 _step.solution.residual,
                                 None,
                                 _fas,
                                 _cc)

        self._print_sweep_end()

        if finalize:
            LOG.debug("Finalizing Level %d" % self.state.current_iteration.current_level_index)
            self.state.current_iteration.current_level.finalize()
Beispiel #2
0
    def _main_solver_loop(self):
        # initialize iteration timer of same type as global timer
        _iter_timer = self.timer.__class__()

        # initialize solver states for this iteration
        self._init_new_iteration()

        self._print_iteration(self.state.current_iteration_index + 1)

        # iterate on time steps
        _iter_timer.start()
        self._level()
        _iter_timer.stop()

        # check termination criteria
        self.threshold.check(self.state)

        # log this iteration's summary
        if self.state.is_first_iteration:
            # on first iteration we do not have comparison values
            self._print_iteration_end(None, None, None, _iter_timer.past())
        else:
            if problem_has_exact_solution(self.problem, self) and not self.state.is_first_iteration:
                # we could compute the correct error of our current solution
                self._print_iteration_end(self.state.solution.solution_reduction(self.state.current_iteration_index),
                                          self.state.solution.error_reduction(self.state.current_iteration_index),
                                          self.state.current_step.solution.residual,
                                          _iter_timer.past())
            else:
                self._print_iteration_end(self.state.solution.solution_reduction(self.state.current_iteration_index),
                                          None,
                                          self.state.current_step.solution.residual,
                                          _iter_timer.past())

        # finalize this iteration (i.e. TrajectorySolutionData.finalize())
        self.state.current_iteration.finalize()

        _reason = self.threshold.has_reached()
        if _reason is None:
            # LOG.debug("solver main loop done: no reason")
            return Message.SolverFlag.iterating
        elif _reason == ['iterations']:
            # LOG.debug("solver main loop done: iterations")
            _dim = list(self.problem.spacial_dim)
            _dim.insert(0, self.ml_provider.integrator(self.state.last.current_level_index).num_nodes)
            LOG.debug("-->\n%s" % (self.state.last.current_level.values.reshape(tuple(_dim)).tolist()))
            self.state.finalize()
            return Message.SolverFlag.finished
        else:
            # LOG.debug("solver main loop done: other")
            _dim = list(self.problem.spacial_dim)
            _dim.insert(0, self.ml_provider.integrator(self.state.last.current_level_index).num_nodes)
            LOG.debug("-->\n%s" % (self.state.last.current_level.values.reshape(tuple(_dim)).tolist()))
            self.state.finalize()
            return Message.SolverFlag.converged
Beispiel #3
0
    def _main_solver_loop(self):
        # initialize iteration timer of same type as global timer
        _iter_timer = self.timer.__class__()

        self._print_iteration(self.state.current_iteration_index + 1)

        # iterate on time steps
        _iter_timer.start()
        for _current_time_step in self.state.current_iteration:
            # run this time step
            self._time_step()
            if self.state.current_time_step_index < len(self.state.current_iteration) - 1:
                self.state.current_iteration.proceed()
        _iter_timer.stop()

        # check termination criteria
        self.threshold.check(self.state)

        # log this iteration's summary
        if self.state.is_first_iteration:
            # on first iteration we do not have comparison values
            self._print_iteration_end(None, None, None, _iter_timer.past())
        else:
            if problem_has_exact_solution(self.problem, self) and not self.state.is_first_iteration:
                # we could compute the correct error of our current solution
                self._print_iteration_end(
                    self.state.solution.solution_reduction(self.state.current_iteration_index),
                    self.state.solution.error_reduction(self.state.current_iteration_index),
                    self.state.current_step.solution.residual,
                    _iter_timer.past(),
                )
            else:
                self._print_iteration_end(
                    self.state.solution.solution_reduction(self.state.current_iteration_index),
                    None,
                    self.state.current_step.solution.residual,
                    _iter_timer.past(),
                )

        # finalize this iteration (i.e. TrajectorySolutionData.finalize())
        self.state.current_iteration.finalize()

        _reason = self.threshold.has_reached()
        if _reason is None:
            # LOG.debug("solver main loop done: no reason")
            return Message.SolverFlag.iterating
        elif _reason == ["iterations"]:
            # LOG.debug("solver main loop done: iterations")
            self.state.finalize()
            return Message.SolverFlag.finished
        else:
            # LOG.debug("solver main loop done: other")
            self.state.finalize()
            return Message.SolverFlag.converged
Beispiel #4
0
    def run(self, core, **kwargs):
        """Applies SDC solver to the initialized problem setup.

        Solves the given problem with the explicit SDC algorithm.

        Parameters
        ----------
        core : :py:class:`.SdcSolverCore`
            core solver stepping method
        dt : :py:class:`float`
            width of the interval to work on; this is devided into the number of given
            time steps this solver has been initialized with

        See Also
        --------
        :py:meth:`.IIterativeTimeSolver.run` : overridden method
        """
        super(MlSdc, self).run(core, **kwargs)

        assert_named_argument('dt', kwargs, types=float, descriptor="Width of Interval", checking_obj=self)
        self._dt = kwargs['dt']

        self._print_header()

        # start iterations
        # TODO: exact solution storage handling
        self.__exact[0] = self.problem.initial_value

        _has_work = True
        _previous_flag = Message.SolverFlag.none
        _current_flag = Message.SolverFlag.none
        __work_loop_count = 1

        while _has_work:
            # LOG.debug("Work Loop: %d" % __work_loop_count)
            _previous_flag = _current_flag
            _current_flag = Message.SolverFlag.none

            # receive dedicated message
            _msg = self._communicator.receive(tag=(self.ml_provider.num_levels - 1))

            if _msg.flag == Message.SolverFlag.failed:
                # previous solver failed
                # --> pass on the failure and abort
                _current_flag = Message.SolverFlag.failed
                _has_work = False
                # LOG.debug("Previous Solver Failed")
            else:
                if _msg.flag == Message.SolverFlag.time_adjusted:
                    # the previous solver has adjusted its interval
                    # --> we need to recompute our interval
                    _current_flag = self._adjust_interval_width()
                    # we don't immediately start the computation of the newly computed interval
                    # but try to pass the new interval end to the next solver as soon as possible
                    # (this should avoid throwing away useless computation)
                    # LOG.debug("Previous Solver Adjusted Time")
                else:
                    if _previous_flag in \
                            [Message.SolverFlag.none, Message.SolverFlag.converged, Message.SolverFlag.finished,
                             Message.SolverFlag.time_adjusted]:
                        # we just started or finished our previous interval
                        # --> start a new interval
                        _has_work = self._init_new_interval(_msg.time_point)

                        if _has_work:
                            # set initial values
                            self.state.initial.value = _msg.value.copy()
                            self.state.initial.solution.time_point = _msg.time_point
                            self.state.initial.done()

                            # LOG.debug("New Interval Initialized")

                            # start logging output
                            self._print_interval_header()

                            # start global timing (per interval)
                            self.timer.start()
                        else:
                            # LOG.debug("No New Interval Available")
                            pass
                    elif _previous_flag == Message.SolverFlag.iterating:
                        # LOG.debug("Next Iteration")
                        pass
                    else:
                        # LOG.warn("WARNING!!! Something went wrong here")
                        pass

                    if _has_work:
                        # we are still on the same interval or have just successfully initialized a new interval
                        # --> do the real computation
                        # LOG.debug("Starting New Solver Main Loop")

                        # initialize a new iteration state
                        self.state.proceed()

                        if _msg.time_point == self.state.initial.time_point:
                            if _previous_flag == Message.SolverFlag.iterating:
                                # LOG.debug("Updating initial value")
                                # if the previous solver has a new initial value for us, we use it
                                self.state.current_iteration.initial.value = _msg.value.copy()

                        _current_flag = self._main_solver_loop()

                        if _current_flag in \
                                [Message.SolverFlag.converged, Message.SolverFlag.finished, Message.SolverFlag.failed]:
                            _log_msgs = {'': OrderedDict()}
                            if self.state.last_iteration_index <= self.threshold.max_iterations:
                                _group = 'Converged after %d iteration(s)' % (self.state.last_iteration_index + 1)
                                _log_msgs[''][_group] = OrderedDict()
                                _log_msgs[''][_group] = self.threshold.has_reached(log=True)
                                _log_msgs[''][_group]['Final Residual'] = "{:.3e}"\
                                    .format(supremum_norm(self.state.last_iteration.final_step.solution.residual))
                                _log_msgs[''][_group]['Solution Reduction'] = "{:.3e}"\
                                    .format(supremum_norm(self.state.solution
                                                          .solution_reduction(self.state.last_iteration_index)))
                                if problem_has_exact_solution(self.problem, self):
                                    _log_msgs[''][_group]['Error Reduction'] = "{:.3e}"\
                                        .format(supremum_norm(self.state.solution
                                                              .error_reduction(self.state.last_iteration_index)))
                            else:
                                warnings.warn("{}: Did not converged: {:s}".format(self._core.name, self.problem))
                                _group = "FAILED: After maximum of {:d} iteration(s)"\
                                         .format(self.state.last_iteration_index + 1)
                                _log_msgs[''][_group] = OrderedDict()
                                _log_msgs[''][_group]['Final Residual'] = "{:.3e}"\
                                    .format(supremum_norm(self.state.last_iteration.final_step.solution.residual))
                                _log_msgs[''][_group]['Solution Reduction'] = "{:.3e}"\
                                    .format(supremum_norm(self.state.solution
                                                          .solution_reduction(self.state.last_iteration_index)))
                                if problem_has_exact_solution(self.problem, self):
                                    _log_msgs[''][_group]['Error Reduction'] = "{:.3e}"\
                                        .format(supremum_norm(self.state.solution
                                                              .error_reduction(self.state.last_iteration_index)))
                                LOG.warn("  {} Failed: Maximum number iterations reached without convergence."
                                         .format(self._core.name))
                            print_logging_message_tree(_log_msgs)
                    elif _previous_flag in [Message.SolverFlag.converged, Message.SolverFlag.finished]:
                        # LOG.debug("Solver Finished.")

                        self.timer.stop()

                        self._print_footer()
                    else:
                        # something went wrong
                        # --> we failed
                        # LOG.warn("Solver failed.")
                        _current_flag = Message.SolverFlag.failed

            self._communicator.send(value=self.state.current_iteration.finest_level.final_step.value,
                                    time_point=self.state.current_iteration.finest_level.final_step.time_point,
                                    flag=_current_flag)
            __work_loop_count += 1

        # end while:has_work is None
        # LOG.debug("Solver Main Loop Done")

        return [_s.solution for _s in self._states]
Beispiel #5
0
    def _time_step(self):
        self.state.current_time_step.delta_time_step = self._deltas["t"]
        for _step in range(0, len(self.state.current_time_step)):
            _node_index = self.state.current_time_step_index * (self.num_nodes - 1) + _step
            self.state.current_time_step[_step].delta_tau = self._deltas["n"][_node_index]
            self.state.current_time_step[_step].solution.time_point = self.__time_points["nodes"][
                self.state.current_time_step_index
            ][_step + 1]

        self._print_time_step(
            self.state.current_time_step_index + 1,
            self.state.current_time_step.initial.time_point,
            self.state.current_time_step.last.time_point,
            self.state.current_time_step.delta_time_step,
        )

        # for classic SDC compute integral
        _integral = 0.0
        _integrate_values = None
        if self.classic:
            if not self.state.current_time_step.initial.rhs_evaluated:
                self.state.current_time_step.initial.rhs = self.problem.evaluate_wrt_time(
                    self.state.current_time_step.initial.time_point, self.state.current_time_step.initial.value
                )

            _integrate_values = np.array([self.state.current_time_step.initial.rhs], dtype=self.problem.numeric_type)
            for _step_index in range(0, len(self.state.current_time_step)):
                if self.state.is_first_iteration:
                    _integrate_values = np.append(
                        _integrate_values,
                        np.array([self.state.current_time_step.initial.rhs], dtype=self.problem.numeric_type),
                        axis=0,
                    )
                else:
                    _step = self.state.previous_iteration[self.state.current_time_step_index][_step_index]
                    if not _step.rhs_evaluated:
                        _step.rhs = self.problem.evaluate_wrt_time(_step.time_point, _step.value)
                    _integrate_values = np.append(
                        _integrate_values, np.array([_step.rhs], dtype=self.problem.numeric_type), axis=0
                    )

            assert_condition(
                _integrate_values.shape[0] == self.num_nodes,
                ValueError,
                message="Number of integration values not correct: {:d} != {:d}".format(
                    _integrate_values.shape[0], self.num_nodes
                ),
                checking_obj=self,
            )

        _full_integral = 0.0

        # do the actual SDC steps of this SDC sweep
        for _step_index in range(0, len(self.state.current_time_step)):
            _current_step = self.state.current_time_step[_step_index]
            if self.classic:
                _integral = self._integrator.evaluate(
                    _integrate_values, from_node=_step_index, target_node=_step_index + 1
                )
                # we successively compute the full integral, which is used for the residual at the end
                _full_integral += _integral
            _current_step.integral = _integral.copy()
            # do the SDC step of this sweep
            self._sdc_step()
            if self.state.current_step_index < len(self.state.current_time_step) - 1:
                self.state.current_time_step.proceed()

        del _integrate_values

        # compute residual and print step details
        for _step_index in range(0, len(self.state.current_time_step)):
            _step = self.state.current_time_step[_step_index]

            self._core.compute_residual(self.state, step=_step, integral=_full_integral)

            # finalize this step (i.e. StepSolutionData.finalize())
            _step.done()

            if _step_index > 0:
                _previous_time = self.state.current_time_step[_step_index - 1].time_point
            else:
                _previous_time = self.state.current_time_step.initial.time_point

            if problem_has_exact_solution(self.problem, self):
                self._print_step(
                    _step_index + 2,
                    _previous_time,
                    _step.time_point,
                    supremum_norm(_step.value),
                    _step.solution.residual,
                    _step.solution.error,
                )
            else:
                self._print_step(
                    _step_index + 2,
                    _previous_time,
                    _step.time_point,
                    supremum_norm(_step.value),
                    _step.solution.residual,
                    None,
                )

        self._print_time_step_end()

        # finalizing the current time step (i.e. TrajectorySolutionData.finalize)
        self.state.current_time_step.finalize()