Exemplo n.º 1
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
Exemplo n.º 2
0
 def function_arg(self, g):
     '''Set the value of this boundary condition.'''
     if isinstance(g, firedrake.Function):
         if g.function_space() != self.function_space():
             raise RuntimeError("%r is defined on incompatible FunctionSpace!" % g)
         self._function_arg = g
     elif isinstance(g, ufl.classes.Zero):
         if g.ufl_shape and g.ufl_shape != self.function_space().ufl_element().value_shape():
             raise ValueError(f"Provided boundary value {g} does not match shape of space")
         # Special case. Scalar zero for direct Function.assign.
         self._function_arg = ufl.zero()
     elif isinstance(g, ufl.classes.Expr):
         if g.ufl_shape != self.function_space().ufl_element().value_shape():
             raise RuntimeError(f"Provided boundary value {g} does not match shape of space")
         try:
             self._function_arg = firedrake.Function(self.function_space())
             self._function_arg_update = firedrake.Interpolator(g, self._function_arg).interpolate
         except (NotImplementedError, AttributeError):
             # Element doesn't implement interpolation
             self._function_arg = firedrake.Function(self.function_space()).project(g)
             self._function_arg_update = firedrake.Projector(g, self._function_arg).project
     else:
         try:
             g = as_ufl(g)
             self._function_arg = g
         except UFLException:
             try:
                 # Recurse to handle this through interpolation.
                 self.function_arg = as_ufl(as_tensor(g))
             except UFLException:
                 raise ValueError(f"{g} is not a valid DirichletBC expression")
Exemplo n.º 3
0
    def coarsen(self, fdm, comm):
        fctx = get_appctx(fdm)
        test, trial = fctx.J.arguments()
        fV = test.function_space()
        fu = fctx._problem.u

        cele = self.coarsen_element(fV.ufl_element())
        cV = firedrake.FunctionSpace(fV.mesh(), cele)
        cdm = cV.dm

        cu = firedrake.Function(cV)
        interpolators = tuple(
            firedrake.Interpolator(fus, cus)
            for fus, cus in zip(fu.split(), cu.split()))

        def inject_state(interpolators):
            for interpolator in interpolators:
                interpolator.interpolate()

        parent = get_parent(fdm)
        assert parent is not None
        add_hook(parent,
                 setup=partial(push_parent, cdm, parent),
                 teardown=partial(pop_parent, cdm, parent),
                 call_setup=True)

        replace_d = {
            fu: cu,
            test: firedrake.TestFunction(cV),
            trial: firedrake.TrialFunction(cV)
        }
        cJ = replace(fctx.J, replace_d)
        cF = replace(fctx.F, replace_d)
        if fctx.Jp is not None:
            cJp = replace(fctx.Jp, replace_d)
        else:
            cJp = None

        cbcs = []
        for bc in fctx._problem.bcs:
            # Don't actually need the value, since it's only used for
            # killing parts of the matrix. This should be generalised
            # for p-FAS, if anyone ever wants to do that

            cV_ = cV
            for index in bc._indices:
                cV_ = cV_.sub(index)

            cbcs.append(
                firedrake.DirichletBC(cV_,
                                      firedrake.zero(cV_.shape),
                                      bc.sub_domain,
                                      method=bc.method))

        fcp = fctx._problem.form_compiler_parameters
        cproblem = firedrake.NonlinearVariationalProblem(
            cF,
            cu,
            cbcs,
            cJ,
            Jp=cJp,
            form_compiler_parameters=fcp,
            is_linear=fctx._problem.is_linear)

        cctx = _SNESContext(
            cproblem,
            fctx.mat_type,
            fctx.pmat_type,
            appctx=fctx.appctx,
            pre_jacobian_callback=fctx._pre_jacobian_callback,
            pre_function_callback=fctx._pre_function_callback,
            post_jacobian_callback=fctx._post_jacobian_callback,
            post_function_callback=fctx._post_function_callback,
            options_prefix=fctx.options_prefix,
            transfer_manager=fctx.transfer_manager)

        add_hook(parent,
                 setup=partial(push_appctx, cdm, cctx),
                 teardown=partial(pop_appctx, cdm, cctx),
                 call_setup=True)
        add_hook(parent,
                 setup=partial(inject_state, interpolators),
                 call_setup=True)

        cdm.setKSPComputeOperators(_SNESContext.compute_operators)
        cdm.setCreateInterpolation(self.create_interpolation)
        cdm.setOptionsPrefix(fdm.getOptionsPrefix())

        # If we're the coarsest grid of the p-hierarchy, don't
        # overwrite the coarsen routine; this is so that you can
        # use geometric multigrid for the p-coarse problem
        try:
            self.coarsen_element(cele)
            cdm.setCoarsen(self.coarsen)
        except ValueError:
            pass

        return cdm
Exemplo n.º 4
0
 def __init__(self, function_space, expr, boundary, method="topological"):
     self.uboundary = fire.Function(function_space)
     self.interpolator = fire.Interpolator(expr, self.uboundary)
     super().__init__(function_space, self.uboundary, boundary, method)