コード例 #1
0
def get_dwr_indicator(F, adjoint_error, test_space=None):
    """
    Generate a dual weighted residual (DWR)
    error indicator, given a form and an
    approximation of the error in the adjoint
    solution.

    :arg F: the form
    :arg adjoint_error: the approximation to
        the adjoint error, either as a single
        :class:`Function`, or in a dictionary
    :kwarg test_space: the :class:`FunctionSpace`
        that the test function lives in, or an
        appropriate dictionary
    """
    mapping = {}
    if isinstance(adjoint_error, firedrake.Function):
        fs = test_space or adjoint_error.function_space()
        if F.ufl_domain() != fs.mesh():
            raise ValueError(
                "Meshes underlying the form and adjoint error do not match.")
        mapping[firedrake.TestFunction(fs)] = adjoint_error
    else:
        if test_space is None:
            test_space = {
                key: firedrake.TestFunction(err.function_space())
                for key, err in adjoint_error.items()
            }
        for key, err in adjoint_error.items():
            if F.ufl_domain() != test_space[key].mesh():
                raise ValueError(
                    "Meshes underlying the form and adjoint error do not match."
                )
            mapping[firedrake.TestFunction(test_space[key])] = err
    return form2indicator(ufl.replace(F, mapping))
コード例 #2
0
    def __init__(self, mesh_r):
        # Create mesh_r and V_r
        self.mesh_r = mesh_r
        element = self.mesh_r.coordinates.function_space().ufl_element()
        self.V_r = fd.FunctionSpace(self.mesh_r, element)

        # Create self.id and self.T, self.mesh_m, and self.V_m.
        X = fd.SpatialCoordinate(self.mesh_r)
        self.id = fd.interpolate(X, self.V_r)
        self.T = fd.Function(self.V_r, name="T")
        self.T.assign(self.id)
        self.mesh_m = fd.Mesh(self.T)
        self.V_m = fd.FunctionSpace(self.mesh_m, element)
        self.is_DG = False

        """
        ControlSpace for discontinuous coordinate fields
        (e.g.  periodic domains)

        In Firedrake, periodic meshes are implemented using a discontinuous
        field. This implies that self.V_r contains discontinuous functions.
        To ensure domain updates do not create holes in the domain,
        use a continuous subspace self.V_c of self.V_r as control space.
        """
        if element.family() == 'Discontinuous Lagrange':
            self.is_DG = True
            self.V_c = fd.VectorFunctionSpace(self.mesh_r,
                                              "CG", element._degree)
            self.Ip = fd.Interpolator(fd.TestFunction(self.V_c),
                                      self.V_r).callable().handle
コード例 #3
0
    def __init__(self, function_space, model_parameters):
        super(AllenCahnHeatModel, self).__init__()

        self._solution_function = fd.Function(function_space)
        self._solutiondot_function = fd.Function(function_space)
        test_function = fd.TestFunction(function_space)

        # Split mixed FE function into separate functions and put them into namedtuple
        FiniteElementFunction = namedtuple("FiniteElementFunction",
                                           ["phi", "T"])

        split_solution_function = FiniteElementFunction(
            *ufl.split(self._solution_function))
        split_solutiondot_function = FiniteElementFunction(
            *ufl.split(self._solutiondot_function))
        split_test_function = FiniteElementFunction(*ufl.split(test_function))

        finite_element_functions = (
            split_solution_function,
            split_solutiondot_function,
            split_test_function,
        )

        F_AC = get_allen_cahn_weak_form(*finite_element_functions,
                                        model_parameters)
        F_heat = get_heat_weak_form(*finite_element_functions,
                                    model_parameters)

        F = F_AC + F_heat

        self._residual = F
コード例 #4
0
    def __init__(self, equation, solution, fields, dt, solver_parameters={}):
        """
        :arg equation: the equation to solve
        :type equation: :class:`BaseEquation` object
        :arg solution: :class:`Function` where solution will be stored
        :arg fields: Dictionary of fields that are passed to the equation
        :type fields: dict of :class:`Function` or :class:`Constant` objects
        :arg float dt: time step in seconds
        :kwarg dict solver_parameters: PETSc solver options
        """
        super(TimeIntegrator, self).__init__()

        self.equation = equation
        self.test = firedrake.TestFunction(solution.function_space())
        self.solution = solution
        self.fields = fields
        self.dt = dt
        self.dt_const = firedrake.Constant(dt)

        # unique identifier used in solver
        self.name = '-'.join(
            [self.__class__.__name__, self.equation.__class__.__name__])

        self.solver_parameters = {}
        self.solver_parameters.update(solver_parameters)
