def buildBlockInverses(self, aca_tol): """Generate the Block LU decompositions """ from bempp import tools A = self.__A layers = self.__layers nproc = self.__comm.NumProc() my_id = self.__comm.MyPID() scheduler = self.__scheduler local_diag_blocks = [] if scheduler.has_key(my_id + 1): for elem in scheduler[my_id + 1]: if elem[0] == elem[1]: local_diag_blocks.append(elem[0]) # Create a vector with index offsets offsets = np.cumsum([0] + [layer['spaces']['ndof'] for layer in layers]) total_time = 0 # Now create the LU blocks and store together with offsets blocks = [] for id in local_diag_blocks: op00 = A.block(2 * id, 2 * id) op01 = A.block(2 * id, 2 * id + 1) op10 = A.block(2 * id + 1, 2 * id) op11 = A.block(2 * id + 1, 2 * id + 1) op = lib.createBlockedBoundaryOperator( self.__context, [[op00, op01], [op10, op11]]) print "Generate approximate LU for block %(id)i on process %(my_id)i..." % { 'id': id, 'my_id': my_id } tstart = time() lu = lib.acaOperatorApproximateLuInverse( op.weakForm().asDiscreteAcaBoundaryOperator(), aca_tol) tend = time() total_time += tend - tstart print "Finished generating approximate LU for block %(id)i on process %(my_id)i in %(tval)f seconds." % { 'id': id, 'my_id': my_id, 'tval': tend - tstart } blocks.append({ 'lu': tools.RealOperator(lu), 'start': offsets[id], 'end': offsets[id + 1], 'ndof': offsets[id + 1] - offsets[id], 'id': id }) self.__total_time_prec_initialisation = total_time return blocks, local_diag_blocks
def buildBlockInverses(self, aca_tol): """Generate the Block LU decompositions """ from bempp import tools A = self.__A layers = self.__layers nproc = self.__comm.NumProc() my_id = self.__comm.MyPID() scheduler = partition(procmap(blockmap(graph), nproc)) local_diag_blocks = [] if scheduler.has_key(my_id + 1): for elem in scheduler[my_id + 1]: if elem[0] == elem[1]: local_diag_blocks.append(elem[0]) # Create a vector with index offsets offsets = np.cumsum([0] + [layer['spaces']['ndof'] for layer in layers]) # Now create the LU blocks and store together with offsets blocks = [] for id in local_diag_blocks: op00 = A.block(2 * id, 2 * id) op01 = A.block(2 * id, 2 * id + 1) op10 = A.block(2 * id + 1, 2 * id) op11 = A.block(2 * id + 1, 2 * id + 1) op = lib.createBlockedBoundaryOperator( self.__context, [[op00, op01], [op10, op11]]) print "Generate approximate LU for block %(id)i on process %(my_id)i" % { 'id': id, 'my_id': my_id } lu = lib.acaOperatorApproximateLuInverse( op.weakForm().asDiscreteAcaBoundaryOperator(), aca_tol) print "Finished generating approximate LU for block %(id)i on process %(my_id)i" % { 'id': id, 'my_id': my_id } blocks.append({ 'lu': tools.RealOperator(lu), 'start': offsets[id], 'end': offsets[id + 1] }) return blocks
def buildBlockInverses(self,aca_tol): """Generate the Block LU decompositions """ from bempp import tools A = self.__A layers = self.__layers nproc = self.__comm.NumProc() my_id = self.__comm.MyPID() scheduler = self.__scheduler local_diag_blocks = [] if scheduler.has_key(my_id+1): for elem in scheduler[my_id+1]: if elem[0] == elem[1]: local_diag_blocks.append(elem[0]) # Create a vector with index offsets offsets = np.cumsum([0]+[layer['spaces']['ndof'] for layer in layers]) total_time = 0 # Now create the LU blocks and store together with offsets blocks = [] for id in local_diag_blocks: op00 = A.block(2*id,2*id) op01 = A.block(2*id,2*id+1) op10 = A.block(2*id+1,2*id) op11 = A.block(2*id+1,2*id+1) op = lib.createBlockedBoundaryOperator(self.__context,[[op00,op01],[op10,op11]]) print "Generate approximate LU for block %(id)i on process %(my_id)i..." % {'id':id, 'my_id':my_id} tstart = time() lu = lib.acaOperatorApproximateLuInverse(op.weakForm().asDiscreteAcaBoundaryOperator(),aca_tol) tend = time() total_time += tend-tstart print "Finished generating approximate LU for block %(id)i on process %(my_id)i in %(tval)f seconds." % {'id':id, 'my_id':my_id,'tval':tend-tstart} blocks.append({'lu':tools.RealOperator(lu), 'start':offsets[id], 'end':offsets[id+1], 'ndof':offsets[id+1]-offsets[id], 'id': id }) self.__total_time_prec_initialisation = total_time return blocks,local_diag_blocks
def solve_bvp(self,wave_number,rhs): from scipy.sparse.linalg import gmres from bempp.tools import RealOperator self._residuals[wave_number] = [] def evaluate_residual(res): self._residuals[wave_number].append(res) n = len(rhs[0]) rhs_dual = (self._identity*rhs[0].reshape(n,1)).ravel() op_found_in_cache = False if self._operator_cache: try: op = self._boundary_operator_cache(wave_number) op_found_in_cache = True except: pass if not op_found_in_cache: slp_bnd_op = _bempplib.createMaxwell3dSingleLayerBoundaryOperator(self._context,self._space, self._space,self._space, 1.0j*wave_number).weakForm() slp_bnd_op_real = RealOperator(slp_bnd_op) prec = None if self._use_aca_lu_preconditioner: prec = RealOperator(_bempplib.acaOperatorApproximateLuInverse(slp_bnd_op,self._aca_lu_delta)) if self._operator_cache: self._boundary_operator_cache.insert(wave_number,(slp_bnd_op_real,prec)) rhs_dual_real = _np.hstack([_np.real(rhs_dual),_np.imag(rhs_dual)]) sol_real,info = gmres(slp_bnd_op_real,rhs_dual_real,tol=self._gmres_tol,maxiter=self._gmres_max_iter,M=prec,callback=evaluate_residual) if info != 0: raise Exception('GMRES did not converge for wavenumber '+str(wave_number)+'.') sol = sol_real[:n]+1j*sol_real[n:] return [sol.ravel()]
def buildBlockInverses(self,aca_tol): """Generate the Block LU decompositions """ from bempp import tools A = self.__A layers = self.__layers nproc = self.__comm.NumProc() my_id = self.__comm.MyPID() scheduler = partition(procmap(blockmap(graph),nproc)) local_diag_blocks = [] if scheduler.has_key(my_id+1): for elem in scheduler[my_id+1]: if elem[0] == elem[1]: local_diag_blocks.append(elem[0]) # Create a vector with index offsets offsets = np.cumsum([0]+[layer['spaces']['ndof'] for layer in layers]) # Now create the LU blocks and store together with offsets blocks = [] for id in local_diag_blocks: op00 = A.block(2*id,2*id) op01 = A.block(2*id,2*id+1) op10 = A.block(2*id+1,2*id) op11 = A.block(2*id+1,2*id+1) op = lib.createBlockedBoundaryOperator(self.__context,[[op00,op01],[op10,op11]]) print "Generate approximate LU for block %(id)i on process %(my_id)i" % {'id':id, 'my_id':my_id} lu = lib.acaOperatorApproximateLuInverse(op.weakForm().asDiscreteAcaBoundaryOperator(),aca_tol) print "Finished generating approximate LU for block %(id)i on process %(my_id)i" % {'id':id, 'my_id':my_id} blocks.append({'lu':tools.RealOperator(lu), 'start':offsets[id], 'end':offsets[id+1] }) return blocks
def solve_bvp(self,wave_number,rhs): self._residuals[wave_number] = [] def evaluate_residual(res): self._residuals[wave_number].append(res) k_ext = 1.0j*wave_number * _np.sqrt(self._eps_ext * self._mu_ext) k_int = 1.0j*wave_number * _np.sqrt(self._eps_int * self._mu_int) rho = (k_int * self._mu_ext) / (k_ext * self._mu_int) op_found_in_cache = False if self._operator_cache: try: op,prec = self._boundary_operator_cache(wave_number) op_found_in_cache = True except: pass if not op_found_in_cache: context = self._context space = self._space slpOpExt = _bempplib.createMaxwell3dSingleLayerBoundaryOperator( context, space, space, space, k_ext, "SLP_ext") dlpOpExt = _bempplib.createMaxwell3dDoubleLayerBoundaryOperator( context, space, space, space, k_ext, "DLP_ext") slpOpInt = _bempplib.createMaxwell3dSingleLayerBoundaryOperator( context, space, space, space, k_int, "SLP_int") dlpOpInt = _bempplib.createMaxwell3dDoubleLayerBoundaryOperator( context, space, space, space, k_int, "DLP_int") idOp = _bempplib.createMaxwell3dIdentityOperator( context, space, space, space, "Id") # Form the left- and right-hand-side operators lhsOp00 = -(slpOpExt + rho * slpOpInt) lhsOp01 = lhsOp10 = dlpOpExt + dlpOpInt lhsOp11 = slpOpExt + (1. / rho) * slpOpInt lhsOp = _bempplib.createBlockedBoundaryOperator( context, [[lhsOp00, lhsOp01], [lhsOp10, lhsOp11]]) precTol = self._aca_lu_delta invLhsOp00 = _bempplib.acaOperatorApproximateLuInverse( lhsOp00.weakForm().asDiscreteAcaBoundaryOperator(), precTol) invLhsOp11 = _bempplib.acaOperatorApproximateLuInverse( lhsOp11.weakForm().asDiscreteAcaBoundaryOperator(), precTol) prec = _bempplib.discreteBlockDiagonalPreconditioner([invLhsOp00, invLhsOp11]) op = lhsOp # Construct the grid functions representing the traces of the incident field incDirichletTrace = _bempplib.createGridFunction( context, space, space, coefficients=rhs[0]) incNeumannTrace = 1./(1j*k_ext)*_bempplib.createGridFunction( context, space, space, coefficients=rhs[1]) self._inc_dirichlet_traces[wave_number] = incDirichletTrace self._inc_neumann_traces[wave_number] = incNeumannTrace # Construct the right-hand-side grid function rhs = [idOp * incNeumannTrace, idOp * incDirichletTrace] solver = _bempplib.createDefaultIterativeSolver(op) solver.initializeSolver(_bempplib.defaultGmresParameterList(self._gmres_tol), prec) # Solve the equation solution = solver.solve(rhs) print solution.solverMessage() # Extract the solution components in the form of grid functions extDirichletTrace = solution.gridFunction(0) extNeumannTrace = solution.gridFunction(1) if self._operator_cache: self._boundary_operator_cache.insert(wave_number,(op,prec)) scatt_dirichlet_ext_fun = extDirichletTrace - self._inc_dirichlet_traces[wave_number] print "Dirichlet Error "+str(scatt_dirichlet_ext_fun.L2Norm()/extDirichletTrace.L2Norm()) scatt_neumann_ext_fun = extNeumannTrace - self._inc_neumann_traces[wave_number] print "Neumann Error "+str(scatt_neumann_ext_fun.L2Norm()/extNeumannTrace.L2Norm()) return [extDirichletTrace.coefficients(),extNeumannTrace.coefficients()]