def _gmres_single_op_imp( A, b, tol=1e-5, restart=None, maxiter=None, use_strong_form=False, return_residuals=False, return_iteration_count=False, ): """Implementation for single operators.""" from bempp.api.assembly.grid_function import GridFunction import scipy.sparse.linalg import bempp.api import time if not isinstance(b, GridFunction): raise ValueError("b must be of type GridFunction") # Assemble weak form before the logging messages if use_strong_form: if not A.range.is_compatible(b.space): raise ValueError( "The range of A and the domain of A must have" + "the same number of unknowns if the strong form is used.") A_op = A.strong_form() b_vec = b.coefficients else: A_op = A.weak_form() b_vec = b.projections(A.dual_to_range) callback = IterationCounter(return_residuals) bempp.api.log("Starting GMRES iteration") start_time = time.time() x, info = scipy.sparse.linalg.gmres(A_op, b_vec, tol=tol, restart=restart, maxiter=maxiter, callback=callback) end_time = time.time() bempp.api.log("GMRES finished in %i iterations and took %.2E sec." % (callback.count, end_time - start_time)) res_fun = GridFunction(A.domain, coefficients=x.ravel()) if return_residuals and return_iteration_count: return res_fun, info, callback.residuals, callback.count if return_residuals: return res_fun, info, callback.residuals if return_iteration_count: return res_fun, info, callback.count return res_fun, info
def grid_function_list_from_projections(projections, spaces, dual_spaces=None): """ Create a list of grid functions from a long vector of projections. Parameters ---------- coefficients : np.ndarray One-dimensional array of coefficients spaces : list of Space objects The sum of the global dofs of the spaces must be equal to the length of the coefficients vector. dual_spaces : list of Space objects The associated dual spaces. If None use the spaces as dual spaces. """ from bempp.api import GridFunction pos = 0 res_list = [] if dual_spaces is None: dual_spaces = spaces if len(spaces) != len(dual_spaces): raise ValueError("spaces must have the same length as dual_spaces") for space, dual in zip(spaces, dual_spaces): dof_count = space.global_dof_count res_list.append( GridFunction(space, projections=projections[pos:pos + dof_count], dual_space=dual)) pos += dof_count return res_list
def load(self, simulation_data, bem_data): # from bempp.api import function_space # from bempp.applications.room_acoustic import Simulation from bempp.api.grid import Grid from bempp.api.assembly.grid_function import GridFunction # Loading BEM object data for attr, value in vars(self).items(): if attr in bem_data.keys(): try: setattr(self, attr, bem_data[attr]) except TypeError: print('Cant load ' + str(attr) + ' field.') # Loading simulation data grid = Grid(simulation_data['grid']['vertices'], simulation_data['grid']['elements'], simulation_data['grid']['domain_indices']) # self.simulation = Simulation(simulation_data['frequencies'], self.admittance, grid) # self.set_SR() self.r0 = simulation_data['positions'] # self.pts = simulation_data['receivers'] self.q = simulation_data['amplitudes'] # self.set_status = True self.boundData = [] # self.simulation._incident_traces = [] # self.simulation._incident_fields = [] for sol in range(len(simulation_data['u'])): u = GridFunction(simulation_data['space'], coefficients=simulation_data['u'][sol]) un = GridFunction(simulation_data['space'], coefficients=simulation_data['un'][sol]) # incident_traces = GridFunction(self.simulation._space, coefficients=simulation_data['incident_traces'][sol]) self.boundData.append((u, un)) # self.simulation._incident_traces.append(incident_traces) # for frequency, mu in zip(self.simulation._frequencies, self.simulation._admittance_factors): # wavenumber = 2 * np.pi * frequency / 343 # _, uinc = self.simulation._compute_incident_trace_and_field(wavenumber, mu, grid=False, incident=True) # self.simulation._incident_fields.append(uinc) print('\tBEM loaded successfully.')
def __mul__(self, other): """Multiply two blocked operators.""" import collections if _np.isscalar(other): # Multiplication with scalar return ScaledBlockedOperator(self, other) elif isinstance(other, BlockedOperatorBase): # Multiplication with another blocked operator. return ProductBlockedOperator(self, other) elif isinstance(other, collections.Iterable): # Multiplication with a list of grid functions. from bempp.api.assembly.grid_function import GridFunction list_input = list(other) if len(list_input) != self.ndims[1]: raise ValueError( "Length of input list is {0}.".format(len(list_input)) + ". But domain dimension of blocked operator" + "is {0}".format(self.ndims[1])) for item in list_input: if not isinstance(item, GridFunction): raise ValueError( "All items in the input list must be grid functions.") weak_op = self.weak_form() input_type = list_input[0].coefficients.dtype for item in list_input: input_type = _np.promote_types(input_type, item.coefficients.dtype) x_in = _np.zeros(weak_op.shape[1], dtype=input_type) col_pos = _np.hstack([[0], _np.cumsum(weak_op.column_dimensions)]) row_pos = _np.hstack([[0], _np.cumsum(weak_op.row_dimensions)]) for index in range(weak_op.ndims[1]): x_in[col_pos[index]:col_pos[index+1]] = \ list_input[index].coefficients res = weak_op * x_in # Now assemble the output grid functions back together. output_list = [] for index in range(weak_op.ndims[0]): output_list.append( GridFunction(self.range_spaces[index], dual_space=self.dual_to_range_spaces[index], projections=res[row_pos[index]:row_pos[index + 1]])) return output_list else: return NotImplementedError
def grid_function_list_from_coefficients(coefficients, spaces): """ Create a list of grid functions from a long vector of coefficients. Parameters ---------- coefficients : np.ndarray One-dimensional array of coefficients spaces : list of Space objects The sum of the global dofs of the spaces must be equal to the length of the coefficients vector. """ from bempp.api import GridFunction pos = 0 res_list = [] for space in spaces: dof_count = space.global_dof_count res_list.append( GridFunction(space, coefficients=coefficients[pos:pos + dof_count])) pos += dof_count return res_list
def gmres(A_full, dual_to_range_sub, domain_sub, rhs_fun, Z, tol=1e-5,restart=None,maxiter=None): A_toe = get_weak_toe_form(A_full,Z) if isinstance(A_full, bempp.api.assembly.blocked_operator.BlockedOperatorBase): blocked = True b_vec = projections_from_grid_functions_list(rhs_fun, dual_to_range_sub) else: blocked = False b_vec = rhs_fun.projections(dual_to_range_sub) # use scipy's gmres to get the coefficients x, info = sp_gmres( A_toe, b_vec, tol=tol, restart=restart, maxiter=maxiter ) if blocked: res_fun = grid_function_list_from_coefficients(x.ravel(), domain_sub) else: res_fun = GridFunction(domain_sub, coefficients=x.ravel()) return res_fun, info
def cg( A, b, tol=1e-5, maxiter=None, use_strong_form=False, return_residuals=False, return_iteration_count=False, ): """Interface to the scipy.sparse.linalg.cg function. This function behaves like the scipy.sparse.linalg.cg function. But instead of a linear operator and a vector b it takes a boundary operator and a grid function. The result is returned as a grid function in the correct space. """ from bempp.api.assembly.boundary_operator import BoundaryOperator from bempp.api.assembly.grid_function import GridFunction import scipy.sparse.linalg import bempp.api import time if not isinstance(A, BoundaryOperator): raise ValueError("A must be of type BoundaryOperator") if not isinstance(b, GridFunction): raise ValueError("b must be of type GridFunction") if use_strong_form: if not A.range.is_compatible(b.space): raise ValueError( "The range of A and the domain of A must " + "have the same number of unknowns if the strong form is used.") A_op = A.strong_form() b_vec = b.coefficients else: A_op = A.weak_form() b_vec = b.projections(A.dual_to_range) callback = IterationCounter(return_residuals, True, A_op, b_vec) bempp.api.log("Starting CG iteration") start_time = time.time() x, info = scipy.sparse.linalg.cg(A_op, b_vec, tol=tol, maxiter=maxiter, callback=callback) end_time = time.time() bempp.api.log("CG finished in %i iterations and took %.2E sec." % (callback.count, end_time - start_time)) res_fun = GridFunction(A.domain, coefficients=x.ravel()) if return_residuals and return_iteration_count: return res_fun, info, callback.residuals, callback.count if return_residuals: return res_fun, info, callback.residuals if return_iteration_count: return res_fun, info, callback.count return res_fun, info