コード例 #5
0
    def get_form(self, V):
        u = fd.TrialFunction(V)
        v = fd.TestFunction(V)
        base = self.base_form.get_form(V)
        n = fd.FacetNormal(V.ufl_domain())

        dim = V.mesh().topological_dimension()

        def h(domain):
            if dim == 3:
                return (fd.FacetArea(domain) * 2)**(1. / 2)
            else:
                return fd.FacetArea(domain)

        h = h(V.mesh())
        alpha = fd.Constant(10)
        from firedrake import div, grad, dS, dx, inner, jump, avg, ds

        def form(u, v):
            return inner(div(grad(u)), div(grad(v)))*dx \
                - inner(avg(div(grad(u))), jump(grad(v), n))*dS \
                - inner(jump(grad(u), n), avg(div(grad(v))))*dS \
                + alpha/h*inner(jump(grad(u), n), jump(grad(v), n))*dS \
                - inner(div(grad(u)), inner(grad(v), n))*ds \
                - inner(inner(grad(u), n), div(grad(v)))*ds \
                + alpha/h*inner(grad(u), grad(v))*ds

        form = base + self.mu * (sum(form(u[i], v[i]) for i in range(dim)))
        return form
コード例 #6
0
ファイル: heat_transport.py プロジェクト: vic1309/icepack
    def _advect(self, dt, E, u, w, h, s, E_inflow, E_surface):
        Q = E.function_space()
        φ, ψ = firedrake.TrialFunction(Q), firedrake.TestFunction(Q)

        U = firedrake.as_vector((u[0], u[1], w))
        flux_cells = -φ * inner(U, grad(ψ)) * h * dx

        mesh = Q.mesh()
        ν = facet_normal_2(mesh)
        outflow = firedrake.max_value(inner(u, ν), 0)
        inflow = firedrake.min_value(inner(u, ν), 0)

        flux_outflow = φ * ψ * outflow * h * ds_v + \
                       φ * ψ * firedrake.max_value(-w, 0) * h * ds_b + \
                       φ * ψ * firedrake.max_value(+w, 0) * h * ds_t
        F = φ * ψ * h * dx + dt * (flux_cells + flux_outflow)

        flux_inflow = -E_inflow * ψ * inflow * h * ds_v \
                      -E_surface * ψ * firedrake.min_value(-w, 0) * h * ds_b \
                      -E_surface * ψ * firedrake.min_value(+w, 0) * h * ds_t
        A = E * ψ * h * dx + dt * flux_inflow

        solver_parameters = {'ksp_type': 'preonly', 'pc_type': 'lu'}
        degree_E = E.ufl_element().degree()
        degree_u = u.ufl_element().degree()
        degree = (3 * degree_E[0] + degree_u[0], 2 * degree_E[1] + degree_u[1])
        form_compiler_parameters = {'quadrature_degree': degree}
        firedrake.solve(F == A,
                        E,
                        solver_parameters=solver_parameters,
                        form_compiler_parameters=form_compiler_parameters)
コード例 #7
0
ファイル: heat_transport.py プロジェクト: benhills/icepack
    def advective_flux(self, **kwargs):
        keys = ('energy', 'velocity', 'vertical_velocity', 'thickness',
                'energy_inflow', 'energy_surface')
        keys_alt = ('E', 'u', 'w', 'h', 'E_inflow', 'E_surface')
        E, u, w, h, E_inflow, E_surface = get_kwargs_alt(
            kwargs, keys, keys_alt)

        Q = E.function_space()
        ψ = firedrake.TestFunction(Q)

        U = firedrake.as_vector((u[0], u[1], w))
        flux_cells = -E * inner(U, grad(ψ)) * h * dx

        mesh = Q.mesh()
        ν = facet_normal_2(mesh)
        outflow = firedrake.max_value(inner(u, ν), 0)
        inflow = firedrake.min_value(inner(u, ν), 0)

        flux_outflow = (E * outflow * ψ * h * ds_v +
                        E * firedrake.max_value(-w, 0) * ψ * h * ds_b +
                        E * firedrake.max_value(+w, 0) * ψ * h * ds_t)

        flux_inflow = (E_inflow * inflow * ψ * h * ds_v +
                       E_surface * firedrake.min_value(-w, 0) * ψ * h * ds_b +
                       E_surface * firedrake.min_value(+w, 0) * ψ * h * ds_t)

        return flux_cells + flux_outflow + flux_inflow
コード例 #8
0
def get_facet_areas(mesh):
    """
    Compute area of each facet of `mesh`.

    The facet areas are stored as a HDiv
    trace field.

    Note that the plus sign is arbitrary
    and could equally well be chosen as minus.

    :arg mesh: the input mesh to do computations on

    :rtype: firedrake.function.Function facet_areas with
        facet area data
    """
    HDivTrace = firedrake.FunctionSpace(mesh, "HDiv Trace", 0)
    v = firedrake.TestFunction(HDivTrace)
    u = firedrake.TrialFunction(HDivTrace)
    facet_areas = firedrake.Function(HDivTrace, name="Facet areas")
    mass_term = v("+") * u("+") * ufl.dS + v * u * ufl.ds
    rhs = v("+") * ufl.FacetArea(mesh) * ufl.dS + v * ufl.FacetArea(mesh) * ufl.ds
    sp = {
        "snes_type": "ksponly",
        "ksp_type": "preonly",
        "pc_type": "jacobi",
    }
    firedrake.solve(mass_term == rhs, facet_areas, solver_parameters=sp)
    return facet_areas
