コード例 #1
0
    def __init__(self, v, v_out, bcs=None, solver_parameters=None, constant_jacobian=True):

        if isinstance(v, expression.Expression) or \
           not isinstance(v, (ufl.core.expr.Expr, function.Function)):
            raise ValueError("Can only project UFL expression or Functions not '%s'" % type(v))

        self._same_fspace = (isinstance(v, function.Function) and v.function_space() ==
                             v_out.function_space())
        self.v = v
        self.v_out = v_out
        self.bcs = bcs

        if not self._same_fspace or self.bcs:
            V = v_out.function_space()

            p = ufl_expr.TestFunction(V)
            q = ufl_expr.TrialFunction(V)

            a = ufl.inner(p, q)*ufl.dx
            L = ufl.inner(p, v)*ufl.dx

            problem = vs.LinearVariationalProblem(a, L, v_out, bcs=self.bcs,
                                                  constant_jacobian=constant_jacobian)

            if solver_parameters is None:
                solver_parameters = {}

            solver_parameters.setdefault("ksp_type", "cg")

            self.solver = vs.LinearVariationalSolver(problem,
                                                     solver_parameters=solver_parameters)
コード例 #2
0
ファイル: solving.py プロジェクト: kalogirou/firedrake
def _solve_varproblem(*args, **kwargs):
    "Solve variational problem a == L or F == 0"

    # Extract arguments
    eq, u, bcs, J, Jp, M, form_compiler_parameters, \
        solver_parameters, nullspace, nullspace_T, \
        near_nullspace, \
        options_prefix = _extract_args(*args, **kwargs)

    appctx = kwargs.get("appctx", {})
    # Solve linear variational problem
    if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form):

        # Create problem
        problem = vs.LinearVariationalProblem(
            eq.lhs,
            eq.rhs,
            u,
            bcs,
            Jp,
            form_compiler_parameters=form_compiler_parameters)

        # Create solver and call solve
        solver = vs.LinearVariationalSolver(
            problem,
            solver_parameters=solver_parameters,
            nullspace=nullspace,
            transpose_nullspace=nullspace_T,
            near_nullspace=near_nullspace,
            options_prefix=options_prefix,
            appctx=appctx)
        solver.solve()

    # Solve nonlinear variational problem
    else:

        if eq.rhs != 0:
            raise TypeError(
                "Only '0' support on RHS of nonlinear Equation, not %r" %
                eq.rhs)
        # Create problem
        problem = vs.NonlinearVariationalProblem(
            eq.lhs,
            u,
            bcs,
            J,
            Jp,
            form_compiler_parameters=form_compiler_parameters)

        # Create solver and call solve
        solver = vs.NonlinearVariationalSolver(
            problem,
            solver_parameters=solver_parameters,
            nullspace=nullspace,
            transpose_nullspace=nullspace_T,
            near_nullspace=near_nullspace,
            options_prefix=options_prefix,
            appctx=appctx)
        solver.solve()
コード例 #3
0
ファイル: solving.py プロジェクト: jshipton/firedrake
def _solve_varproblem(*args, **kwargs):
    "Solve variational problem a == L or F == 0"

    # Extract arguments
    eq, u, bcs, J, Jp, M, form_compiler_parameters, \
        solver_parameters, nullspace, options_prefix, \
        nest = _extract_args(*args, **kwargs)

    # Solve linear variational problem
    if isinstance(eq.lhs, ufl.Form) and isinstance(eq.rhs, ufl.Form):

        # Create problem
        problem = vs.LinearVariationalProblem(
            eq.lhs,
            eq.rhs,
            u,
            bcs,
            Jp,
            form_compiler_parameters=form_compiler_parameters,
            nest=nest)

        # Create solver and call solve
        solver = vs.LinearVariationalSolver(
            problem,
            solver_parameters=solver_parameters,
            nullspace=nullspace,
            options_prefix=options_prefix)
        with progress(INFO, 'Solving linear variational problem'):
            solver.solve()

    # Solve nonlinear variational problem
    else:

        if eq.rhs != 0:
            raise TypeError(
                "Only '0' support on RHS of nonlinear Equation, not %r" %
                eq.rhs)
        # Create problem
        problem = vs.NonlinearVariationalProblem(
            eq.lhs,
            u,
            bcs,
            J,
            Jp,
            form_compiler_parameters=form_compiler_parameters,
            nest=nest)

        # Create solver and call solve
        solver = vs.NonlinearVariationalSolver(
            problem,
            solver_parameters=solver_parameters,
            nullspace=nullspace,
            options_prefix=options_prefix)
        with progress(INFO, 'Solving nonlinear variational problem'):
            solver.solve()
