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
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")
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
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)