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()
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
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
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]
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()