def coarsen_function_space(V, self, coefficient_mapping=None): if hasattr(V, "_coarse"): return V._coarse fine = V indices = [] while True: if V.index is not None: indices.append(V.index) if V.component is not None: indices.append(V.component) if V.parent is not None: V = V.parent else: break mesh = self(V.mesh(), self) Vf = V V = firedrake.FunctionSpace(mesh, V.ufl_element()) from firedrake.dmhooks import get_transfer_operators, push_transfer_operators transfer = get_transfer_operators(Vf.dm) push_transfer_operators(V.dm, *transfer) if len(V) > 1: for V_, Vc_ in zip(Vf, V): transfer = get_transfer_operators(V_.dm) push_transfer_operators(Vc_.dm, *transfer) for i in reversed(indices): V = V.sub(i) V._fine = fine fine._coarse = V return V
def compute_operators(ksp, J, P): r"""Form the Jacobian for this problem :arg ksp: a PETSc KSP object :arg J: the Jacobian (a Mat) :arg P: the preconditioner matrix (a Mat) """ dm = ksp.getDM() ctx = dmhooks.get_appctx(dm) problem = ctx._problem assert J.handle == ctx._jac.petscmat.handle if problem._constant_jacobian and ctx._jacobian_assembled: # Don't need to do any work with a constant jacobian # that's already assembled return ctx._jacobian_assembled = True fine = ctx._fine if fine is not None: _, _, inject = dmhooks.get_transfer_operators(fine._x.function_space().dm) inject(fine._x, ctx._x) for bc in ctx._problem.bcs: bc.apply(ctx._x) ctx._assemble_jac() ctx._jac.force_evaluation() if ctx.Jp is not None: assert P.handle == ctx._pjac.petscmat.handle ctx._assemble_pjac() ctx._pjac.force_evaluation()
def compute_operators(ksp, J, P): r"""Form the Jacobian for this problem :arg ksp: a PETSc KSP object :arg J: the Jacobian (a Mat) :arg P: the preconditioner matrix (a Mat) """ from firedrake.bcs import DirichletBC dm = ksp.getDM() ctx = dmhooks.get_appctx(dm) problem = ctx._problem assert J.handle == ctx._jac.petscmat.handle # TODO: Check how to use constant jacobian properly for TS if problem._constant_jacobian and ctx._jacobian_assembled: # Don't need to do any work with a constant jacobian # that's already assembled return ctx._jacobian_assembled = True fine = ctx._fine if fine is not None: manager = dmhooks.get_transfer_operators( fine._x.function_space().dm) manager.inject(fine._x, ctx._x) for bc in itertools.chain(*ctx._problem.bcs): if isinstance(bc, DirichletBC): bc.apply(ctx._x) ctx._assemble_jac() if ctx.Jp is not None: assert P.handle == ctx._pjac.petscmat.handle ctx._assemble_pjac()
def coarsen_function_space(V, self, coefficient_mapping=None): if hasattr(V, "_coarse"): return V._coarse from firedrake.dmhooks import (get_transfer_operators, get_parent, push_transfer_operators, pop_transfer_operators, push_parent, pop_parent, add_hook) fine = V indices = [] while True: if V.index is not None: indices.append(V.index) if V.component is not None: indices.append(V.component) if V.parent is not None: V = V.parent else: break mesh = self(V.mesh(), self) V = firedrake.FunctionSpace(mesh, V.ufl_element()) for i in reversed(indices): V = V.sub(i) V._fine = fine fine._coarse = V # FIXME: This replicates some code from dmhooks.coarsen, but we # can't do things there because that code calls this code. # We need to move these operators over here because if we have # fieldsplits + MG with auxiliary coefficients on spaces other # than which we do the MG, dm.coarsen is never called, so the # hooks are not attached. Instead we just call (say) inject which # coarsens the functionspace. cdm = V.dm transfer = get_transfer_operators(fine.dm) parent = get_parent(fine.dm) try: add_hook(parent, setup=partial(push_parent, cdm, parent), teardown=partial(pop_parent, cdm, parent), call_setup=True) add_hook(parent, setup=partial(push_transfer_operators, cdm, transfer), teardown=partial(pop_transfer_operators, cdm, transfer), call_setup=True) except ValueError: # Not in an add_hooks context pass return V