def _TimeQuadrature(time_interval: tuple_of(Number), function_over_time: list_of(Number)): return TimeQuadrature_Numbers(time_interval, function_over_time)
def _jacobian_bcs_apply(self, bcs: (list_of(DirichletBC), ProductOutputDirichletBC)): for bc in self.bcs: bc.apply(self.jacobian_matrix)
class _FunctionsList(AbstractFunctionsList): def __init__(self, space, component): if component is None: self.space = space else: self.space = wrapping.get_function_subspace(space, component) self.mpi_comm = wrapping.get_mpi_comm(space) self._list = list() # of functions self._precomputed_slices = Cache() # from tuple to FunctionsList def enrich(self, functions, component=None, weights=None, copy=True): # Append to storage self._enrich(functions, component, weights, copy) # Reset precomputed slices self._precomputed_slices = Cache() # Prepare trivial precomputed slice self._precomputed_slices[0, len(self._list)] = self @overload(backend.Function.Type(), (None, str, dict_of(str, str)), (None, Number), bool) def _enrich(self, function, component, weight, copy): self._add_to_list(function, component, weight, copy) @overload((lambda cls: cls, list_of( backend.Function.Type()), tuple_of(backend.Function.Type())), (None, str, dict_of(str, str)), (None, list_of(Number)), bool) def _enrich(self, functions, component, weights, copy): if weights is not None: assert len(weights) == len(functions) for (index, function) in enumerate(functions): self._add_to_list(function, component, weights[index], copy) else: for function in functions: self._add_to_list(function, component, None, copy) @overload(TimeSeries, (None, str, dict_of(str, str)), (None, list_of(Number)), bool) def _enrich(self, functions, component, weights, copy): self._enrich(functions._list, component, weights, copy) @overload(object, (None, str, dict_of(str, str)), (None, Number, list_of(Number)), bool) def _enrich(self, function, component, weight, copy): if AdditionalIsFunction(function): function = ConvertAdditionalFunctionTypes(function) assert weight is None or isinstance(weight, Number) self._add_to_list(function, component, weight, copy) elif isinstance(function, list): converted_function = list() for function_i in function: if AdditionalIsFunction(function_i): converted_function.append( ConvertAdditionalFunctionTypes(function_i)) else: raise RuntimeError( "Invalid function provided to FunctionsList.enrich()" ) assert weight is None or isinstance(weight, list) self._enrich(converted_function, component, weight, copy) else: raise RuntimeError( "Invalid function provided to FunctionsList.enrich()") @overload(backend.Function.Type(), (None, str), (None, Number), bool) def _add_to_list(self, function, component, weight, copy): self._list.append( wrapping.function_extend_or_restrict(function, component, self.space, component, weight, copy)) @overload(backend.Function.Type(), dict_of(str, str), (None, Number), bool) def _add_to_list(self, function, component, weight, copy): assert len(component) == 1 for (component_from, component_to) in component.items(): break self._list.append( wrapping.function_extend_or_restrict(function, component_from, self.space, component_to, weight, copy)) def clear(self): self._list = list() # Reset precomputed slices self._precomputed_slices.clear() def save(self, directory, filename): self._save_Nmax(directory, filename) for (index, function) in enumerate(self._list): wrapping.function_save(function, directory, filename + "_" + str(index)) def _save_Nmax(self, directory, filename): def save_Nmax_task(): with open(os.path.join(str(directory), filename + ".length"), "w") as length: length.write(str(len(self._list))) parallel_io(save_Nmax_task, self.mpi_comm) def load(self, directory, filename): if len(self._list) > 0: # avoid loading multiple times return False Nmax = self._load_Nmax(directory, filename) for index in range(Nmax): function = backend.Function(self.space) wrapping.function_load(function, directory, filename + "_" + str(index)) self.enrich(function) return True def _load_Nmax(self, directory, filename): def load_Nmax_task(): with open(os.path.join(str(directory), filename + ".length"), "r") as length: return int(length.readline()) return parallel_io(load_Nmax_task, self.mpi_comm) @overload( online_backend.OnlineMatrix.Type(), ) def __mul__(self, other): return wrapping.functions_list_mul_online_matrix( self, other, type(self)) @overload( (online_backend.OnlineVector.Type(), ThetaType), ) def __mul__(self, other): return wrapping.functions_list_mul_online_vector(self, other) @overload( online_backend.OnlineFunction.Type(), ) def __mul__(self, other): return wrapping.functions_list_mul_online_vector( self, online_wrapping.function_to_vector(other)) def __len__(self): return len(self._list) @overload(int) def __getitem__(self, key): return self._list[key] @overload(slice) # e.g. key = :N, return the first N functions def __getitem__(self, key): if key.start is not None: start = key.start else: start = 0 assert key.step is None if key.stop is not None: stop = key.stop else: stop = len(self._list) assert start <= stop if start < stop: assert start >= 0 assert start < len(self._list) assert stop > 0 assert stop <= len(self._list) # elif start == stop # trivial case which will result in an empty FunctionsList if (start, stop) not in self._precomputed_slices: output = _FunctionsList.__new__(type(self), self.space) output.__init__(self.space) if start < stop: output._list = self._list[key] self._precomputed_slices[start, stop] = output return self._precomputed_slices[start, stop] @overload(int, backend.Function.Type()) def __setitem__(self, key, item): self._list[key] = item @overload(int, object) def __setitem__(self, key, item): if AdditionalIsFunction(item): item = ConvertAdditionalFunctionTypes(item) self._list[key] = item else: raise RuntimeError( "Invalid function provided to FunctionsList.__setitem__()") def __iter__(self): return self._list.__iter__()
class UpperBoundsList(list): def __init__(self): self._list = list() def append(self, element): self._list.append(element) @overload(list_of(OnlineVector.Type())) def extend(self, other_list): self._list.extend(other_list) @overload(lambda cls: cls) def extend(self, other_list): self._list.extend(other_list._list) def save(self, directory, filename): # Get full directory name full_directory = Folders.Folder(os.path.join(str(directory), filename)) full_directory.create() # Save list length self._save_len(full_directory) # Save list item vector dimension self._save_item_vector_dimension(full_directory) # Save list self._save_list(full_directory) def _save_len(self, full_directory): LenIO.save_file(len(self._list), full_directory, "len") def _save_item_vector_dimension(self, full_directory): ItemVectorDimensionIO.save_file(self._list[0].N, full_directory, "item_vector_dimension") def _save_list(self, full_directory): for (index, item) in enumerate(self._list): online_export(item, full_directory, "item_" + str(index)) def load(self, directory, filename): if len(self._list) > 0: # avoid loading multiple times return False else: # Get full directory name full_directory = Folders.Folder(os.path.join(str(directory), filename)) # Load list length len_ = self._load_len(full_directory) # Load list item vector dimension reference_vector = self._load_item_vector_dimension(full_directory) # Load list self._load_list(len_, reference_vector, full_directory) # Return return True def _load_len(self, full_directory): assert LenIO.exists_file(full_directory, "len") return LenIO.load_file(full_directory, "len") def _load_item_vector_dimension(self, full_directory): N = ItemVectorDimensionIO.load_file(full_directory, "item_vector_dimension") return OnlineVector(N) def _load_list(self, len_, reference_vector, full_directory): for index in range(len_): item = online_copy(reference_vector) online_import_(item, full_directory, "item_" + str(index)) self._list.append(item) def __getitem__(self, key): return self._list[key] def __setitem__(self, key, item): self._list[key] = item def __iter__(self): return iter(self._list) def __len__(self): return len(self._list)
def _residual_bcs_apply(self, bcs: (list_of(DirichletBC), ProductOutputDirichletBC)): for bc in self.bcs: bc.apply(self.residual_vector, self.solution.vector())
def _solution_bcs_apply(self, bcs: (list_of(DirichletBC), ProductOutputDirichletBC)): for bc in bcs: bc.apply(self.solution.vector())
# Copyright (C) 2015-2021 by the RBniCS authors # # This file is part of RBniCS. # # SPDX-License-Identifier: LGPL-3.0-or-later from dolfin import FunctionSpace from rbnics.backends.basic import BasisFunctionsMatrix as BasicBasisFunctionsMatrix from rbnics.backends.dolfin.function import Function from rbnics.backends.dolfin.functions_list import FunctionsList from rbnics.backends.dolfin.wrapping import (basis_functions_matrix_mul_online_matrix, basis_functions_matrix_mul_online_vector, function_to_vector, get_function_subspace, get_mpi_comm) from rbnics.backends.online import OnlineFunction, OnlineMatrix, OnlineVector from rbnics.backends.online.wrapping import function_to_vector as online_function_to_online_vector from rbnics.utils.decorators import BackendFor, list_of, ModuleWrapper backend = ModuleWrapper(Function, FunctionsList) wrapping = ModuleWrapper(basis_functions_matrix_mul_online_matrix, basis_functions_matrix_mul_online_vector, function_to_vector, get_function_subspace, get_mpi_comm) online_backend = ModuleWrapper(OnlineFunction=OnlineFunction, OnlineMatrix=OnlineMatrix, OnlineVector=OnlineVector) online_wrapping = ModuleWrapper(online_function_to_online_vector) BasisFunctionsMatrix_Base = BasicBasisFunctionsMatrix(backend, wrapping, online_backend, online_wrapping) @BackendFor("dolfin", inputs=(FunctionSpace, (list_of(str), str, None))) class BasisFunctionsMatrix(BasisFunctionsMatrix_Base): pass
# Copyright (C) 2015-2020 by the RBniCS authors # # This file is part of RBniCS. # # SPDX-License-Identifier: LGPL-3.0-or-later from numbers import Number from rbnics.backends.common.product import ProductOutput from rbnics.utils.decorators import backend_for, list_of, overload, tuple_of python_sum = sum # product function to assemble truth/reduced affine expansions. To be used in combination with product, # even though product actually carries out both the sum and the product! @backend_for("common", inputs=((list_of(Number), ProductOutput, tuple_of(Number)), )) def sum(args): return _sum(args) @overload def _sum(args: ProductOutput): return args.sum_product_return_value @overload def _sum(args: (list_of(Number), tuple_of(Number))): return python_sum(args)
def _sum(args: (list_of(Number), tuple_of(Number))): return python_sum(args)
# Copyright (C) 2015-2020 by the RBniCS authors # # This file is part of RBniCS. # # SPDX-License-Identifier: LGPL-3.0-or-later from numbers import Number from rbnics.backends.common.time_series import TimeSeries from rbnics.utils.decorators import backend_for, list_of, overload @backend_for("common", inputs=((list_of(Number), TimeSeries), (list_of(Number), TimeSeries))) def assign(object_to, object_from): _assign(object_to, object_from) @overload def _assign(object_to: TimeSeries, object_from: TimeSeries): if object_from is not object_to: from rbnics.backends import assign assign(object_to._list, object_from._list) @overload def _assign(object_to: list_of(Number), object_from: list_of(Number)): if object_from is not object_to: del object_to[:] object_to.extend(object_from)
def _assign(object_to: list_of(Number), object_from: list_of(Number)): if object_from is not object_to: del object_to[:] object_to.extend(object_from)
class _BasisFunctionsMatrix(AbstractBasisFunctionsMatrix): def __init__(self, space, component=None): if component is not None: self.space = wrapping.get_function_subspace(space, component) else: self.space = space self.mpi_comm = wrapping.get_mpi_comm(space) self._components = dict() # of FunctionsList self._precomputed_sub_components = Cache( ) # from tuple to FunctionsList self._precomputed_slices = Cache() # from tuple to FunctionsList self._components_name = list() # filled in by init self._component_name_to_basis_component_index = ComponentNameToBasisComponentIndexDict( ) # filled in by init self._component_name_to_basis_component_length = OnlineSizeDict() def init(self, components_name): if self._components_name != components_name: # Do nothing if it was already initialized with the same dicts # Store components name self._components_name = components_name # Initialize components FunctionsList self._components.clear() for component_name in components_name: self._components[component_name] = backend.FunctionsList( self.space) # Prepare len components self._component_name_to_basis_component_length.clear() for component_name in components_name: self._component_name_to_basis_component_length[ component_name] = 0 # Intialize the component_name_to_basis_component_index dict self._component_name_to_basis_component_index.clear() for (basis_component_index, component_name) in enumerate(components_name): self._component_name_to_basis_component_index[ component_name] = basis_component_index # Reset precomputed sub components self._precomputed_sub_components.clear() # Reset precomputed slices self._precomputed_slices.clear() # Patch FunctionsList.enrich() to update internal attributes def patch_functions_list_enrich(component_name, functions_list): original_functions_list_enrich = functions_list.enrich def patched_functions_list_enrich(self_, functions, component=None, weights=None, copy=True): # Append to storage original_functions_list_enrich(functions, component, weights, copy) # Update component name to basis component length if component is not None: if isinstance(component, dict): assert len(component) == 1 for (_, component_to) in component.items(): break assert component_name == component_to else: assert component_name == component self._update_component_name_to_basis_component_length( component_name) # Reset precomputed sub components self._precomputed_sub_components.clear() # Prepare trivial precomputed sub components self._prepare_trivial_precomputed_sub_components() # Reset precomputed slices self._precomputed_slices.clear() # Prepare trivial precomputed slice self._prepare_trivial_precomputed_slice() functions_list.enrich_patch = PatchInstanceMethod( functions_list, "enrich", patched_functions_list_enrich) functions_list.enrich_patch.patch() for component_name in components_name: patch_functions_list_enrich( component_name, self._components[component_name]) def enrich(self, functions, component=None, weights=None, copy=True): assert copy is True # Append to storage self._enrich(functions, component, weights, copy) @overload( object, None, (None, list_of(Number)), bool ) # the first argument is object in order to handle FunctionsList's AdditionalFunctionType def _enrich(self, functions, component, weights, copy): assert len(self._components) == 1 assert len(self._components_name) == 1 component_0 = self._components_name[0] self._components[component_0].enrich(functions, None, weights, copy) @overload( object, str, (None, list_of(Number)), bool ) # the first argument is object in order to handle FunctionsList's AdditionalFunctionType def _enrich(self, functions, component, weights, copy): assert component in self._components self._components[component].enrich(functions, component, weights, copy) @overload( object, dict_of(str, str), (None, list_of(Number)), bool ) # the first argument is object in order to handle FunctionsList's AdditionalFunctionType def _enrich(self, functions, component, weights, copy): assert len(component) == 1 for (_, component_to) in component.items(): break assert component_to in self._components self._components[component_to].enrich(functions, component, weights) @overload(None) def _update_component_name_to_basis_component_length(self, component): assert len(self._components) == 1 assert len(self._components_name) == 1 component_0 = self._components_name[0] self._component_name_to_basis_component_length[component_0] = len( self._components[component_0]) @overload(str) def _update_component_name_to_basis_component_length(self, component): self._component_name_to_basis_component_length[component] = len( self._components[component]) @overload(dict_of(str, str)) def _update_component_name_to_basis_component_length(self, component): assert len(component) == 1 for (_, component_to) in component.items(): break assert component_to in self._components self._component_name_to_basis_component_length[component_to] = len( self._components[component_to]) def _prepare_trivial_precomputed_sub_components(self): self._precomputed_sub_components[tuple( self._components_name)] = self def _prepare_trivial_precomputed_slice(self): if len(self._components) == 1: assert len(self._components_name) == 1 component_0 = self._components_name[0] precomputed_slice_key_start = 0 precomputed_slice_key_stop = self._component_name_to_basis_component_length[ component_0] else: precomputed_slice_key_start = list() precomputed_slice_key_stop = list() for component_name in self._components_name: precomputed_slice_key_start.append(0) precomputed_slice_key_stop.append( self._component_name_to_basis_component_length[ component_name]) precomputed_slice_key_start = tuple( precomputed_slice_key_start) precomputed_slice_key_stop = tuple(precomputed_slice_key_stop) self._precomputed_slices[precomputed_slice_key_start, precomputed_slice_key_stop] = self def clear(self): components_name = self._components_name # Trick _init into re-initializing everything self._components_name = None self.init(components_name) def save(self, directory, filename): if len(self._components) > 1: def filename_and_component(component_name): return filename + "_" + component_name else: def filename_and_component(component_name): return filename for (component_name, functions_list) in self._components.items(): functions_list.save(directory, filename_and_component(component_name)) def load(self, directory, filename): return_value = True assert len(self._components) > 0 if len(self._components) > 1: def filename_and_component(component_name): return filename + "_" + component_name else: def filename_and_component(component_name): return filename for (component_name, functions_list) in self._components.items(): # Skip updating internal attributes while reading in basis functions, we will do that # only once at the end assert hasattr(functions_list, "enrich_patch") functions_list.enrich_patch.unpatch() # Load each component return_value_component = functions_list.load( directory, filename_and_component(component_name)) return_value = return_value and return_value_component # Populate component length self._update_component_name_to_basis_component_length( component_name) # Restore patched enrich method functions_list.enrich_patch.patch() # Reset precomputed sub components self._precomputed_sub_components.clear() # Prepare trivial precomputed sub components self._prepare_trivial_precomputed_sub_components() # Reset precomputed slices self._precomputed_slices.clear() # Prepare trivial precomputed slice self._prepare_trivial_precomputed_slice() # Return return return_value @overload( online_backend.OnlineMatrix.Type(), ) def __mul__(self, other): if isinstance(other.M, dict): assert set(other.M.keys()) == set(self._components_name) def BasisFunctionsMatrixWithInit(space): output = _BasisFunctionsMatrix.__new__(type(self), space) output.__init__(space) output.init(self._components_name) return output return wrapping.basis_functions_matrix_mul_online_matrix( self, other, BasisFunctionsMatrixWithInit) @overload( online_backend.OnlineFunction.Type(), ) def __mul__(self, other): return self.__mul__(online_wrapping.function_to_vector(other)) @overload( online_backend.OnlineVector.Type(), ) def __mul__(self, other): if isinstance(other.N, dict): assert set(other.N.keys()) == set(self._components_name) return wrapping.basis_functions_matrix_mul_online_vector( self, other) @overload( ThetaType, ) def __mul__(self, other): return wrapping.basis_functions_matrix_mul_online_vector( self, other) def __len__(self): assert len(self._components_name) == 1 assert len(self._component_name_to_basis_component_length) == 1 return self._component_name_to_basis_component_length[ self._components_name[0]] @overload(int) def __getitem__(self, key): # spare the user an obvious extraction of the first component return basis function number key assert len(self._components) == 1 assert len(self._components_name) == 1 component_0 = self._components_name[0] return self._components[component_0][key] @overload(str) def __getitem__(self, key): # return all basis functions for each component, then the user may use __getitem__ of FunctionsList to extract a single basis function return self._components[key] @overload(list_of(str)) def __getitem__(self, key): return self._precompute_sub_components(key) @overload(slice) # e.g. key = :N, return the first N functions def __getitem__(self, key): assert key.step is None return self._precompute_slice(key.start, key.stop) @overload( int, object ) # the second argument is object in order to handle FunctionsList's AdditionalFunctionType def __setitem__(self, key, item): assert len( self._components ) == 1, "Cannot set components, only single functions. Did you mean to call __getitem__ to extract a component and __setitem__ of a single function on that component?" assert len(self._components_name) == 1 self._components[self._components_name[0]][key] = item @overload(None, int) def _precompute_slice(self, _, N_stop): return self._precompute_slice(0, N_stop) @overload(int, None) def _precompute_slice(self, N_start, _): return self._precompute_slice(N_start, len(self)) @overload(int, int) def _precompute_slice(self, N_start, N_stop): if (N_start, N_stop) not in self._precomputed_slices: assert len(self._components) == 1 output = _BasisFunctionsMatrix.__new__(type(self), self.space) output.__init__(self.space) output.init(self._components_name) for component_name in self._components_name: output._components[component_name].enrich( self._components[component_name][N_start:N_stop], copy=False) self._precomputed_slices[N_start, N_stop] = output return self._precomputed_slices[N_start, N_stop] @overload(None, OnlineSizeDict) def _precompute_slice(self, _, N_stop): N_start = OnlineSizeDict() for component_name in self._components_name: N_start[component_name] = 0 return self._precompute_slice(N_start, N_stop) @overload(OnlineSizeDict, None) def _precompute_slice(self, N_start, _): N_stop = OnlineSizeDict() for component_name in self._components_name: N_stop[ component_name] = self._component_name_to_basis_component_length[ component_name] return self._precompute_slice(N_start, len(self)) @overload(OnlineSizeDict, OnlineSizeDict) def _precompute_slice(self, N_start, N_stop): assert set(N_start.keys()) == set(self._components_name) assert set(N_stop.keys()) == set(self._components_name) N_start_key = tuple(N_start[component_name] for component_name in self._components_name) N_stop_key = tuple(N_stop[component_name] for component_name in self._components_name) if (N_start_key, N_stop_key) not in self._precomputed_slices: output = _BasisFunctionsMatrix.__new__(type(self), self.space) output.__init__(self.space) output.init(self._components_name) for component_name in self._components_name: output._components[component_name].enrich( self._components[component_name] [N_start[component_name]:N_stop[component_name]], copy=False) self._precomputed_slices[N_start_key, N_stop_key] = output return self._precomputed_slices[N_start_key, N_stop_key] def _precompute_sub_components(self, sub_components): sub_components_key = tuple(sub_components) if sub_components_key not in self._precomputed_sub_components: assert set(sub_components).issubset(self._components_name) output = _BasisFunctionsMatrix.__new__(type(self), self.space, sub_components) output.__init__(self.space, sub_components) output.init(sub_components) for component_name in sub_components: output._components[component_name].enrich( self._components[component_name], component=component_name, copy=True) self._precomputed_sub_components[sub_components_key] = output return self._precomputed_sub_components[sub_components_key] def __iter__(self): assert len(self._components) == 1 assert len(self._components_name) == 1 component_0 = self._components_name[0] return self._components[component_0].__iter__()
def Matrix(m, n): return numpy_matrix(zeros((m, n))) def Vector(n): return zeros((n, )) class Error(RuntimeError): pass # Linear program solver @BackendFor("common", inputs=(numpy_vector, numpy_matrix, numpy_vector, list_of(tuple_of(Number)))) class LinearProgramSolver(AbstractLinearProgramSolver): def __init__(self, cost, inequality_constraints_matrix, inequality_constraints_vector, bounds): self.Q = len(cost) # Store cost self.cost = cvxopt.matrix(cost) # Store inequality constraints matrix, also including a 2*Q x 2*Q submatrix for bound constraints self.inequality_constraints_matrix = cvxopt.matrix( vstack( (-inequality_constraints_matrix, -eye(self.Q), eye(self.Q)))) # Store inequality constraints vector, also including 2*Q rows for bound constraints assert len(bounds) == self.Q bounds_lower = zeros(self.Q) bounds_upper = zeros(self.Q) for (q, bounds_q) in enumerate(bounds):
# RBniCS is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RBniCS. If not, see <http://www.gnu.org/licenses/>. # from numbers import Number from scipy.integrate import simps from rbnics.backends.abstract import TimeQuadrature as AbstractTimeQuadrature from rbnics.backends.online.numpy.function import Function from rbnics.utils.decorators import BackendFor, list_of, tuple_of @BackendFor("numpy", inputs=(tuple_of(Number), list_of(Function.Type()))) class TimeQuadrature(AbstractTimeQuadrature): def __init__(self, time_interval, function_over_time): assert len(function_over_time) > 1 self._time_step_size = (time_interval[1] - time_interval[0])/(len(function_over_time) - 1) self._function_over_time = function_over_time def integrate(self): vector_over_time = list() N = self._function_over_time[0].N for function in self._function_over_time: assert function.N == N vector_over_time.append(function.vector()) integrated_vector = simps(vector_over_time, dx=self._time_step_size, axis=0) integrated_function = Function(N) integrated_function.vector()[:] = integrated_vector
class _Assign(object): @overload(backend.Function.Type(), backend.Function.Type()) def __call__(self, object_to, object_from): if object_from is not object_to: assert isinstance(object_to.vector().N, (dict, int)) assert isinstance(object_from.vector().N, (dict, int)) if isinstance(object_from.vector().N, dict) and isinstance( object_to.vector().N, dict): from_N_keys = set(object_from.vector().N.keys()) to_N_keys = set(object_to.vector().N.keys()) components_in_both = from_N_keys & to_N_keys for c in components_in_both: assert object_to.vector().N[c] == object_from.vector( ).N[c] components_only_in_from = from_N_keys - to_N_keys components_only_in_to = to_N_keys - from_N_keys from_N_dict = OnlineSizeDict() to_N_dict = OnlineSizeDict() for c in components_in_both: from_N_dict[c] = object_from.vector().N[c] to_N_dict[c] = object_to.vector().N[c] for c in components_only_in_from: from_N_dict[c] = 0 for c in components_only_in_to: to_N_dict[c] = 0 object_to.vector()[:to_N_dict] = object_from.vector( )[:from_N_dict] self._preserve_vector_attributes( object_to.vector(), object_from.vector(), len(components_only_in_from) > 0, len(components_only_in_to) > 0) elif isinstance(object_from.vector().N, int) and isinstance( object_to.vector().N, dict): assert len(object_to.vector().N) == 1 raise ValueError( "Refusing to assign a dict dimension N to an int dimension N" ) elif isinstance(object_from.vector().N, dict) and isinstance( object_to.vector().N, int): assert len(object_from.vector().N) == 1 for (c, N_c) in object_from.vector().N.items(): break assert N_c == object_to.vector().N N = OnlineSizeDict() N[c] = N_c object_to.vector().N = N object_to.vector()[:] = object_from.vector() self._preserve_vector_attributes(object_to.vector(), object_from.vector()) else: # isinstance(object_from.vector().N, int) and isinstance(object_to.vector().N, int): assert object_to.vector().N == object_from.vector().N object_to.vector()[:] = object_from.vector() self._preserve_vector_attributes(object_to.vector(), object_from.vector()) @overload(list_of(backend.Function.Type()), list_of(backend.Function.Type())) def __call__(self, object_to, object_from): if object_from is not object_to: del object_to[:] object_to.extend(object_from) @overload(backend.Matrix.Type(), backend.Matrix.Type()) def __call__(self, object_to, object_from): if object_from is not object_to: assert object_to.N == object_from.N assert object_to.M == object_from.M object_to[:, :] = object_from self._preserve_matrix_attributes(object_to, object_from) @overload(backend.Vector.Type(), backend.Vector.Type()) def __call__(self, object_to, object_from): if object_from is not object_to: assert object_to.N == object_from.N object_to[:] = object_from self._preserve_vector_attributes(object_to, object_from) def _preserve_vector_attributes(self, object_to, object_from, subset=False, superset=False): # Preserve auxiliary attributes related to basis functions matrix assert (object_to._component_name_to_basis_component_index is None ) == (object_to._component_name_to_basis_component_length is None) if object_to._component_name_to_basis_component_index is None: assert not subset object_to._component_name_to_basis_component_index = object_from._component_name_to_basis_component_index object_to._component_name_to_basis_component_length = object_from._component_name_to_basis_component_length else: if not subset and not superset: assert object_from._component_name_to_basis_component_index == object_to._component_name_to_basis_component_index assert object_from._component_name_to_basis_component_length == object_to._component_name_to_basis_component_length elif subset: assert set( object_to._component_name_to_basis_component_index. keys()) <= set( object_from. _component_name_to_basis_component_index.keys()) assert object_to._component_name_to_basis_component_length.items( ) <= object_from._component_name_to_basis_component_length.items( ) else: # is superset assert set( object_to._component_name_to_basis_component_index. keys()) >= set( object_from. _component_name_to_basis_component_index.keys()) assert object_to._component_name_to_basis_component_length.items( ) >= object_from._component_name_to_basis_component_length.items( ) def _preserve_matrix_attributes(self, object_to, object_from): # Preserve auxiliary attributes related to basis functions matrix assert (object_to._component_name_to_basis_component_index[0] is None) == ( object_to._component_name_to_basis_component_length[0] is None) assert (object_to._component_name_to_basis_component_index[0] is None) == ( object_to._component_name_to_basis_component_index[1] is None) assert (object_to._component_name_to_basis_component_length[0] is None) == ( object_to._component_name_to_basis_component_length[1] is None) if object_to._component_name_to_basis_component_index[0] is None: object_to._component_name_to_basis_component_index = object_from._component_name_to_basis_component_index object_to._component_name_to_basis_component_length = object_from._component_name_to_basis_component_length else: assert object_from._component_name_to_basis_component_index == object_to._component_name_to_basis_component_index assert object_from._component_name_to_basis_component_length == object_to._component_name_to_basis_component_length
from ufl import Form from dolfin import assemble, DirichletBC, PETScLUSolver from rbnics.backends.abstract import LinearSolver as AbstractLinearSolver, LinearProblemWrapper from rbnics.backends.dolfin.evaluate import evaluate from rbnics.backends.dolfin.function import Function from rbnics.backends.dolfin.matrix import Matrix from rbnics.backends.dolfin.parametrized_tensor_factory import ParametrizedTensorFactory from rbnics.backends.dolfin.vector import Vector from rbnics.backends.dolfin.wrapping.dirichlet_bc import ProductOutputDirichletBC from rbnics.utils.decorators import BackendFor, dict_of, list_of, overload @BackendFor("dolfin", inputs=((Form, Matrix.Type(), ParametrizedTensorFactory, LinearProblemWrapper), Function.Type(), (Form, ParametrizedTensorFactory, Vector.Type(), None), (list_of(DirichletBC), ProductOutputDirichletBC, dict_of(str, list_of(DirichletBC)), dict_of(str, ProductOutputDirichletBC), None))) class LinearSolver(AbstractLinearSolver): @overload((Form, Matrix.Type(), ParametrizedTensorFactory), Function.Type(), (Form, ParametrizedTensorFactory, Vector.Type()), (list_of(DirichletBC), ProductOutputDirichletBC, dict_of(str, list_of(DirichletBC)), dict_of(str, ProductOutputDirichletBC), None)) def __init__(self, lhs, solution, rhs, bcs=None): self.solution = solution self._init_lhs(lhs, bcs) self._init_rhs(rhs, bcs) self._apply_bcs(bcs) self._linear_solver = "default" self.monitor = None @overload(LinearProblemWrapper, Function.Type())
# RBniCS is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RBniCS is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RBniCS. If not, see <http://www.gnu.org/licenses/>. # from numbers import Number from rbnics.utils.decorators import backend_for, list_of from rbnics.utils.io import Folders, TextIO @backend_for("common", inputs=(list_of(Number), (Folders.Folder, str), str, None, None)) def import_(solution, directory, filename, suffix=None, component=None): if TextIO.exists_file(directory, filename): loaded_solution = TextIO.load_file(directory, filename) assert len(solution) == len(loaded_solution) for (i, solution_i) in enumerate(loaded_solution): solution[i] = float(solution_i) return True else: return False
class LinearSolver(AbstractLinearSolver): @overload((Form, Matrix.Type(), ParametrizedTensorFactory), Function.Type(), (Form, ParametrizedTensorFactory, Vector.Type()), (list_of(DirichletBC), ProductOutputDirichletBC, dict_of(str, list_of(DirichletBC)), dict_of(str, ProductOutputDirichletBC), None)) def __init__(self, lhs, solution, rhs, bcs=None): self.solution = solution self._init_lhs(lhs, bcs) self._init_rhs(rhs, bcs) self._apply_bcs(bcs) self._linear_solver = "default" self.monitor = None @overload(LinearProblemWrapper, Function.Type()) def __init__(self, problem_wrapper, solution): self.__init__(problem_wrapper.matrix_eval(), solution, problem_wrapper.vector_eval(), problem_wrapper.bc_eval()) self.monitor = problem_wrapper.monitor @overload(Form, (list_of(DirichletBC), ProductOutputDirichletBC, dict_of(str, list_of(DirichletBC)), dict_of(str, ProductOutputDirichletBC), None)) def _init_lhs(self, lhs, bcs): self.lhs = assemble(lhs, keep_diagonal=True) @overload(ParametrizedTensorFactory, (list_of(DirichletBC), ProductOutputDirichletBC, dict_of(str, list_of(DirichletBC)), dict_of(str, ProductOutputDirichletBC), None)) def _init_lhs(self, lhs, bcs): self.lhs = evaluate(lhs) @overload(Matrix.Type(), None) def _init_lhs(self, lhs, bcs): self.lhs = lhs @overload(Matrix.Type(), (list_of(DirichletBC), ProductOutputDirichletBC, dict_of(str, list_of(DirichletBC)), dict_of(str, ProductOutputDirichletBC))) def _init_lhs(self, lhs, bcs): # Create a copy of lhs, in order not to change # the original references when applying bcs self.lhs = lhs.copy() @overload(Form, (list_of(DirichletBC), ProductOutputDirichletBC, dict_of(str, list_of(DirichletBC)), dict_of(str, ProductOutputDirichletBC), None)) def _init_rhs(self, rhs, bcs): self.rhs = assemble(rhs) @overload(ParametrizedTensorFactory, (list_of(DirichletBC), ProductOutputDirichletBC, dict_of(str, list_of(DirichletBC)), dict_of(str, ProductOutputDirichletBC), None)) def _init_rhs(self, rhs, bcs): self.rhs = evaluate(rhs) @overload(Vector.Type(), None) def _init_rhs(self, rhs, bcs): self.rhs = rhs @overload(Vector.Type(), (list_of(DirichletBC), ProductOutputDirichletBC, dict_of(str, list_of(DirichletBC)), dict_of(str, ProductOutputDirichletBC))) def _init_rhs(self, rhs, bcs): # Create a copy of rhs, in order not to change # the original references when applying bcs self.rhs = rhs.copy() @overload(None) def _apply_bcs(self, bcs): pass @overload((list_of(DirichletBC), ProductOutputDirichletBC)) def _apply_bcs(self, bcs): for bc in bcs: bc.apply(self.lhs, self.rhs) @overload((dict_of(str, list_of(DirichletBC)), dict_of(str, ProductOutputDirichletBC))) def _apply_bcs(self, bcs): for key in bcs: for bc in bcs[key]: bc.apply(self.lhs, self.rhs) def set_parameters(self, parameters): assert len(parameters) in (0, 1) if len(parameters) == 1: assert "linear_solver" in parameters self._linear_solver = parameters.get("linear_solver", "default") def solve(self): solver = PETScLUSolver(self._linear_solver) solver.solve(self.lhs, self.solution.vector(), self.rhs) if self.monitor is not None: self.monitor(self.solution)
# Copyright (C) 2015-2021 by the RBniCS authors # # This file is part of RBniCS. # # SPDX-License-Identifier: LGPL-3.0-or-later from numbers import Number from rbnics.utils.decorators import backend_for, list_of from rbnics.utils.io import Folders, TextIO @backend_for("common", inputs=(list_of(Number), (Folders.Folder, str), str, (int, None), None)) def import_(solution, directory, filename, suffix=None, component=None): if suffix is not None: filename = filename + "_" + str(suffix) if TextIO.exists_file(directory, filename): loaded_solution = TextIO.load_file(directory, filename) assert len(solution) == len(loaded_solution) for (i, solution_i) in enumerate(loaded_solution): solution[i] = float(solution_i) else: raise OSError
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RBniCS. If not, see <http://www.gnu.org/licenses/>. # from numbers import Number from scipy.integrate import simps from rbnics.backends.abstract import TimeQuadrature as AbstractTimeQuadrature from rbnics.backends.dolfin.function import Function from rbnics.backends.dolfin.wrapping import function_copy from rbnics.utils.decorators import BackendFor, list_of, tuple_of @BackendFor("dolfin", inputs=(tuple_of(Number), list_of(Function.Type()))) class TimeQuadrature(AbstractTimeQuadrature): def __init__(self, time_interval, function_over_time): assert len(function_over_time) > 1 self._time_step_size = (time_interval[1] - time_interval[0]) / ( len(function_over_time) - 1) self._function_over_time = function_over_time def integrate(self): vector_over_time = list() for function in self._function_over_time: vector_over_time.append(function.vector().get_local()) integrated_vector = simps(vector_over_time, dx=self._time_step_size, axis=0) integrated_function = function_copy(self._function_over_time[0])
raise Error("Linear program solver reports convergence failure with reason", result["status"]) else: return result["primal objective"] if linear_programming_backends["scipy"]: class SciPyLinearProgramSolver(AbstractLinearProgramSolver): def __init__(self, cost, inequality_constraints_matrix, inequality_constraints_vector, bounds): self.cost = cost self.inequality_constraints_matrix = - inequality_constraints_matrix self.inequality_constraints_vector = - inequality_constraints_vector self.bounds = bounds def solve(self): result = linprog(self.cost, self.inequality_constraints_matrix, self.inequality_constraints_vector, bounds=self.bounds) if not result.success: raise Error("Linear program solver reports convergence failure with reason", result.status) else: return result.fun from numbers import Number if linear_programming_backends["cvxopt"]: @BackendFor("common", inputs=(numpy_vector, numpy_matrix, numpy_vector, list_of(tuple_of(Number)))) class LinearProgramSolver(CVXOPTLinearProgramSolver): pass elif linear_programming_backends["scipy"]: @BackendFor("common", inputs=(numpy_vector, numpy_matrix, numpy_vector, list_of(tuple_of(Number)))) class LinearProgramSolver(SciPyLinearProgramSolver): pass else: raise RuntimeError("No linear programming backends found")
def test_supercedes_2(): class A(object): pass class B(A): pass class C(object): pass assert supercedes((B, ), (A, )) assert supercedes((B, A), (A, A)) assert not supercedes((B, A), (A, B)) assert not supercedes((A, ), (B, )) assert supercedes((B, ), ((A, C), )) assert supercedes((C, ), ((A, C), )) assert not supercedes((A, ), ((B, C), )) assert not supercedes(((A, B), ), (B, )) assert supercedes(((A, B), ), (A, )) assert supercedes((A, ), ((A, B), )) assert supercedes((B, ), ((A, B), )) assert supercedes((iterable_of(B), ), (iterable_of(A), )) assert supercedes((iterable_of((B, A)), ), (iterable_of(A), )) assert supercedes((iterable_of((B, A)), ), (iterable_of((A, A)), )) assert supercedes((iterable_of((B, A)), ), (iterable_of((A, B)), )) assert supercedes((iterable_of((B, B)), ), (iterable_of((B)), )) assert supercedes((iterable_of((B, B)), ), (iterable_of((A, B)), )) assert supercedes((iterable_of(B), B), (iterable_of(A), A)) assert not supercedes((iterable_of(A), ), (iterable_of(B), )) assert supercedes((list_of(B), ), (list_of(A), )) assert supercedes((list_of((B, A)), ), (list_of(A), )) assert supercedes((list_of((B, A)), ), (list_of((A, A)), )) assert supercedes((list_of((B, A)), ), (list_of((A, B)), )) assert supercedes((list_of((B, B)), ), (list_of((B)), )) assert supercedes((list_of((B, B)), ), (list_of((A, B)), )) assert supercedes((list_of(B), B), (list_of(A), A)) assert not supercedes((list_of(A), ), (list_of(B), )) assert supercedes((list_of(B), ), (iterable_of(A), )) assert not supercedes((iterable_of(B), ), (list_of(A), )) assert supercedes((list_of((B, A)), ), (iterable_of(A), )) assert not supercedes((iterable_of((B, A)), ), (list_of(A), )) assert supercedes((list_of((B, A)), ), (iterable_of((A, A)), )) assert not supercedes((iterable_of((B, A)), ), (list_of((A, A)), )) assert supercedes((list_of((B, A)), ), (iterable_of((A, B)), )) assert not supercedes((iterable_of((B, A)), ), (list_of((A, B)), )) assert supercedes((list_of((B, B)), ), (iterable_of((B)), )) assert not supercedes((iterable_of((B, B)), ), (list_of((B)), )) assert supercedes((list_of((B, B)), ), (iterable_of((A, B)), )) assert not supercedes((iterable_of((B, B)), ), (list_of((A, B)), )) assert supercedes((list_of(B), B), (iterable_of(A), A)) assert not supercedes((iterable_of(B), B), (list_of(A), A)) assert not supercedes((list_of(A), ), (iterable_of(B), )) assert not supercedes((iterable_of(A), ), (list_of(B), )) assert supercedes((dict_of(B, C), ), (dict_of(A, C), )) assert supercedes((dict_of(B, C), ), (dict_of((A, C), C), )) assert supercedes((dict_of(C, C), ), (dict_of((A, C), C), )) assert not supercedes((dict_of((B, C), C), ), (dict_of(A, C), )) assert supercedes((dict_of(list_of(B), C), ), (dict_of(list_of(A), C), ))
def _assign(object_to: list_of(Function.Type()), object_from: list_of(Function.Type())): if object_from is not object_to: del object_to[:] object_to.extend(object_from)
def test_consistent_2(): class A(object): pass class B(A): pass class C(object): pass assert consistent((A, ), (A, )) assert consistent((B, ), (B, )) assert not consistent((A, ), (C, )) assert consistent((A, B), (A, B)) assert consistent((B, A), (A, B)) assert not consistent((B, A), (B, )) assert not consistent((B, A), (B, C)) assert consistent((iterable_of(A), ), (iterable_of(A), )) assert consistent((iterable_of(B), ), (iterable_of(B), )) assert not consistent((iterable_of(A), ), (iterable_of(C), )) assert consistent((iterable_of((A, B)), ), (iterable_of((A, B)), )) assert consistent((iterable_of((B, A)), ), (iterable_of((A, B)), )) assert consistent((iterable_of((B, A)), ), (iterable_of(B), )) assert consistent((iterable_of((B, A)), ), (iterable_of(A), )) assert not consistent((iterable_of((B, A)), ), (iterable_of((B, C)), )) assert consistent((list_of(A), ), (list_of(A), )) assert consistent((list_of(B), ), (list_of(B), )) assert not consistent((list_of(A), ), (list_of(C), )) assert consistent((list_of((A, B)), ), (list_of((A, B)), )) assert consistent((list_of((B, A)), ), (list_of((A, B)), )) assert consistent((list_of((B, A)), ), (list_of(B), )) assert consistent((list_of((B, A)), ), (list_of(A), )) assert not consistent((list_of((B, A)), ), (list_of((B, C)), )) assert not consistent((list_of(A), ), (iterable_of(A), )) assert not consistent((iterable_of(A), ), (list_of(A), )) assert not consistent((list_of(B), ), (iterable_of(B), )) assert not consistent((iterable_of(B), ), (list_of(B), )) assert not consistent((list_of(A), ), (iterable_of(C), )) assert not consistent((iterable_of(A), ), (list_of(C), )) assert not consistent((list_of((A, B)), ), (iterable_of((A, B)), )) assert not consistent((iterable_of((A, B)), ), (list_of((A, B)), )) assert not consistent((list_of((B, A)), ), (iterable_of((A, B)), )) assert not consistent((iterable_of((B, A)), ), (list_of((A, B)), )) assert not consistent((list_of((B, A)), ), (iterable_of(B), )) assert not consistent((iterable_of((B, A)), ), (list_of(B), )) assert not consistent((list_of((B, A)), ), (iterable_of(A), )) assert not consistent((iterable_of((B, A)), ), (list_of(A), )) assert not consistent((list_of((B, A)), ), (iterable_of((B, C)), )) assert not consistent((iterable_of((B, A)), ), (list_of((B, C)), )) assert consistent((dict_of(A, C), ), (dict_of(A, C), )) assert consistent((dict_of(B, C), ), (dict_of(B, C), )) assert not consistent((dict_of(A, C), ), (dict_of(C, C), ))
def _residual_bcs_apply(self, bcs: (dict_of(str, list_of(DirichletBC)), dict_of(str, ProductOutputDirichletBC))): for key in self.bcs: for bc in self.bcs[key]: bc.apply(self.residual_vector, self.solution.vector())
def test_ambiguous_2(): class A(object): pass class B(A): pass class C(object): pass assert not ambiguous((A, ), (A, )) assert not ambiguous((A, ), (B, )) assert not ambiguous((B, ), (B, )) assert not ambiguous((A, B), (B, B)) assert ambiguous((A, B), (B, A)) assert not ambiguous((list_of(A), ), (list_of(A), )) assert not ambiguous((list_of(B), ), (list_of(B), )) assert not ambiguous((list_of(A), ), (list_of(C), )) assert not ambiguous((list_of((A, B)), ), (list_of((A, B)), )) assert not ambiguous((list_of((B, A)), ), (list_of((A, B)), )) assert not ambiguous((list_of((B, A)), ), (list_of(B), )) assert not ambiguous((list_of((B, A)), ), (list_of(A), )) assert not ambiguous((list_of((B, A)), ), (list_of((B, C)), ))
def _jacobian_bcs_apply(self, bcs: (dict_of(str, list_of(DirichletBC)), dict_of(str, ProductOutputDirichletBC))): for key in self.bcs: for bc in self.bcs[key]: bc.apply(self.jacobian_matrix)
class E(object): @dispatch(list_of(int)) def __init__(self, arg): self.arg = arg[0]
# Copyright (C) 2015-2020 by the RBniCS authors # # This file is part of RBniCS. # # SPDX-License-Identifier: LGPL-3.0-or-later from rbnics.backends.basic import copy as basic_copy from rbnics.backends.dolfin.function import Function from rbnics.backends.dolfin.matrix import Matrix from rbnics.backends.dolfin.vector import Vector from rbnics.backends.dolfin.wrapping import function_copy, tensor_copy from rbnics.utils.decorators import backend_for, list_of, ModuleWrapper backend = ModuleWrapper(Function, Matrix, Vector) wrapping = ModuleWrapper(function_copy, tensor_copy) copy_base = basic_copy(backend, wrapping) @backend_for("dolfin", inputs=((Function.Type(), list_of(Function.Type()), Matrix.Type(), Vector.Type()), )) def copy(arg): return copy_base(arg)
# RBniCS is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RBniCS. If not, see <http://www.gnu.org/licenses/>. # from numbers import Number from scipy.integrate import simps from rbnics.backends.abstract import TimeQuadrature as AbstractTimeQuadrature from rbnics.backends.common.time_series import TimeSeries from rbnics.utils.decorators import backend_for, list_of, tuple_of, overload @backend_for("common", inputs=(tuple_of(Number), (list_of(Number), TimeSeries))) def TimeQuadrature(time_interval, function_over_time): return _TimeQuadrature(time_interval, function_over_time) class TimeQuadrature_Numbers(AbstractTimeQuadrature): def __init__(self, time_interval, function_over_time): assert len(function_over_time) > 1 self._time_step_size = (time_interval[1] - time_interval[0])/(len(function_over_time) - 1) self._function_over_time = function_over_time def integrate(self): return simps(self._function_over_time, dx=self._time_step_size) @overload def _TimeQuadrature(time_interval: tuple_of(Number), function_over_time: list_of(Number)): return TimeQuadrature_Numbers(time_interval, function_over_time)