def direct_solve(A, b, W, which='umfpack'): '''inv(A)*b''' print 'Solving system of size %d' % A.size(0) # NOTE: umfpack sometimes blows up, MUMPS produces crap more often than not if isinstance(W, list): wh = ii_Function(W) LUSolver(which).solve(A, wh.vector(), b) print('|b-Ax| from direct solver', (A * wh.vector() - b).norm('linf')) return wh wh = Function(W) LUSolver(which).solve(A, wh.vector(), b) print('|b-Ax| from direct solver', (A * wh.vector() - b).norm('linf')) if isinstance( W.ufl_element(), (ufl.VectorElement, ufl.TensorElement)) or W.num_sub_spaces() == 1: return ii_Function([W], [wh]) # Now get components Wblock = serialize_mixed_space(W) wh = wh.split(deepcopy=True) return ii_Function(Wblock, wh)
def main(module_name, ncases, params, petsc_params): ''' Run the test case in module with ncases. Optionally store results in savedir. For some modules there are multiple (which) choices of preconditioners. ''' # Unpack for k, v in params.items(): exec(k + '=v', locals()) RED = '\033[1;37;31m%s\033[0m' print RED % ('\tRunning %s' % module_name) module = __import__(module_name) # no importlib in python2.7 # Setup the MMS case u_true, rhs_data = module.setup_mms(eps) # Setup the convergence monitor if log: params = [('solver', solver), ('precond', str(precond)), ('eps', str(eps))] path = '_'.join([module_name] + ['%s=%s' % pv for pv in params]) path = os.path.join(save_dir if save_dir else '.', path) path = '.'.join([path, 'txt']) else: path = '' memory, residuals = [], [] monitor = module.setup_error_monitor(u_true, memory, path=path) # Sometimes it is usedful to transform the solution before computing # the error. e.g. consider subdomains if hasattr(module, 'setup_transform'): # NOTE: transform take two args for case and the current computed # solution transform = module.setup_transform else: transform = lambda i, x: x print '=' * 79 print '\t\t\tProblem eps = %g' % eps print '=' * 79 for i in ncases: a, L, W = module.setup_problem(i, rhs_data, eps=eps) # Assemble blocks t = Timer('assembly') t.start() AA, bb = map(ii_assemble, (a, L)) print '\tAssembled blocks in %g s' % t.stop() wh = ii_Function(W) if solver == 'direct': # Turn into a (monolithic) PETScMatrix/Vector t = Timer('conversion') t.start() AAm, bbm = map(ii_convert, (AA, bb)) print '\tConversion to PETScMatrix/Vector took %g s' % t.stop() t = Timer('solve') t.start() LUSolver('umfpack').solve(AAm, wh.vector(), bbm) print '\tSolver took %g s' % t.stop() niters = 1 else: # Here we define a Krylov solver using PETSc BB = module.setup_preconditioner(W, precond, eps=eps) ## AA and BB as block_mat ksp = PETSc.KSP().create() # Default is minres if '-ksp_type' not in petsc_params: petsc_params['-ksp_type'] = 'minres' opts = PETSc.Options() for key, value in petsc_params.iteritems(): opts.setValue(key, None if value == 'none' else value) ksp.setOperators(ii_PETScOperator(AA)) ksp.setNormType(PETSc.KSP.NormType.NORM_PRECONDITIONED) # ksp.setTolerances(rtol=1E-6, atol=None, divtol=None, max_it=300) ksp.setConvergenceHistory() # We attach the wrapped preconditioner defined by the module ksp.setPC(ii_PETScPreconditioner(BB, ksp)) ksp.setFromOptions() print ksp.getTolerances() # Want the iterations to start from random wh.block_vec().randomize() # Solve, note the past object must be PETSc.Vec t = Timer('solve') t.start() ksp.solve(as_petsc_nest(bb), wh.petsc_vec()) print '\tSolver took %g s' % t.stop() niters = ksp.getIterationNumber() residuals.append(ksp.getConvergenceHistory()) # Let's check the final size of the residual r_norm = (bb - AA * wh.block_vec()).norm() # Convergence? monitor.send((transform(i, wh), niters, r_norm)) # Only send the final if save_dir: path = os.path.join(save_dir, module_name) for i, wh_i in enumerate(wh): # Renaming to make it easier to save state in Visit/Pareview wh_i.rename('u', str(i)) File('%s_%d.pvd' % (path, i)) << wh_i # Plot relative residual norm if plot: plt.figure() [ plt.semilogy(res / res[0], label=str(i)) for i, res in enumerate(residuals, 1) ] plt.legend(loc='best') plt.show()
def main(module_name, ncases, params, petsc_params): ''' Run the test case in module with ncases. Optionally store results in savedir. For some modules there are multiple (which) choices of preconditioners. ''' # Unpack for k, v in params.items(): exec(k + '=v', locals()) RED = '\033[1;37;31m%s\033[0m' print RED % ('\tRunning %s with %d preconditioner' % (module_name, precond)) module = __import__(module_name) # no importlib in python2.7 # Setup the MMS case u_true, rhs_data = module.setup_mms(eps) # Setup the convergence monitor if log: params = [('solver', solver), ('precond', str(precond)), ('eps', str(eps))] path = '_'.join([module_name] + ['%s=%s' % pv for pv in params]) path = os.path.join(save_dir if save_dir else '.', path) path = '.'.join([path, 'txt']) else: path = '' memory, residuals = [], [] monitor = module.setup_error_monitor(u_true, memory, path=path) # Sometimes it is usedful to transform the solution before computing # the error. e.g. consider subdomains if hasattr(module, 'setup_transform'): # NOTE: transform take two args for case and the current computed # solution transform = module.setup_transform else: transform = lambda i, x: x print '='*79 print '\t\t\tProblem eps = %r' % eps print '='*79 for i in ncases: a, L, W = module.setup_problem(i, rhs_data, eps=eps) # Assemble blocks t = Timer('assembly'); t.start() AA, bb = map(ii_assemble, (a, L)) print '\tAssembled blocks in %g s' % t.stop() # Check the symmetry wh = ii_Function(W) assert (AA*wh.block_vec() - (AA.T)*wh.block_vec()).norm() < 1E-10 if solver == 'direct': # Turn into a (monolithic) PETScMatrix/Vector t = Timer('conversion'); t.start() AAm, bbm = map(ii_convert, (AA, bb)) print '\tConversion to PETScMatrix/Vector took %g s' % t.stop() t = Timer('solve'); t.start() LUSolver('umfpack').solve(AAm, wh.vector(), bbm) print '\tSolver took %g s' % t.stop() niters = 1 if solver == 'iterative': # Here we define a Krylov solver using PETSc BB = module.setup_preconditioner(W, precond, eps=eps) ## AA and BB as block_mat ksp = PETSc.KSP().create() # Default is minres if '-ksp_type' not in petsc_params: petsc_params['-ksp_type'] = 'minres' opts = PETSc.Options() for key, value in petsc_params.iteritems(): opts.setValue(key, None if value == 'none' else value) ksp.setOperators(ii_PETScOperator(AA)) ksp.setNormType(PETSc.KSP.NormType.NORM_PRECONDITIONED) # ksp.setTolerances(rtol=1E-6, atol=None, divtol=None, max_it=300) ksp.setConvergenceHistory() # We attach the wrapped preconditioner defined by the module ksp.setPC(ii_PETScPreconditioner(BB, ksp)) ksp.setFromOptions() print ksp.getTolerances() # Want the iterations to start from random wh.block_vec().randomize() # Solve, note the past object must be PETSc.Vec t = Timer('solve'); t.start() ksp.solve(as_petsc_nest(bb), wh.petsc_vec()) print '\tSolver took %g s' % t.stop() niters = ksp.getIterationNumber() residuals.append(ksp.getConvergenceHistory()) # Let's check the final size of the residual r_norm = (bb - AA*wh.block_vec()).norm() # Convergence? monitor.send((transform(i, wh), W, niters, r_norm)) # Only send the final if save_dir: path = os.path.join(save_dir, module_name) for i, wh_i in enumerate(wh): # Renaming to make it easier to save state in Visit/Pareview wh_i.rename('u', str(i)) File('%s_%d.pvd' % (path, i)) << wh_i # Plot relative residual norm if plot: plt.figure() [plt.semilogy(res/res[0], label=str(i)) for i, res in enumerate(residuals, 1)] plt.legend(loc='best') plt.show()
def get_iters(A, b, B, W, Z=None, params=params): ''' Solution and iters A: W->W', B:W'->W, b\in W' ''' ## AA and BB as block_mat ksp = PETSc.KSP().create() ksp.setConvergenceHistory() ksp.setNormType(PETSc.KSP.NormType.NORM_PRECONDITIONED) compute_eigs = params['-ksp_type'] == 'cg' if compute_eigs: ksp.setComputeEigenvalues(1) else: ksp.setComputeEigenvalues(0) if isinstance(W, list): # The problem should always be symmetric y = A.create_vec() y = randomize(y) if params['-ksp_type'] == 'minres': Ay = A * y # At_y = (A.T)*y # assert (Ay - At_y).norm() < 1E-6*sum(yi.size() for yi in y), (Ay - At_y).norm() ksp.setOperators(ii_PETScOperator(A, Z)) # Wrap block_mat ksp.setPC(ii_PETScPreconditioner(B, ksp)) # Wrapped block_op wh = ii_Function(W) # Want the iterations to start from random wh.block_vec().randomize() # User configs opts = PETSc.Options() for key, value in params.iteritems(): opts.setValue(key, None if value == 'none' else value) ksp.setFromOptions() Z is not None and Z.orthogonalize(wh.block_vec()) # Time the solver timer = Timer('solver') Z is not None and Z.orthogonalize(b) ksp.solve(as_petsc_nest(b), wh.petsc_vec()) ksp_time = timer.stop() else: pc_config, Bmat = B # A for syste, B for preconditioner ksp.setOperators(as_backend_type(A).mat(), Bmat) # Now config pc = ksp.getPC() pc_options = pc_config(pc) params.update(pc_options) opts = PETSc.Options() # Database + user options for key, value in params.iteritems(): opts.setValue(key, None if value == 'none' else value) # Apply pc.setFromOptions() ksp.setFromOptions() wh = Function(W) x = as_backend_type(wh.vector()) x.set_local(np.random.rand(x.local_size())) timer = Timer('solver') ksp.solve(as_backend_type(b).vec(), x.vec()) ksp_time = timer.stop() if isinstance(W.ufl_element(), (ufl.VectorElement, ufl.TensorElement)) or W.num_sub_spaces() == 1: wh = ii_Function([W], [wh]) else: # Now get components Wblock = serialize_mixed_space(W) wh = wh.split(deepcopy=True) wh = ii_Function(Wblock, wh) # Done niters = ksp.getIterationNumber() residuals = ksp.getConvergenceHistory() if compute_eigs: eigs = np.abs(ksp.computeEigenvalues()) cond = np.max(eigs) / np.min(eigs) else: cond = -1 return cond, ksp_time, niters, residuals, wh