コード例 #4
0
ファイル: solving.py プロジェクト: jwallwork23/firedrake
def _la_solve(A, x, b, **kwargs):
    r"""Solve a linear algebra problem.

    :arg A: the assembled bilinear form, a :class:`.Matrix`.
    :arg x: the :class:`.Function` to write the solution into.
    :arg b: the :class:`.Function` defining the right hand side values.
    :kwarg solver_parameters: optional solver parameters.
    :kwarg nullspace: an optional :class:`.VectorSpaceBasis` (or
         :class:`.MixedVectorSpaceBasis`) spanning the null space of
         the operator.
    :kwarg transpose_nullspace: as for the nullspace, but used to
         make the right hand side consistent.
    :kwarg near_nullspace: as for the nullspace, but used to add
         the near nullspace.
    :kwarg options_prefix: an optional prefix used to distinguish
         PETSc options.  If not provided a unique prefix will be
         created.  Use this option if you want to pass options
         to the solver from the command line in addition to
         through the ``solver_parameters`` dict.

    .. note::

        This function no longer accepts :class:`.DirichletBC`\s or
        :class:`.EquationBC`\s as arguments.
        Any boundary conditions must be applied when assembling the
        bilinear form as:

        .. code-block:: python

           A = assemble(a, bcs=[bc1])
           solve(A, x, b)

    Example usage:

    .. code-block:: python

        _la_solve(A, x, b, solver_parameters=parameters_dict)."""

    bcs, solver_parameters, nullspace, nullspace_T, near_nullspace, \
        options_prefix = _extract_linear_solver_args(A, x, b, **kwargs)

    if bcs is not None:
        raise RuntimeError(
            "It is no longer possible to apply or change boundary conditions after assembling the matrix `A`; pass any necessary boundary conditions to `assemble` when assembling `A`."
        )

    solver = ls.LinearSolver(A,
                             solver_parameters=solver_parameters,
                             nullspace=nullspace,
                             transpose_nullspace=nullspace_T,
                             near_nullspace=near_nullspace,
                             options_prefix=options_prefix)
    if isinstance(x, firedrake.Vector):
        x = x.function
    # linear MG doesn't need RHS, supply zero.
    lvp = vs.LinearVariationalProblem(a=A.a, L=0, u=x, bcs=A.bcs)
    mat_type = A.mat_type
    appctx = solver_parameters.get("appctx", {})
    ctx = solving_utils._SNESContext(lvp,
                                     mat_type=mat_type,
                                     pmat_type=mat_type,
                                     appctx=appctx,
                                     options_prefix=options_prefix)
    dm = solver.ksp.dm

    with dmhooks.add_hooks(dm, solver, appctx=ctx):
        solver.solve(x, b)