コード例 #9
0
    def advective_flux(self, **kwargs):
        keys = (
            "energy",
            "velocity",
            "vertical_velocity",
            "thickness",
            "energy_inflow",
            "energy_surface",
        )
        E, u, w, h, E_inflow, E_surface = itemgetter(*keys)(kwargs)

        Q = E.function_space()
        ψ = firedrake.TestFunction(Q)

        # NOTE: Be careful here going to xz! You might have to separate this into
        # the sum of a horizontal and vertical flux if we're shadowing Firedrake's
        # grad operator with out own specialized one.
        U = firedrake.as_vector((u[0], u[1], w))
        flux_cells = -E * inner(U, grad(ψ)) * h * dx

        ν = FacetNormal(Q.mesh())
        outflow = firedrake.max_value(inner(u, ν), 0)
        inflow = firedrake.min_value(inner(u, ν), 0)

        flux_outflow = (E * outflow * ψ * h * ds_v +
                        E * firedrake.max_value(-w, 0) * ψ * h * ds_b +
                        E * firedrake.max_value(+w, 0) * ψ * h * ds_t)

        flux_inflow = (E_inflow * inflow * ψ * h * ds_v +
                       E_surface * firedrake.min_value(-w, 0) * ψ * h * ds_b +
                       E_surface * firedrake.min_value(+w, 0) * ψ * h * ds_t)

        return flux_cells + flux_outflow + flux_inflow
コード例 #10
0
ファイル: advection_diffusion.py プロジェクト: LLNL/lestofire
def AdvectionDiffusionGLS(
    V: fd.FunctionSpace,
    theta: fd.Function,
    phi: fd.Function,
    PeInv: float = 1e-4,
    phi_t: fd.Function = None,
):
    PeInv_ct = fd.Constant(PeInv)
    rho = fd.TestFunction(V)
    F = (inner(theta, grad(phi)) * rho +
         PeInv_ct * inner(grad(phi), grad(rho))) * dx

    if phi_t:
        F += phi_t * rho * dx

    h = fd.CellDiameter(V.ufl_domain())
    R_U = dot(theta, grad(phi)) - PeInv_ct * div(grad(phi))

    if phi_t:
        R_U += phi_t

    beta_gls = 0.9
    tau_gls = beta_gls * ((4.0 * dot(theta, theta) / h**2) + 9.0 *
                          (4.0 * PeInv_ct / h**2)**2)**(-0.5)

    theta_U = dot(theta, grad(rho)) - PeInv_ct * div(grad(rho))
    F += tau_gls * inner(R_U, theta_U) * dx()

    return F
コード例 #11
0
    def _initialise_problem(self):
        """
        Set up the Firedrake machinery for solving the problem.
        """

        # Define trial and test functions on the space
        self._u = fd.TrialFunction(self.V)

        self._v = fd.TestFunction(self.V)

        # Define sesquilinear form and antilinear functional
        self._a = self._define_form(self._A, self._n)

        self._set_L()

        self._set_pre()

        # Define problem and solver (following code courtesy of Lawrence
        # Mitchell, via Slack)
        problem = fd.LinearVariationalProblem(self._a,
                                              self._L,
                                              self.u_h,
                                              aP=self._a_pre,
                                              constant_jacobian=False)

        self._solver = fd.LinearVariationalSolver(
            problem, solver_parameters=self._solver_parameters)

        self._initialised = True
コード例 #12
0
def create_form(form_string, family, degree, dimension, operation):
    from firedrake import dx, inner, grad
    import firedrake as f

    f.parameters['coffee']['optlevel'] = 'O3'
    f.parameters['pyop2_options']['opt_level'] = 'O3'
    f.parameters['pyop2_options']['simd_isa'] = 'avx'
    f.parameters["pyop2_options"]["lazy_evaluation"] = False

    m = f.UnitSquareMesh(2, 2, quadrilateral=True)
    if dimension == 3:
        m = f.ExtrudedMesh(m, 2)

    fs = f.FunctionSpace(m, family, degree)
    v = f.TestFunction(fs)
    if operation == "matrix":
        u = f.TrialFunction(fs)
    elif operation == "action":
        u = f.Function(fs)
    else:
        raise ValueError("Unknown operation: %s" % operation)

    if form_string == "u * v * dx":
        return u * v * dx
    elif form_string == "inner(grad(u), grad(v)) * dx":
        return inner(grad(u), grad(v)) * dx
