예제 #1
0
파일: utils.py 프로젝트: MiroK/emi-book-fem
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)
예제 #2
0
    def __init__(self, *args, **kwargs):
        """
        Create solver for
        :py:class:`SemiDecoupled <muflon.functions.discretization.SemiDecoupled>`
        discretization scheme.

        See :py:class:`Solver <muflon.solving.solvers.Solver>` for the list of
        valid initialization arguments.
        """
        super(SemiDecoupled, self).__init__(*args, **kwargs)

        # Extract solution functions
        DS = self.data["model"].discretization_scheme()
        w_ch, w_ns = DS.solution_ctl()

        # Adjust bcs
        bcs_ch = []
        bcs_ns = []
        _bcs = self.data["model"].bcs()
        for bc_v in _bcs.get("v", []):
            assert isinstance(bc_v, tuple)
            assert len(bc_v) == len(w_ns.sub(0))
            bcs_ns += [bc for bc in bc_v if bc is not None]
        bcs_ns += [bc for bc in _bcs.get("p", [])]
        # FIXME: Deal with possible bcs for ``phi`` and ``th``

        # Prepare solver for CH part
        F = self.data["forms"]["nln"]
        J = derivative(F, w_ch)

        # Store solvers and collect other data
        self.data["problem_ch"] = self.CHProblem(F, bcs_ch, J)
        self.data["solver"] = OrderedDict()
        self.data["solver"]["CH"] = OrderedDict()
        self.data["solver"]["CH"]["lin"] = LUSolver("mumps")
        # NOTE: Initialization of nonlinear solver is postponed until setup
        self.data["solver"]["NS"] = LUSolver("mumps")
        self.data["sol_ch"] = w_ch
        self.data["sol_ns"] = w_ns
        self.data["bcs_ns"] = bcs_ns

        # Preparation for tackling singular systems
        if self._flags["fix_p"]:
            null_space, null_fcn = DS.build_pressure_null_space()
            self.data["null_space"] = null_space
            self.data["null_fcn"] = null_fcn

        # Store number of iterations
        self.iters = OrderedDict()
        self.iters["CH"] = [0, 0]  # (total, last solve)
        self.iters["NS"] = [0, 0]  # (total, last solve)
예제 #3
0
    def solve_alpha_M_beta_F(self, alpha, beta, b, t):
        """Solve  :code:`alpha * M * u + beta * F(u, t) = b`  with Dirichlet
        conditions.
        """
        matrix = alpha * self.M + beta * self.A

        # See above for float conversion
        right_hand_side = -float(beta) * self.b.copy()
        if b:
            right_hand_side += b

        for bc in self.dirichlet_bcs:
            bc.apply(matrix, right_hand_side)

        # TODO proper preconditioner for convection
        if self.convection:
            # Use HYPRE-Euclid instead of ILU for parallel computation.
            # However, this PC sometimes fails.
            # solver = KrylovSolver('gmres', 'hypre_euclid')
            # Fallback:
            solver = LUSolver()
        else:
            solver = KrylovSolver("gmres", "hypre_amg")
            solver.parameters["relative_tolerance"] = 1.0e-13
            solver.parameters["absolute_tolerance"] = 0.0
            solver.parameters["maximum_iterations"] = 100
            solver.parameters["monitor_convergence"] = True

        solver.set_operator(matrix)

        u = Function(self.Q)
        solver.solve(u.vector(), right_hand_side)
        return u
예제 #4
0
파일: solves.py 프로젝트: pdelab/pyeafe
def assert_solves(
    mesh: Mesh,
    diffusion: Coefficient,
    convection: Optional[Coefficient],
    reaction: Optional[Coefficient],
    source: Coefficient,
    exact: Coefficient,
    l2_tol: Optional[float] = 1.0e-8,
    h1_tol: Optional[float] = 1.0e-6,
):
    eafe_matrix = eafe_assemble(mesh, diffusion, convection, reaction)

    pw_linears = FunctionSpace(mesh, "Lagrange", 1)
    test_function = TestFunction(pw_linears)
    rhs_vector = assemble(source * test_function * dx)

    bc = DirichletBC(pw_linears, exact, lambda _, on_bndry: on_bndry)
    bc.apply(eafe_matrix, rhs_vector)

    solution = Function(pw_linears)
    solver = LUSolver(eafe_matrix, "default")
    solver.parameters["symmetric"] = False
    solver.solve(solution.vector(), rhs_vector)

    l2_err: float = errornorm(exact, solution, "l2", 3)
    assert l2_err <= l2_tol, f"L2 error too large: {l2_err} > {l2_tol}"

    h1_err: float = errornorm(exact, solution, "H1", 3)
    assert h1_err <= h1_tol, f"H1 error too large: {h1_err} > {h1_tol}"