コード例 #5
0
ファイル: pml.py プロジェクト: benSepanski/fd2mm
def pml(mesh,
        scatterer_bdy_id,
        outer_bdy_id,
        wave_number,
        options_prefix=None,
        solver_parameters=None,
        inner_region=None,
        fspace=None,
        tfspace=None,
        true_sol_grad=None,
        pml_type=None,
        delta=None,
        quad_const=None,
        speed=None,
        pml_min=None,
        pml_max=None):
    """
        For unlisted arg descriptions, see run_method

        :arg inner_region: boundary id of non-pml region
        :arg pml_type: Type of pml function, either 'quadratic' or 'bdy_integral'
        :arg delta: For :arg:`pml_type` of 'bdy_integral', added to denominator
                    to prevent 1 / 0 at edge of boundary
        :arg quad_const: For :arg:`pml_type` of 'quadratic', a scaling constant
        :arg speed: Speed of sound
        :arg pml_min: A list, *pml_min[i]* is where to begin pml layer in direction
                      *i*
        :arg pml_max: A list, *pml_max[i]* is where to end pml layer in direction *i*
    """
    # Handle defauls
    if pml_type is None:
        pml_type = 'bdy_integral'
    if delta is None:
        delta = 1e-3
    if quad_const is None:
        quad_const = 1.0
    if speed is None:
        speed = 340.0

    pml_types = ['bdy_integral', 'quadratic']
    if pml_type not in pml_types:
        raise ValueError("PML type of %s is not one of %s" %
                         (pml_type, pml_types))

    xx = SpatialCoordinate(mesh)
    # {{{ create sigma functions for PML
    sigma = None
    if pml_type == 'bdy_integral':
        sigma = [
            Constant(speed) / (Constant(delta + extent) - abs(coord))
            for extent, coord in zip(pml_max, xx)
        ]
    elif pml_type == 'quadratic':
        sigma = [
            Constant(quad_const) * (abs(coord) - Constant(min_))**2
            for min_, coord in zip(pml_min, xx)
        ]
    r"""
        Here \kappa is the wave number and c is the speed

        ..math::

        \kappa = \frac{ \omega } { c }
    """
    omega = wave_number * speed

    # {{{ Set up PML functions
    gamma = [
        Constant(1.0) + conditional(
            abs(real(coord)) >= real(min_),
            Constant(1j / omega) * sigma_i, Constant(0.0))
        for min_, coord, sigma_i in zip(pml_min, xx, sigma)
    ]

    kappa = [None] * len(gamma)
    gamma_prod = 1.0
    for i in range(len(gamma)):
        gamma_prod *= gamma[i]
        tensor_i = [Constant(0.0) for _ in range(len(gamma))]
        tensor_i[i] = 1.0
        r"""
            *i*th entry is

            .. math::

            \frac{\prod_{j\neq i} \gamma_j}{ \gamma_i }
        """
        for j in range(len(gamma)):
            if j != i:
                tensor_i[i] *= gamma[j]
            else:
                tensor_i[i] /= gamma[j]
        kappa[i] = tensor_i

    kappa = as_tensor(kappa)

    # }}}

    p = TrialFunction(fspace)
    q = TestFunction(fspace)

    k = wave_number  # Just easier to look at
    a = (inner(dot(grad(p), kappa), grad(q)) -
         Constant(k**2) * gamma_prod * inner(p, q)) * dx

    n = FacetNormal(mesh)
    L = inner(dot(true_sol_grad, n), q) * ds(scatterer_bdy_id)

    bc = DirichletBC(fspace, Constant(0), outer_bdy_id)

    solution = Function(fspace)

    #solve(a == L, solution, bcs=[bc], options_prefix=options_prefix)
    # Create a solver and return the KSP object with the solution so that can get
    # PETSc information
    # Create problem
    problem = vs.LinearVariationalProblem(a, L, solution, [bc], None)
    # Create solver and call solve
    solver = vs.LinearVariationalSolver(problem,
                                        solver_parameters=solver_parameters,
                                        options_prefix=options_prefix)
    solver.solve()

    return solver.snes, solution
コード例 #6
0
ファイル: solving.py プロジェクト: zhoubing34/firedrake
def _la_solve(A, x, b, **kwargs):
    r"""Solve a linear algebra problem.

    :arg A: the assembled bilinear form, a :class:`.Matrix`.
    :arg x: the :class:`.Function` to write the solution into.
    :arg b: the :class:`.Function` defining the right hand side values.
    :kwarg bcs: an optional list of :class:`.DirichletBC`\s to apply.
    :kwarg solver_parameters: optional solver parameters.
    :kwarg nullspace: an optional :class:`.VectorSpaceBasis` (or
         :class:`.MixedVectorSpaceBasis`) spanning the null space of
         the operator.
    :kwarg transpose_nullspace: as for the nullspace, but used to
         make the right hand side consistent.
    :kwarg near_nullspace: as for the nullspace, but used to add
         the near nullspace.
    :kwarg options_prefix: an optional prefix used to distinguish
         PETSc options.  If not provided a unique prefix will be
         created.  Use this option if you want to pass options
         to the solver from the command line in addition to
         through the ``solver_parameters`` dict.

    .. note::

        Any boundary conditions passed in as an argument here override the
        boundary conditions set when the bilinear form was assembled.
        That is, in the following example:

        .. code-block:: python

           A = assemble(a, bcs=[bc1])
           solve(A, x, b, bcs=[bc2])

        the boundary conditions in `bc2` will be applied to the problem
        while `bc1` will be ignored.

    Example usage:

    .. code-block:: python

        _la_solve(A, x, b, solver_parameters=parameters_dict)."""

    bcs, solver_parameters, nullspace, nullspace_T, near_nullspace, \
        options_prefix = _extract_linear_solver_args(A, x, b, **kwargs)
    if bcs is not None:
        A.bcs = bcs

    solver = ls.LinearSolver(A, solver_parameters=solver_parameters,
                             nullspace=nullspace,
                             transpose_nullspace=nullspace_T,
                             near_nullspace=near_nullspace,
                             options_prefix=options_prefix)

    if isinstance(x, firedrake.Vector):
        x = x.function
    # linear MG doesn't need RHS, supply zero.
    lvp = vs.LinearVariationalProblem(a=A.a, L=0, u=x, bcs=bcs)
    mat_type = A.mat_type
    appctx = solver_parameters.get("appctx", {})
    ctx = solving_utils._SNESContext(lvp,
                                     mat_type=mat_type,
                                     pmat_type=mat_type,
                                     appctx=appctx,
                                     options_prefix=options_prefix)
    dm = solver.ksp.dm

    with dmhooks.appctx(dm, ctx):
        solver.solve(x, b)
