def _assign_solvers(self): mat, ind = self._obtain_submatrix() all_ind = np.arange(self.rhs.size) not_ind = [np.setdiff1d(all_ind, i) for i in ind] factory = LSFactory() num_mat = len(mat) solvers = np.empty(num_mat, dtype=np.object) for i, A in enumerate(mat): sz = A.shape[0] if sz < 5000: solvers[i] = factory.direct(A) else: # amg solver is pyamg is installed, if not ilu try: solvers[i] = factory.amg(A, as_precond=True) except ImportError: solvers[i] = factory.ilu(A) return solvers, ind, not_ind
def solve(self, max_direct=40000, callback=False, **kwargs): """ This is an adaption of the elliptic solver to the Schur complement elimination. The only change can be found in the if self.el statement. """ # Discretize tic = time.time() logger.info('Discretize') self.lhs, self.rhs = self.reassemble() if self.el: to_be_eliminated = SC.dofs_of_dimension(other.grid(), other.lhs, eldim) self.lhs, self.rhs, _, _, _ = SC.eliminate_dofs( other.lhs, other.rhs, to_be_eliminated) logger.info('Done. Elapsed time ' + str(time.time() - tic)) # Solve tic = time.time() ls = LSFactory() if self.rhs.size < max_direct: logger.info('Solve linear system using direct solver') self.x = ls.direct(self.lhs, self.rhs) else: logger.info('Solve linear system using GMRES') precond = self._setup_preconditioner() # precond = ls.ilu(self.lhs) slv = ls.gmres(self.lhs) self.x, info = slv(self.rhs, M=precond, callback=callback, maxiter=10000, restart=1500, tol=1e-8) if info == 0: logger.info('GMRES succeeded.') else: logger.error('GMRES failed with status ' + str(info)) logger.info('Done. Elapsed time ' + str(time.time() - tic)) return self.x
def solve(self, max_direct=40000, callback=False, **kwargs): """ Reassemble and solve linear system. After the funtion has been called, the attributes lhs and rhs are updated according to the parameter states. Also, the attribute x gives the pressure given the current state. TODO: Provide an option to save solver information if multiple systems are to be solved with the same left hand side. The function attempts to set up the best linear solver based on the system size. The setup and parameter choices here are still experimental. Parameters: max_direct (int): Maximum number of unknowns where a direct solver is applied. If a direct solver can be applied this is usually the most efficient option. However, if the system size is too large compared to available memory, a direct solver becomes extremely slow. callback (boolean, optional): If True iteration information will be output when an iterative solver is applied (system size larger than max_direct) Returns: np.array: Pressure state. """ logger.error("Solve elliptic model") # Discretize tic = time.time() logger.warning("Discretize") self.lhs, self.rhs = self.reassemble() logger.warning("Done. Elapsed time " + str(time.time() - tic)) # Solve tic = time.time() ls = LSFactory() if self.rhs.size < max_direct: logger.warning("Solve linear system using direct solver") self.x = ls.direct(self.lhs, self.rhs) else: logger.warning("Solve linear system using GMRES") precond = self._setup_preconditioner() # precond = ls.ilu(self.lhs) slv = ls.gmres(self.lhs) self.x, info = slv( self.rhs, M=precond, callback=callback, maxiter=10000, restart=1500, tol=1e-8, ) if info == 0: logger.warning("GMRES succeeded.") else: logger.warning("GMRES failed with status " + str(info)) logger.warning("Done. Elapsed time " + str(time.time() - tic)) return self.x
def solve(self, max_direct=40000, callback=False, discretize=True, **kwargs): """ Reassemble and solve linear system. After the funtion has been called, the attributes lhs and rhs are updated according to the parameter states. Also, the attribute x gives the pressure given the current state. The function attempts to set up the best linear solver based on the system size. The setup and parameter choices here are still experimental. Parameters: max_direct (int): Maximum number of unknowns where a direct solver is applied. If a direct solver can be applied this is usually the most efficient option. However, if the system size is too large compared to available memory, a direct solver becomes extremely slow. callback (boolean, optional): If True iteration information will be output when an iterative solver is applied (system size larger than max_direct) Returns: np.array: Pressure state. """ # Discretize tic = time.time() if discretize: logger.info('Discretize') self.lhs, self.rhs = self.reassemble(**kwargs) self.is_factorized = False logger.info('Done. Elapsed time ' + str(time.time() - tic)) else: self.rhs = self._stress_disc.rhs(self.grid(), self.data()) # Solve tic = time.time() ls = LSFactory() if self.rhs.size < max_direct: logger.info('Solve linear system using direct solver') if not self.is_factorized: logger.info('Making LU decomposition') self.lhs = self.lhs.tocsc() self.lhs = sps.linalg.factorized(self.lhs) self.is_factorized = True logger.info('Done. Elapsed time ' + str(time.time() - tic)) logger.info('Solve linear system using direct solver') tic = time.time() self.x = self.lhs(self.rhs) else: logger.info('Solve linear system using GMRES') precond = self._setup_preconditioner() # precond = ls.ilu(self.lhs) slv = ls.gmres(self.lhs) self.x, info = slv(self.rhs, M=precond, callback=callback, maxiter=10000, restart=1500, tol=1e-8) if info == 0: logger.info('GMRES succeeded.') else: logger.error('GMRES failed with status ' + str(info)) logger.info('Done. Elapsed time ' + str(time.time() - tic)) return self.x