コード例 #13
0
    def make_kernels(self, Vf, Vc):
        """
        Interpolation and restriction kernels between arbitrary elements.

        This is temporary while we wait for structure-preserving tfsc kernels.
        """
        self.prolong_kernel = self.prolongation_transfer_kernel_action(
            Vf, self.uc)
        matrix_kernel = self.prolongation_transfer_kernel_action(
            Vf, firedrake.TestFunction(Vc))
        # The way we transpose the prolongation kernel is suboptimal.
        # A local matrix is generated each time the kernel is executed.
        element_kernel = loopy.generate_code_v2(
            matrix_kernel.code).device_code()
        element_kernel = element_kernel.replace(
            "void expression_kernel", "static void expression_kernel")
        dimc = Vc.finat_element.space_dimension() * Vc.value_size
        dimf = Vf.finat_element.space_dimension() * Vf.value_size
        restrict_code = f"""
        {element_kernel}

        void restriction({ScalarType_c} *restrict Rc, const {ScalarType_c} *restrict Rf, const {ScalarType_c} *restrict w)
        {{
            {ScalarType_c} Afc[{dimf}*{dimc}] = {{0}};
            expression_kernel(Afc);
            for ({IntType_c} i = 0; i < {dimf}; i++)
               for ({IntType_c} j = 0; j < {dimc}; j++)
                   Rc[j] += Afc[i*{dimc} + j] * Rf[i] * w[i];
        }}
        """
        self.restrict_kernel = op2.Kernel(restrict_code, "restriction")
コード例 #14
0
ファイル: beam.py プロジェクト: obokhove/SurfsUP20142019
 def define_functions(self):
     self.X = fd.Function(self.V, name="X")  # displacement, not position
     self.U = fd.Function(self.V, name="U")  # velocity
     self.trial = fd.TrialFunction(self.V)
     #        self.phi_vect = fd.Function(self.V, name="Surface forcing")
     #Fgr = Function(V, name="Gravity")
     self.v = fd.TestFunction(self.V)
コード例 #15
0
    def __init__(self, mesh_m):
        super().__init__()

        # Setup problem
        V = fd.FunctionSpace(mesh_m, "CG", 1)

        # Weak form of Poisson problem
        u = fda.Function(V, name="State")
        v = fd.TestFunction(V)
        f = fda.Constant(4.)
        F = (fd.inner(fd.grad(u), fd.grad(v)) - f * v) * fd.dx
        bcs = fda.DirichletBC(V, 0., "on_boundary")

        # PDE-solver parameters
        params = {
            "ksp_type": "cg",
            "mat_type": "aij",
            "pc_type": "hypre",
            "pc_factor_mat_solver_package": "boomerang",
            "ksp_rtol": 1e-11,
            "ksp_atol": 1e-11,
            "ksp_stol": 1e-15,
        }

        self.solution = u
        problem = fda.NonlinearVariationalProblem(F, self.solution, bcs=bcs)
        self.solver = fda.NonlinearVariationalSolver(problem,
                                                     solver_parameters=params)
コード例 #16
0
ファイル: inverse.py プロジェクト: benhills/icepack
    def __init__(self, problem, callback=(lambda s: None), memory=5):
        self._setup(problem, callback)
        self.update_state()
        self.update_adjoint_state()

        Q = self.parameter.function_space()
        self._memory = memory

        q, dJ = self.search_direction, self.gradient
        M = firedrake.TrialFunction(Q) * firedrake.TestFunction(Q) * dx
        f = firedrake.Function(Q)
        problem = firedrake.LinearVariationalProblem(
            M, dJ, f, form_compiler_parameters=self._fc_params)
        self._search_direction_solver = firedrake.LinearVariationalSolver(
            problem, solver_parameters=self._solver_params)
        self._search_direction_solver.solve()
        q.assign(-f)

        self._f = f
        self._rho = []
        self._ps = [self.parameter.copy(deepcopy=True)]
        self._fs = [q.copy(deepcopy=True)]
        self._fs[-1] *= -1

        self._callback(self)
コード例 #17
0
    def setup(self, **kwargs):
        r"""Create the internal data structures that help reuse information
        from past prognostic solves"""
        for name, field in kwargs.items():
            if name in self._fields.keys():
                self._fields[name].assign(field)
            else:
                if isinstance(field, firedrake.Constant):
                    self._fields[name] = firedrake.Constant(field)
                elif isinstance(field, firedrake.Function):
                    self._fields[name] = field.copy(deepcopy=True)
                else:
                    raise TypeError(
                        'Input fields must be Constant or Function!')

        dt = firedrake.Constant(1.)
        dh_dt = self._continuity(dt, **self._fields)
        h = self._fields.get('thickness', self._fields.get('h'))
        h_0 = h.copy(deepcopy=True)
        q = firedrake.TestFunction(h.function_space())
        F = (h - h_0) * q * dx - dt * dh_dt

        problem = firedrake.NonlinearVariationalProblem(F, h)
        self._solver = firedrake.NonlinearVariationalSolver(
            problem, solver_parameters=self._solver_parameters)

        self._thickness_old = h_0
        self._timestep = dt