コード例 #7
0
def transmission(
    mesh,
    scatterer_bdy_id,
    outer_bdy_id,
    wave_number,
    options_prefix=None,
    solver_parameters=None,
    fspace=None,
    true_sol_grad_expr=None,
):
    r"""
        preconditioner_gamma and preconditioner_lambda are used to precondition
        with the following equation:

        \Delta u - \kappa^2 \gamma u = 0
        (\partial_n - i\kappa\beta) u |_\Sigma = 0
    """
    # need as tuple so can use integral measure
    if isinstance(outer_bdy_id, int):
        outer_bdy_id = [outer_bdy_id]
    outer_bdy_id = tuple(outer_bdy_id)

    u = TrialFunction(fspace)
    v = TestFunction(fspace)
    a = inner(grad(u), grad(v)) * dx - Constant(wave_number**2) * inner(u, v) * dx \
        - Constant(1j * wave_number) * inner(u, v) * ds(outer_bdy_id)

    n = FacetNormal(mesh)
    metadata = {'quadrature_degree': 2 * fspace.ufl_element().degree()}
    L = inner(inner(true_sol_grad_expr, n), v) * ds(scatterer_bdy_id,
                                                    metadata=metadata)

    solution = Function(fspace)

    #       {{{ Used for preconditioning
    if 'gamma' in solver_parameters or 'beta' in solver_parameters:
        solver_params = dict(solver_parameters)
        gamma = complex(solver_parameters.pop('gamma', 1.0))

        import cmath
        beta = complex(solver_parameters.pop('beta', cmath.sqrt(gamma)))

        aP = inner(grad(u), grad(v)) * dx \
            - Constant(wave_number**2 * gamma) * inner(u, v) * dx \
            - Constant(1j * wave_number * beta) * inner(u, v) * ds(outer_bdy_id)
    else:
        aP = None
        solver_params = solver_parameters
    #       }}}

    # prepare to set up pyamg preconditioner if using it
    using_pyamg = solver_params['pc_type'] == 'pyamg'
    if using_pyamg:
        pyamg_tol = solver_parameters.get('pyamg_tol', None)
        if pyamg_tol is not None:
            pyamg_tol = float(pyamg_tol)
        pyamg_maxiter = solver_params.get('pyamg_maxiter', None)
        if pyamg_maxiter is not None:
            pyamg_maxiter = int(pyamg_maxiter)
        del solver_params['pc_type']

    # Create a solver and return the KSP object with the solution so that can get
    # PETSc information
    # Create problem
    problem = vs.LinearVariationalProblem(a, L, solution, aP=aP)

    # Create solver and call solve
    solver = vs.LinearVariationalSolver(problem,
                                        solver_parameters=solver_params,
                                        options_prefix=options_prefix)
    # prepare to set up pyamg preconditioner if using it
    if using_pyamg:
        A = assemble(a).M.handle
        pc = solver.snes.getKSP().pc
        pc.setType(pc.Type.PYTHON)
        pc.setPythonContext(
            AMGTransmissionPreconditioner(wave_number,
                                          fspace,
                                          A,
                                          tol=pyamg_tol,
                                          maxiter=pyamg_maxiter,
                                          use_plane_waves=True))

    # If using pyamg as preconditioner, use it!
    try:
        solver.solve()
    except ConvergenceError:
        pass

    return solver.snes, solution
コード例 #8
0
wave_number = 0.1  # one of [0.1, 1.0, 5.0, 10.0]
true_sol = get_true_sol_expr(SpatialCoordinate(mesh), wave_number)

a = inner(grad(u), grad(v)) * dx \
    - Constant(wave_number**2) * inner(u, v) * dx \
    - Constant(1j * wave_number) * inner(u, v) * ds(outer_bdy_id)

n = FacetNormal(mesh)
L = inner(inner(grad(true_sol), n), v) * ds(scatterer_bdy_id)

solution = Function(fspace)

# Create a solver and return the KSP object with the solution so that can get
# PETSc information
# Create problem
problem = vs.LinearVariationalProblem(a, L, solution)

# Create solver
pyamg_tol = None
pyamg_maxiter = None
solver_params = {
    'pyamg_tol': pyamg_tol,
    'pyamg_maxiter': pyamg_maxiter,
    'ksp_monitor': None,
}
solver = vs.LinearVariationalSolver(problem, solver_parameters=solver_params)

# Build matrix and store text file
A = assemble(a).M.handle
store_mat = True
if store_mat: