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
Beispiel #4
0
    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    
Beispiel #6
0
    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()]