コード例 #18
0
 def __init__(self, V, fixed_dims=[], direct_solve=False):
     if isinstance(fixed_dims, int):
         fixed_dims = [fixed_dims]
     self.V = V
     self.fixed_dims = fixed_dims
     self.direct_solve = direct_solve
     self.zero = fd.Constant(V.mesh().topological_dimension() * (0, ))
     u = fd.TrialFunction(V)
     v = fd.TestFunction(V)
     self.zero_fun = fd.Function(V)
     self.a = 1e-2 * \
         fd.inner(u, v) * fd.dx + fd.inner(fd.sym(fd.grad(u)),
                                           fd.sym(fd.grad(v))) * fd.dx
     self.bc_fun = fd.Function(V)
     if len(self.fixed_dims) == 0:
         bcs = [fd.DirichletBC(self.V, self.bc_fun, "on_boundary")]
     else:
         bcs = []
         for i in range(self.V.mesh().topological_dimension()):
             if i in self.fixed_dims:
                 bcs.append(fd.DirichletBC(self.V.sub(i), 0, "on_boundary"))
             else:
                 bcs.append(
                     fd.DirichletBC(self.V.sub(i), self.bc_fun.sub(i),
                                    "on_boundary"))
     self.A_ext = fd.assemble(self.a, bcs=bcs, mat_type="aij")
     self.ls_ext = fd.LinearSolver(self.A_ext,
                                   solver_parameters=self.get_params())
     self.A_adj = fd.assemble(self.a,
                              bcs=fd.DirichletBC(self.V, self.zero,
                                                 "on_boundary"),
                              mat_type="aij")
     self.ls_adj = fd.LinearSolver(self.A_adj,
                                   solver_parameters=self.get_params())
コード例 #19
0
    def _setup(self, **kwargs):
        for name, field in kwargs.items():
            if name in self._fields.keys():
                self._fields[name].assign(field)
            else:
                if isinstance(field, firedrake.Constant):
                    self._fields[name] = firedrake.Constant(field)
                elif isinstance(field, firedrake.Function):
                    self._fields[name] = field.copy(deepcopy=True)
                else:
                    raise TypeError(
                        "Input %s field has type %s, must be Constant or Function!"
                        % (name, type(field)))

        dt = Constant(1.0)

        aflux = self.model.advective_flux(**self.fields)
        dflux = self.model.diffusive_flux(**self.fields)
        sources = self.model.sources(**self.fields)
        dE_dt = sources - aflux - dflux
        E, h = itemgetter("energy", "thickness")(self.fields)
        E_0 = E.copy(deepcopy=True)
        ψ = firedrake.TestFunction(E.function_space())
        F = (E - E_0) * ψ * h * dx - dt * dE_dt

        degree = E.ufl_element().degree()
        fc_params = {"quadrature_degree": (3 * degree[0], 2 * degree[1])}
        problem = firedrake.NonlinearVariationalProblem(
            F, E, form_compiler_parameters=fc_params)

        self._solver = firedrake.NonlinearVariationalSolver(
            problem, solver_parameters=self._solver_parameters)

        self._energy_old = E_0
        self._timestep = dt
コード例 #20
0
ファイル: heat_transport.py プロジェクト: benhills/icepack
    def _setup(self, **kwargs):
        for name, field in kwargs.items():
            if name in self.fields.keys():
                self.fields[name].assign(field)
            else:
                self.fields[name] = utilities.copy(field)

        dt = Constant(1.)

        aflux = self.model.advective_flux(**self.fields)
        dflux = self.model.diffusive_flux(**self.fields)
        sources = self.model.sources(**self.fields)
        dE_dt = sources - aflux - dflux
        E = self.fields.get('energy', self.fields.get('E'))
        h = self.fields.get('thickness', self.fields.get('h'))
        E_0 = E.copy(deepcopy=True)
        ψ = firedrake.TestFunction(E.function_space())
        F = (E - E_0) * ψ * h * dx - dt * dE_dt

        degree = E.ufl_element().degree()
        fc_params = {'quadrature_degree': (3 * degree[0], 2 * degree[1])}
        problem = firedrake.NonlinearVariationalProblem(
            F, E, form_compiler_parameters=fc_params
        )

        self._solver = firedrake.NonlinearVariationalSolver(
            problem, solver_parameters=self._solver_parameters
        )

        self._energy_old = E_0
        self._timestep = dt
コード例 #21
0
ファイル: test_L2tracking.py プロジェクト: mfkiwl/fireshape
    def __init__(self, mesh_m):
        super().__init__()
        self.mesh_m = mesh_m

        # Setup problem
        self.V = fd.FunctionSpace(self.mesh_m, "CG", 1)

        # Preallocate solution variables for state and adjoint equations
        self.solution = fd.Function(self.V, name="State")

        # Weak form of Poisson problem
        u = self.solution
        v = fd.TestFunction(self.V)
        self.f = fd.Constant(4.)
        self.F = (fd.inner(fd.grad(u), fd.grad(v)) - self.f * v) * fd.dx
        self.bcs = fd.DirichletBC(self.V, 0., "on_boundary")

        # PDE-solver parameters
        self.params = {
            "ksp_type": "cg",
            "mat_type": "aij",
            "pc_type": "hypre",
            "pc_factor_mat_solver_package": "boomerang",
            "ksp_rtol": 1e-11,
            "ksp_atol": 1e-11,
            "ksp_stol": 1e-15,
        }

        stateproblem = fd.NonlinearVariationalProblem(self.F,
                                                      self.solution,
                                                      bcs=self.bcs)
        self.solver = fd.NonlinearVariationalSolver(
            stateproblem, solver_parameters=self.params)
コード例 #22
0
ファイル: projection.py プロジェクト: jwallwork23/firedrake
 def A(self):
     u = firedrake.TrialFunction(self.target.function_space())
     v = firedrake.TestFunction(self.target.function_space())
     a = firedrake.inner(u, v)*firedrake.dx
     if self.use_slate_for_inverse:
         a = firedrake.Tensor(a).inv
     A = firedrake.assemble(a, bcs=self.bcs,
                            form_compiler_parameters=self.form_compiler_parameters)
     return A
コード例 #23
0
 def V_approx_inv_mass(self, V, DG):
     """
     Approximate inverse mass.  Computes (cellwise) (V, V)^{-1} (V, DG).
     :arg V: a function space
     :arg DG: the DG space
     :returns: A PETSc Mat mapping from V -> DG.
     """
     key = V.dim()
     try:
         return self._V_approx_inv_mass[key]
     except KeyError:
         a = firedrake.Tensor(firedrake.inner(firedrake.TestFunction(V),
                                              firedrake.TrialFunction(V))*firedrake.dx)
         b = firedrake.Tensor(firedrake.inner(firedrake.TestFunction(V),
                                              firedrake.TrialFunction(DG))*firedrake.dx)
         M = firedrake.assemble(a.inv * b)
         M.force_evaluation()
         return self._V_approx_inv_mass.setdefault(key, M.petscmat)
コード例 #24
0
def solve_something(mesh):
    V = fd.FunctionSpace(mesh, "CG", 1)
    u = fd.Function(V)
    v = fd.TestFunction(V)

    x, y = fd.SpatialCoordinate(mesh)
    # f = fd.sin(x) * fd.sin(y) + x**2 + y**2
    # uex = x**4 * y**4
    uex = fd.sin(x) * fd.sin(y)  #*(x*y)**3
    # def source(xs, ys):
    #     return 1/((x-xs)**2+(y-ys)**2 + 0.1)
    # uex = source(0, 0)
    uex = uex - fd.assemble(uex * fd.dx) / fd.assemble(1 * fd.dx(domain=mesh))
    # f = fd.conditional(fd.ge(abs(x)-abs(y), 0), 1, 0)
    from firedrake import inner, grad, dx, ds, div, sym
    eps = fd.Constant(0.0)
    f = uex - div(grad(uex)) + eps * div(grad(div(grad(uex))))
    n = fd.FacetNormal(mesh)
    g = inner(grad(uex), n)
    g1 = inner(grad(div(grad(uex))), n)
    g2 = div(grad(uex))
    # F = 0.1 * inner(u, v) * dx + inner(grad(u), grad(v)) * dx + inner(grad(grad(u)), grad(grad(v))) * dx - f * v * dx - g * v * ds
    F = inner(u, v) * dx + inner(grad(u),
                                 grad(v)) * dx - f * v * dx - g * v * ds
    F += eps * inner(div(grad(u)), div(grad(v))) * dx
    F += eps * g1 * v * ds
    F -= eps * g2 * inner(grad(v), n) * ds
    # f = -div(grad(uex))
    # F = inner(grad(u), grad(v)) * dx - f * v * dx

    # bc = fd.DirichletBC(V, uex, "on_boundary")
    bc = None
    fd.solve(F == 0,
             u,
             bcs=bc,
             solver_parameters={
                 "ksp_type": "cg",
                 "ksp_atol": 1e-13,
                 "ksp_rtol": 1e-13,
                 "ksp_dtol": 1e-13,
                 "ksp_stol": 1e-13,
                 "pc_type": "jacobi",
                 "pc_factor_mat_solver_type": "mumps",
                 "snes_type": "ksponly",
                 "ksp_converged_reason": None
             })
    print("||u-uex||             =", fd.norm(u - uex))
    print("||grad(u-uex)||       =", fd.norm(grad(u - uex)))
    print("||grad(grad(u-uex))|| =", fd.norm(grad(grad(u - uex))))
    err = fd.Function(
        fd.TensorFunctionSpace(mesh, "DG",
                               V.ufl_element().degree() - 2)).interpolate(
                                   grad(grad(u - uex)))
    # err = fd.Function(fd.FunctionSpace(mesh, "DG", V.ufl_element().degree())).interpolate(u-uex)
    fd.File(outdir + "sln.pvd").write(u)
    fd.File(outdir + "err.pvd").write(err)
