def residual(self, iteration): """Accessor for the residuals of a specific iteration. Parameters ---------- iteration : :py:class:`int` 0-based index of the iteration. ``-1`` means last iteration. Returns ------- residual : instance of :py:attr:`.Residual` or :py:class:`None` if no solutions are stored. Raises ------ ValueError : If given ``iteration`` index is not in the valid range. """ if len(self._data) > 0: assert_condition(iteration in range(-1, len(self._data)), ValueError, message="Iteration index not within valid range: {:d} not in [-1, {:d}" .format(iteration, len(self._data)), checking_obj=self) if self._data_type == StepSolutionData: return np.array(self._data[iteration].residual, dtype=np.object) else: return self._data[iteration].residuals else: return None
def value(self, value): assert_condition(not self.finalized, AttributeError, message="Cannot change this solution data storage any more.", checking_obj=self) assert_is_instance(value, np.ndarray, descriptor="Values", checking_obj=self) self._dim = value.shape self._numeric_type = value.dtype self._data = value
def write_buffer(self, tag=None, **kwargs): """Writes data into this communicator's buffer Parameters ---------- value : data values to be send to the next solver time_point : :py:class:`float` time point of the data values flag : :py:class:`.Message.SolverFlag` message flag Raises ------ ValueError * if no arguments are given * if ``time_point`` is not a :py:class:`float` """ assert_condition(len(kwargs) > 0, ValueError, "At least one argument must be given.", self) if tag not in self._buffer: self._buffer[tag] = Message() self.write_buffer(tag=tag, **kwargs) if "value" in kwargs: self._buffer[tag].value = deepcopy(kwargs["value"]) if "time_point" in kwargs: assert_is_instance(kwargs["time_point"], float, descriptor="Time Point", checking_obj=self) self._buffer[tag].time_point = deepcopy(kwargs["time_point"]) if "flag" in kwargs: self._buffer[tag].flag = deepcopy(kwargs["flag"])
def evaluate(self, data, **kwargs): """Applies this integrator to given data in specified time interval. Parameters ---------- data : :py:class:`numpy.ndarray` Data vector of the values at given time points. Its length must equal the number of integration nodes. time_start : :py:class:`float` *(optional)* Begining of the time interval to integrate over. time_end : :py:class:`float` *(optional)* End of the time interval to integrate over. Raises ------ ValueError : * if ``data`` is not a :py:class:`numpy.ndarray` * if either ``time_start`` or ``time_end`` are not given * if ``time_start`` is larger or equals ``time_end`` """ assert_is_instance(data, np.ndarray, descriptor="Data to integrate", checking_obj=self) assert_condition("time_start" in kwargs or "time_end" in kwargs, ValueError, message="Either start or end of time interval need to be given.", checking_obj=self) assert_condition(kwargs["time_start"] < kwargs["time_end"], ValueError, message="Time interval need to be non-zero positive: [{:f}, {:f}]" .format(kwargs["time_start"], kwargs["time_end"]), checking_obj=self)
def _init_new_iteration(self): _current_state = self.state.current_iteration _previous_iteration = self.state.previous_iteration # set initial values for _level_index in range(0, self.ml_provider.num_levels): _current_state.add_finer_level(self.ml_provider.integrator(_level_index).num_nodes - 1) _level = _current_state.finest_level assert_condition(len(_level) == self.ml_provider.integrator(_level_index).num_nodes - 1, RuntimeError, "Number of Steps on Level %d not correct (%d)" % (len(_level), self.ml_provider.integrator(_level_index).num_nodes - 1), checking_obj=self) _level.initial = deepcopy(self.state.initial) if _previous_iteration is None: _level.broadcast(_level.initial.value) for _step_index in range(0, len(_level)): _level[_step_index].delta_tau = self.__deltas[_level_index][_step_index + 1] _level[_step_index].solution.time_point = self.__time_points[_level_index][_step_index + 1] if _previous_iteration is not None: _level[_step_index].value = _previous_iteration[_level_index][_step_index].value.copy() assert_condition(len(self.state.current_iteration) == self.ml_provider.num_levels, RuntimeError, "Number of levels in current state not correct." " (this shouldn't have happend)", checking_obj=self)
def finalize(self): assert_condition(not self.finalized, RuntimeError, message="This {} is already done.".format(class_name(self)), checking_obj=self) self._solution = self.finest_level.solution self._current_index = 0 self._finalized = True
def values(self, values): assert_condition(values.shape[0] == (len(self) + 1), ValueError, "Number of values does not match number of nodes: %d != %d" % (values.shape[0], (len(self) + 1)), checking_obj=self) for _step in range(0, len(self)): self[_step].value = values[_step + 1].copy()
def __init__(self, **kwargs): """ Parameters ---------- solution_class : :py:class:`.ISolution`, :py:class:`.StepSolutionData` or :py:class:`.TrajectorySolutionData` element_type : :py:class:`.IStepState` or :py:class:`.IStateItertor` num_states : :py:class:`int` *(optional)* Raises ------ ValueError if ``num_states`` is not a non-zero positive integer """ assert_named_argument('solution_class', kwargs, descriptor="Solution Type", checking_obj=self) assert_named_argument('element_type', kwargs, descriptor="Element Type", checking_obj=self) self._solution = kwargs['solution_class']() del kwargs['solution_class'] self._element_type = kwargs['element_type'] del kwargs['element_type'] self._states = [] self._current_index = 0 self._finalized = False if 'num_states' in kwargs: _num_states = kwargs['num_states'] assert_condition(isinstance(_num_states, int) and _num_states > 0, ValueError, message="Number of states must be a non-zero positive integer: NOT {}" .format(_num_states), checking_obj=self) self._states = [self._element_type(**kwargs) for i in range(0, _num_states)]
def construct_space_tensor(self, number_of_points_list, stencil=None): """Constructs the Spacetensor which is important for the evaluation in the case of Dirichlet boundary conditions Parameters ---------- number_of_points_list : :py:class:`int` or :py:class:`numpy.ndarray` Number of points which will be distributed equiv-spaced on the grid """ if isinstance(number_of_points_list, (int, float, complex)): assert_is_instance(stencil, Stencil, descriptor="Stencil", checking_obj=self) npoints = int(number_of_points_list) # LOG.debug("Your number %s was modified to %s" % (number_of_points_list, npoints)) assert_condition(npoints > max(stencil.arr.shape), ValueError, message="Not enough points for the stencil", checking_obj=self) npoints = np.asarray([npoints] * len(self.spacial_dim)) elif isinstance(number_of_points_list, np.ndarray): assert_condition(len(number_of_points_list.shape) == 1 and number_of_points_list.size == len(self.spacial_dim), ValueError, message="The number_of_points list is wrong", checking_obj=self) npoints = np.floor(number_of_points_list) else: raise ValueError("Wrong number of points list") # first we assign the memory using numpy # spt(npoints,dim) self._act_npoints = npoints lspc = [] for i in range(len(self.spacial_dim)): lspc.append(np.linspace(self._geometry[i, 0], self._geometry[i, 1], npoints[i])) if len(self.spacial_dim) > 1: space_tensor = np.asarray(np.meshgrid(*lspc)) else: space_tensor = np.linspace(self._geometry[0, 0], self._geometry[0, 1], npoints) return space_tensor
def _add_iteration(self): assert_condition(self.num_level > 0, ValueError, message="Number of number of levels and nodes per level must be larger 0: NOT {}" .format(self.num_level), checking_obj=self) self._states.append(self._element_type(num_level=self.num_level))
def fas_correction(self, fas_correction): assert_condition(fas_correction.shape[0] == (len(self) + 1), ValueError, "Number of FAS Corrections does not match number of nodes: %d != %d" % (fas_correction.shape[0], (len(self) + 1)), checking_obj=self) for _step in range(0, len(self)): self[_step].fas_correction = fas_correction[_step + 1] - fas_correction[_step]
def coarse_corrections(self, coarse_correction): assert_condition(coarse_correction.shape[0] == (len(self) + 1), ValueError, "Number of Coarse Corrections does not match number of nodes: %d != %d" % (coarse_correction.shape[0], (len(self) + 1)), checking_obj=self) for _step in range(0, len(self)): self[_step].coarse_correction = coarse_correction[_step + 1]
def _add_iteration(self): assert_condition(self.num_time_steps > 0 and self.num_nodes > 0, ValueError, message="Number of time steps and nodes per time step must be larger 0: NOT {}, {}" .format(self.num_time_steps, self.num_nodes), checking_obj=self) self._states.append(self._element_type(num_states=self.num_nodes, num_time_steps=self.num_time_steps))
def add_coefficient(self, coefficient, power): """Adds or sets the coefficient :math:`c` of :math:`cx^p` for a specific :math:`p`. The polynomial gets automatically extended to hold the new coefficient in case it didn't included the specified power previously. Unset, but skipped powers have a coefficient of zero by default. Parameters ---------- coefficient : :py:class:`float` Coefficient :math:`c` of :math:`cx^p`. power : :py:class:`int` Power :math:`p` of :math:`cx^p`. Examples -------- >>> polyWeights = PolynomialWeightFunction() >>> # To set the coefficient of x^3 to 3.14 use: >>> polyWeights.add_coefficient(3.14, 3) >>> # Similar, to set the constant coefficient 42, e.i. 42*x^0, use: >>> polyWeights.add_coefficient(42, 0) """ assert_is_instance(power, int, descriptor="Power", checking_obj=self) assert_condition(power >= 0, ValueError, message="Power must be zero or positive: {:d}".format(power), checking_obj=self) if self._coefficients.size <= power + 1: self._coefficients = np.resize(self._coefficients, (power + 1)) self._coefficients[power] = coefficient
def solution(self, iteration): """Accessor for the solution of a specific iteration. Parameters ---------- iteration : :py:class:`int` 0-based index of the iteration. ``-1`` means last iteration. Returns ------- solution : instance of :py:attr:`.data_storage_type` or :py:class:`None` if no solutions are stored. Raises ------ ValueError : If given ``iteration`` index is not in the valid range. """ if len(self._data) > 0: assert_condition(iteration in range(-1, len(self._data)), ValueError, message="Iteration index not within valid range: {:d} not in [-1, {:d}" .format(iteration, len(self._data)), checking_obj=self) return self._data[iteration] else: return None
def time_interval(self, value): assert_is_instance(value, np.ndarray, descriptor="Time Interval", checking_obj=self) assert_condition(value.size == 2, ValueError, message="Time Interval must have two values: NOT %d" % value.size) self.validate_time_interval(start=value[0], end=value[1]) self.time_start = value[0] self.time_end = value[1]
def link_solvers(self, *args, **kwargs): """Links the given communicators with this communicator Parameters ---------- previous : :py:class:`.ForwardSendingMessaging` communicator of the previous solver next : :py:class:`.ForwardSendingMessaging` communicator of the next solver Raises ------ ValueError if one of the two communicators of the specified type is not given """ super(ForwardSendingMessaging, self).link_solvers(*args, **kwargs) assert_condition(len(kwargs) == 2, ValueError, message="Exactly two communicators must be given: NOT %d" % len(kwargs), checking_obj=self) assert_named_argument('previous', kwargs, types=ForwardSendingMessaging, descriptor="Previous Communicator", checking_obj=self) self._previous = kwargs['previous'] assert_named_argument('next', kwargs, types=ForwardSendingMessaging, descriptor="Next Communicator", checking_obj=self) self._next = kwargs['next']
def __init__(self, fine_level, coarse_level, rst_stencil, ipl_stencil): assert_is_instance(fine_level, MultigridLevel1D, "Not an MultigridLevel1D") assert_is_instance(coarse_level, MultigridLevel1D, "Not an MultigridLevel1D") self.fl = fine_level self.cl = coarse_level assert_is_instance(ipl_stencil, InterpolationByStencilListIn1D) assert_is_instance(rst_stencil, RestrictionStencilPure) assert_condition(rst_stencil.ndim == 1, ValueError, "Restriction Stencil" + "has not the dimension 1") self.ipl = ipl_stencil self.rst = rst_stencil self.ipl_fine_views = [] self.ipl_coarse_views = [] # collect the views which are needed, if self.ipl.mode == "own": self.ipl_fine_views.append(self.fl.evaluable_view( self.ipl.stencil_list[0])) self.ipl_coarse_views(self.cl.mid) elif self.ipl.mode == "list": for stencil in self.ipl.stencil_list: self.ipl_fine_views.append(self.fl.evaluable_view(stencil)) self.ipl_coarse_views.append(self.cl.mid) else: raise NotImplementedError("What do you have in mind?") self.rst_fine_view = self.fl.evaluable_view(self.rst) self.rst_coarse_view = self.cl.mid
def __eq__(self, other): assert_condition(isinstance(other, self.__class__), TypeError, message="Can not compare {} with {}".format(self.__class__, class_name(other)), checking_obj=self) return ( self.numeric_type == other.numeric_type and np.array_equal(self.value, other.value) )
def used_iterations(self, used_iterations): assert_condition(not self.finalized, ValueError, message="Solution cannot be changed any more.", checking_obj=self) assert_condition(used_iterations > 0, ValueError, message="Number of used iterations must be non-zero positive: NOT {:d}" .format(used_iterations), checking_obj=self) self._used_iterations = used_iterations
def validate_time_interval(self, start=None, end=None): if start is None: start = self.time_start if end is None: end = self.time_end assert_condition(start < end, ValueError, message="Start Time must be smaller than End Time: NOT %s >= %s" % (start, end), checking_obj=self) return True
def add_solution_data(self, *args, **kwargs): """Appends solution of a new time point to the trajectory. Parameters ---------- step_data : :py:class:`.StepSolutionData` *(optional)* In case a single unnamed argument is given, this is required to be an instance of :py:class:`.StepSolutionData`. If no named argument is given, the following two parameters are *not* optional. values : :py:class:`numpy.ndarray` *(optional)* Solution values. Passed on to constructor of :py:class:`.StepSolutionData`. time_point : :py:class:`float` *(optional)* Time point of the solution. Passed on to constructor of :py:class:`.StepSolutionData`. Raises ------ ValueError * if construction of :py:class:`.StepSolutionData` fails * if internal consistency check fails (see :py:meth:`._check_consistency`) """ assert_condition( not self.finalized, AttributeError, message="Cannot change this solution data storage any more.", checking_obj=self, ) _old_data = self._data # backup for potential rollback if len(args) == 1 and isinstance(args[0], StepSolutionData): assert_condition( args[0].time_point is not None, ValueError, message="Time point must not be None.", checking_obj=self ) self._data = np.append(self._data, np.array([args[0]], dtype=np.object)) else: self._data = np.append(self._data, np.array([StepSolutionData(*args, **kwargs)], dtype=np.object)) try: self._check_consistency() except ValueError as err: # consistency check failed, thus removing recently added solution data storage warnings.warn("Consistency Check failed with:\n\t\t{}\n\tNot adding this solution.".format(*err.args)) self._data = _old_data.copy() # rollback raise err finally: # everything ok pass if self._data.size == 1: self._dim = self._data[-1].dim self._numeric_type = self._data[-1].numeric_type
def initial_value(self, initial_value): assert_is_instance(initial_value, np.ndarray, descriptor="Initial Value", checking_obj=self) assert_condition( initial_value.shape == self.dim_for_time_solver, ValueError, message="Initial Values shape must match problem DOFs: %s != %s" % (initial_value.shape, self.dim_for_time_solver), checking_obj=self, ) self._initial_value = initial_value
def __contains__(self, item): assert_condition( isinstance(item, StepSolutionData), TypeError, message="Item must be a StepSolutionData: NOT {}".format(class_name(item)), checking_obj=self, ) for elem in self._data: if elem == item: return True return False
def finalize(self): """Locks this storage data instance. Raises ------ ValueError : If it has already been locked. """ assert_condition(not self.finalized, AttributeError, message="This solution data storage is already finalized.", checking_obj=self) self._finalized = True
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))
def finalize(self): """Finalizes the whole solver state. This copies the :py:class:`.TrajectorySolutionData` objects from the :py:class:`.IIterationState` instances of this sequence to the main :py:class:`.IterativeSolution` object and finalizes it. """ assert_condition(not self.finalized, RuntimeError, message="This {} is already done.".format(class_name(self)), checking_obj=self) for _iter in self: self.solution.add_solution(_iter.solution) # self.solution.finalize() self._current_index = 0
def embed(self, ue): """ Summary _______ checks if u fits then embeds it Parameters ---------- ue : ndarray numpy array to embed """ assert_condition(ue.size == self._mid_points, ValueError, "Array to embed has the wrong size") self[self.borders[0]:-self.borders[1]] = ue
def embed(self, ue): """ Summary _______ checks if u fits then embeds it Parameters ---------- ue : ndarray numpy array to embed """ assert_condition(ue.shape == self.mid.shape, ValueError, "Array to embed has the wrong size") self.mid = ue
def _check_consistency(self): """Check consistency of stored solution data objects. Raises ------ ValueError : If the time points of at least two solution data storage objects differ. """ if len(self._data) > 0: _time_points = self._data[0].time_points for iteration in range(1, len(self._data)): assert_condition(np.array_equal(_time_points, self._data[iteration].time_points), ValueError, message="Time points of one or more stored solution data objects do not match.", checking_obj=self)