예제 #5
0
    def _get_constant_pressure(self, W):
        w = TrialFunction(W)
        w_ = TestFunction(W)
        p_ = self.test_functions()["p"]
        A, b = assemble_system(inner(w, w_) * dx, p_ * dx)
        null_fcn = Function(W)
        solver = LUSolver("mumps")
        solver.solve(A, null_fcn.vector(), b)

        return null_fcn
예제 #6
0
    def __init__(self, *args, **kwargs):
        """
        Create linear solver for :py:class:`FullyDecoupled \
        <muflon.functions.discretization.FullyDecoupled>`
        discretization scheme.

        See :py:class:`Solver <muflon.solving.solvers.Solver>` for the list of
        valid initialization arguments.
        """
        super(FullyDecoupled, self).__init__(*args, **kwargs)

        # Create solvers
        solver = OrderedDict()
        solver["phi"] = LUSolver("mumps")
        solver["chi"] = LUSolver("mumps")
        solver["v"] = LUSolver("mumps")
        solver["p"] = LUSolver("mumps")
        self.data["solver"] = solver

        # Initialize flags
        self._flags["setup"] = False
예제 #7
0
 def _assemble(self):
     # Get input:
     self.gamma = self.Parameters['gamma']
     if self.Parameters.has_key('beta'): self.beta = self.Parameters['beta']
     else: self.beta = 0.0
     self.Vm = self.Parameters['Vm']
     if self.Parameters.has_key('m0'):
         self.m0 = self.Parameters['m0'].copy(deepcopy=True)
         isFunction(self.m0)
     else:
         self.m0 = Function(self.Vm)
     self.mtrial = TrialFunction(self.Vm)
     self.mtest = TestFunction(self.Vm)
     self.mysample = Function(self.Vm)
     self.draw = Function(self.Vm)
     # Assemble:
     self.R = assemble(inner(nabla_grad(self.mtrial), \
     nabla_grad(self.mtest))*dx)
     self.M = PETScMatrix()
     assemble(inner(self.mtrial, self.mtest) * dx, tensor=self.M)
     # preconditioner is Gamma^{-1}:
     if self.beta > 1e-16:
         self.precond = self.gamma * self.R + self.beta * self.M
     else:
         self.precond = self.gamma * self.R + (1e-14) * self.M
     # Discrete operator K:
     self.K = self.gamma * self.R + self.beta * self.M
     # Get eigenvalues for M:
     self.eigsolM = SLEPcEigenSolver(self.M)
     self.eigsolM.solve()
     # Solver for M^{-1}:
     self.solverM = LUSolver()
     self.solverM.parameters['reuse_factorization'] = True
     self.solverM.parameters['symmetric'] = True
     self.solverM.set_operator(self.M)
     # Solver for K^{-1}:
     self.solverK = LUSolver()
     self.solverK.parameters['reuse_factorization'] = True
     self.solverK.parameters['symmetric'] = True
     self.solverK.set_operator(self.K)
예제 #8
0
 def setUp(self):
     mesh = UnitSquareMesh(5, 5, 'crossed')
     self.V = FunctionSpace(mesh, 'Lagrange', 5)
     self.u = Function(self.V)
     self.uM = Function(self.V)
     self.uMdiag = Function(self.V)
     test = TestFunction(self.V)
     trial = TrialFunction(self.V)
     m = test * trial * dx
     self.M = assemble(m)
     self.solver = LUSolver()
     self.solver.parameters['reuse_factorization'] = True
     self.solver.parameters['symmetric'] = True
     self.solver.set_operator(self.M)
     self.ones = np.ones(self.V.dim())
예제 #9
0
파일: heat.py 프로젝트: nschloe/flow
    def solve_alpha_M_beta_F(self, alpha, beta, b, t):
        '''Solve  alpha * M * u + beta * F(u, t) = b  for u.
        '''
        A = alpha * self.M + beta * self.A

        # See above for float conversion
        right_hand_side = - float(beta) * self.b.copy()
        if b:
            right_hand_side += b

        for bc in self.bcs:
            bc.apply(A, b)

        # The Krylov solver doesn't converge
        solver = LUSolver()
        solver.set_operator(A)

        u = Function(self.V)
        solver.solve(u.vector(), b)
        return u
예제 #10
0
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()