コード例 #25
0
    def evaluate_adj_component(self,
                               inputs,
                               adj_inputs,
                               block_variable,
                               idx,
                               prepared=None):
        if not self.linear and self.func == block_variable.output:
            # We are not able to calculate derivatives wrt initial guess.
            return None
        F_form = prepared["form"]
        adj_sol = prepared["adj_sol"]
        adj_sol_bdy = prepared["adj_sol_bdy"]
        c = block_variable.output
        c_rep = block_variable.saved_output

        if isinstance(c, firedrake.Function):
            trial_function = firedrake.TrialFunction(c.function_space())
        elif isinstance(c, firedrake.Constant):
            mesh = self.compat.extract_mesh_from_form(F_form)
            trial_function = firedrake.TrialFunction(
                c._ad_function_space(mesh))
        elif isinstance(c, firedrake.DirichletBC):
            tmp_bc = self.compat.create_bc(
                c,
                value=self.compat.extract_subfunction(adj_sol_bdy,
                                                      c.function_space()))
            return [tmp_bc]
        elif isinstance(c, self.compat.MeshType):
            # Using CoordianteDerivative requires us to do action before
            # differentiating, might change in the future.
            F_form_tmp = firedrake.action(F_form, adj_sol)
            X = firedrake.SpatialCoordinate(c_rep)
            dFdm = firedrake.derivative(
                -F_form_tmp, X, firedrake.TestFunction(c._ad_function_space()))

            dFdm = self.compat.assemble_adjoint_value(dFdm,
                                                      **self.assemble_kwargs)
            return dFdm

        # dFdm_cache works with original variables, not block saved outputs.
        if c in self._dFdm_cache:
            dFdm = self._dFdm_cache[c]
        else:
            dFdm = -firedrake.derivative(self.lhs, c, trial_function)
            dFdm = firedrake.adjoint(dFdm)
            self._dFdm_cache[c] = dFdm

        # Replace the form coefficients with checkpointed values.
        replace_map = self._replace_map(dFdm)
        replace_map[self.func] = self.get_outputs()[0].saved_output
        dFdm = replace(dFdm, replace_map)

        dFdm = dFdm * adj_sol
        dFdm = self.compat.assemble_adjoint_value(dFdm, **self.assemble_kwargs)

        return dFdm
コード例 #26
0
def restrict_kernel(Vf, Vc):
    hierarchy, level = utils.get_level(Vc.ufl_domain())
    levelf = level + Fraction(1 / hierarchy.refinements_per_level)
    cache = hierarchy._shared_data_cache["transfer_kernels"]
    coordinates = Vc.ufl_domain().coordinates
    key = (("restrict", ) + Vf.ufl_element().value_shape() +
           entity_dofs_key(Vf.finat_element.entity_dofs()) +
           entity_dofs_key(Vc.finat_element.entity_dofs()) + entity_dofs_key(
               coordinates.function_space().finat_element.entity_dofs()))
    try:
        return cache[key]
    except KeyError:
        mesh = coordinates.ufl_domain()
        evaluate_kernel = compile_element(firedrake.TestFunction(Vc), Vf)
        to_reference_kernel = to_reference_coordinates(
            coordinates.ufl_element())
        coords_element = create_element(coordinates.ufl_element())
        element = create_element(Vc.ufl_element())
        eval_args = evaluate_kernel.args[:-1]
        args = eval_args[-1].gencode(not_scope=True)
        R, fine = (a.sym.symbol for a in eval_args)
        my_kernel = """
        %(to_reference)s
        %(evaluate)s

        __attribute__((noinline)) /* Clang bug */
        static void pyop2_kernel_restrict(double *R, %(args)s, const double *X, const double *Xc)
        {
            double Xref[%(tdim)d];
            int cell = -1;
            for (int i = 0; i < %(ncandidate)d; i++) {
                const double *Xci = Xc + i*%(Xc_cell_inc)d;
                to_reference_coords_kernel(Xref, X, Xci);
                if (%(inside_cell)s) {
                    cell = i;
                    const double *Ri = %(R)s + cell*%(coarse_cell_inc)d;
                    pyop2_kernel_evaluate(Ri, %(fine)s, Xref);
                    break;
                }
            }
        }
        """ % {
            "to_reference": str(to_reference_kernel),
            "evaluate": str(evaluate_kernel),
            "ncandidate": hierarchy.fine_to_coarse_cells[levelf].shape[1],
            "inside_cell": inside_check(element.cell, eps=1e-8, X="Xref"),
            "Xc_cell_inc": coords_element.space_dimension(),
            "coarse_cell_inc": element.space_dimension(),
            "args": args,
            "R": R,
            "fine": fine,
            "tdim": mesh.topological_dimension()
        }

        return cache.setdefault(
            key, op2.Kernel(my_kernel, name="pyop2_kernel_restrict"))
コード例 #27
0
ファイル: inverse.py プロジェクト: vic1309/icepack
 def update_search_direction(self):
     r"""Set the search direction to be the inverse of the mass matrix times
     the gradient of the objective"""
     q, dJ = self.search_direction, self.gradient
     Q = q.function_space()
     M = firedrake.TrialFunction(Q) * firedrake.TestFunction(Q) * dx
     firedrake.solve(M == -dJ,
                     q,
                     solver_parameters=self._solver_params,
                     form_compiler_parameters=self._fc_params)
コード例 #28
0
 def derivative(self, out):
     """
     Assemble partial directional derivative wrt ControlSpace perturbations.
     """
     v = fd.TestFunction(self.V_control)
     fd.assemble(self.derivative_form(v),
                 tensor=self.deriv_r,
                 form_compiler_parameters=self.params)
     out.fun.assign(self.deriv_r)
     out.scale(self.scale)
コード例 #29
0
def estimate_timestep(mesh, V, c, estimate_max_eigenvalue=True):
    """Estimate the maximum stable timestep based on the spectral radius
    using optionally the Gershgorin Circle Theorem to estimate the
    maximum generalized eigenvalue. Otherwise computes the maximum
    generalized eigenvalue exactly

    ONLY WORKS WITH KMV ELEMENTS
    """

    u, v = fire.TrialFunction(V), fire.TestFunction(V)
    quad_rule = finat.quadrature.make_quadrature(V.finat_element.cell,
                                                 V.ufl_element().degree(),
                                                 "KMV")
    dxlump = fire.dx(rule=quad_rule)
    A = fire.assemble(u * v * dxlump)
    ai, aj, av = A.petscmat.getValuesCSR()
    av_inv = []
    for value in av:
        if value == 0:
            av_inv.append(0.0)
        else:
            av_inv.append(1 / value)
    Asp = scipy.sparse.csr_matrix((av, aj, ai))
    Asp_inv = scipy.sparse.csr_matrix((av_inv, aj, ai))

    K = fire.assemble(c * c * dot(grad(u), grad(v)) * dxlump)
    ai, aj, av = K.petscmat.getValuesCSR()
    Ksp = scipy.sparse.csr_matrix((av, aj, ai))

    # operator
    Lsp = Asp_inv.multiply(Ksp)
    if estimate_max_eigenvalue:
        # absolute maximum of diagonals
        max_eigval = np.amax(np.abs(Lsp.diagonal()))
    else:
        print(
            "Computing exact eigenvalues is extremely computationally demanding!",
            flush=True,
        )
        max_eigval = scipy.sparse.linalg.eigs(Ksp,
                                              M=Asp,
                                              k=1,
                                              which="LM",
                                              return_eigenvectors=False)[0]

    # print(max_eigval)
    if np.sqrt(max_eigval) > 0.0:
        max_dt = np.float(2 / np.sqrt(max_eigval))
    else:
        max_dt = 100000000
    #print(
    #    f"Maximum stable timestep should be about: {np.float(2 / np.sqrt(max_eigval))} seconds",
    #    flush=True,
    #)
    return max_dt
コード例 #30
0
ファイル: innerproduct.py プロジェクト: medinaeder/fireshape
    def __init__(self, Q, free_bids=["on_boundary"]):
        (V, I_interp) = Q.get_space_for_inner()

        self.free_bids = free_bids

        u = fd.TrialFunction(V)
        v = fd.TestFunction(V)

        n = fd.FacetNormal(V.mesh())

        def surf_grad(u):
            return fd.sym(fd.grad(u) - fd.outer(fd.grad(u) * n, n))

        a = (fd.inner(surf_grad(u), surf_grad(v)) + fd.inner(u, v)) * fd.ds
        # petsc doesn't like matrices with zero rows
        a += 1e-10 * fd.inner(u, v) * fd.dx
        A = fd.assemble(a, mat_type="aij")
        A = A.petscmat
        tdim = V.mesh().topological_dimension()

        lsize = fd.Function(V).vector().local_size()

        def get_nodes_bc(bc):
            nodes = bc.nodes
            return nodes[nodes < lsize]

        def get_nodes_bid(bid):
            bc = fd.DirichletBC(V, fd.Constant(tdim * (0, )), bid)
            return get_nodes_bc(bc)

        free_nodes = np.concatenate(
            [get_nodes_bid(bid) for bid in self.free_bids])
        free_dofs = np.concatenate(
            [tdim * free_nodes + i for i in range(tdim)])
        free_dofs = np.unique(np.sort(free_dofs))
        self.free_is = PETSc.IS().createGeneral(free_dofs)
        lgr, lgc = A.getLGMap()
        self.global_free_is_row = lgr.applyIS(self.free_is)
        self.global_free_is_col = lgc.applyIS(self.free_is)
        A = A.createSubMatrix(self.global_free_is_row, self.global_free_is_col)
        # A.view()
        A.assemble()
        self.A = A
        Aksp = PETSc.KSP().create()
        Aksp.setOperators(self.A)
        Aksp.setOptionsPrefix("A_")
        opts = PETSc.Options()
        opts["A_ksp_type"] = "cg"
        opts["A_pc_type"] = "hypre"
        opts["A_ksp_atol"] = 1e-10
        opts["A_ksp_rtol"] = 1e-10
        Aksp.setUp()
        Aksp.setFromOptions()
        self.Aksp = Aksp