def create_subdm(dm, fields, *args, **kwargs): """Callback to create a sub-DM describing the specified fields. :arg DM: The DM. :arg fields: The fields in the new sub-DM. """ W = get_function_space(dm) ctx = get_appctx(dm) coarsen = get_ctx_coarsener(dm) if len(fields) == 1: # Subspace is just a single FunctionSpace. idx, = fields subdm = W[idx].dm iset = W._ises[idx] if ctx is not None: ctx, = ctx.split([(idx, )]) push_appctx(subdm, ctx) push_ctx_coarsener(subdm, coarsen) return iset, subdm else: # Need to build an MFS for the subspace subspace = firedrake.MixedFunctionSpace([W[f] for f in fields]) # Index set mapping from W into subspace. iset = PETSc.IS().createGeneral(numpy.concatenate( [W._ises[f].indices for f in fields]), comm=W.comm) if ctx is not None: ctx, = ctx.split([fields]) push_appctx(subspace.dm, ctx) push_ctx_coarsener(subspace.dm, coarsen) return iset, subspace.dm
def MixedFunctionSpaceHierarchy(mesh_hierarchy, *args, **kwargs): from firedrake.logging import warning, RED warning( RED % "TensorFunctionSpaceHierarchy is obsolete. Just build a FunctionSpace on the relevant mesh" ) kwargs.pop("mesh", None) return tuple( firedrake.MixedFunctionSpace(*args, mesh=mesh, **kwargs) for mesh in mesh_hierarchy)
def create_subdm(dm, fields, *args, **kwargs): """Callback to create a sub-DM describing the specified fields. :arg DM: The DM. :arg fields: The fields in the new sub-DM. .. note:: This should, but currently does not, transfer appropriately split application contexts onto the sub-DMs. """ W = get_function_space(dm) # TODO: Correct splitting of SNESContext for len(fields) > 1 case if len(fields) == 1: # Subspace is just a single FunctionSpace. idx = fields[0] subdm = W[idx].dm iset = W._ises[idx] return iset, subdm else: try: # Look up the subspace in the cache iset, subspace = W._subspaces[tuple(fields)] return iset, subspace.dm except KeyError: pass # Need to build an MFS for the subspace subspace = firedrake.MixedFunctionSpace([W[f] for f in fields]) # Index set mapping from W into subspace. iset = PETSc.IS().createGeneral(numpy.concatenate([W._ises[f].indices for f in fields]), comm=W.comm) # Keep hold of strong reference to created subspace (given we # only hold a weakref in the shell DM), and so we can # reuse it later. W._subspaces[tuple(fields)] = iset, subspace return iset, subspace.dm
if quad_mesh: RT1 = fd.FunctionSpace(mesh, "RTCF", order) DG0 = fd.FunctionSpace(mesh, "DQ", order - 1) # Others function space V = fd.VectorFunctionSpace(mesh, "DQ", order - 1) # pre-process purporse T = fd.TensorFunctionSpace(mesh, "DQ", order - 1) # kinv else: RT1 = fd.FunctionSpace(mesh, "RT", order) DG0 = fd.FunctionSpace(mesh, "DG", order - 1) # Others function space V = fd.VectorFunctionSpace(mesh, "DG", order - 1) # pre-process purporse T = fd.TensorFunctionSpace(mesh, "DG", order - 1) # kinv W = fd.MixedFunctionSpace([RT1, DG0, DG0]) P1 = fd.VectorFunctionSpace(mesh, "CG", order) # post-process purporse # test and trial functions on the subspaces of the mixed function spaces as # follows: :: v, q, r = fd.TestFunctions(W) # %% # 3.2) material property # perm lognormal Kinv = fd.Function(T, name="Kinv") k = np.random.randn(nx * n, ny * n) + par_a * np.random.randn(1) kf = ndimage.gaussian_filter(k, sigma) kl = k0 * np.exp(par_b + par_c * kf) * mD
cx, cy, cz = fd.SpatialCoordinate(mesh) outward_normals = fd.CellNormal(mesh) M = args.nsteps def perp(u): return fd.cross(outward_normals, u) degree = args.degree V1 = fd.FunctionSpace(mesh, "BDFM", degree + 1) V2 = fd.FunctionSpace(mesh, "DG", degree) V0 = fd.FunctionSpace(mesh, "CG", degree + 2) W = fd.MixedFunctionSpace((V1, V2)) u, eta = fd.TrialFunctions(W) v, phi = fd.TestFunctions(W) Omega = fd.Constant(7.292e-5) # rotation rate f = 2 * Omega * cz / fd.Constant(R0) # Coriolis parameter g = fd.Constant(9.8) # Gravitational constant b = fd.Function(V2, name="Topography") c = fd.sqrt(g * H) dT = fd.Constant(0.) # D = eta + b def both(u): return 2 * fd.avg(u)
def create_subdm(dm, fields, *args, **kwargs): """Callback to create a sub-DM describing the specified fields. :arg DM: The DM. :arg fields: The fields in the new sub-DM. """ W = get_function_space(dm) ctx = get_appctx(dm) coarsen = get_ctx_coarsener(dm) parent = get_parent(dm) if len(fields) == 1: # Subspace is just a single FunctionSpace. idx, = fields subdm = W[idx].dm iset = W._ises[idx] add_hook(parent, setup=partial(push_parent, subdm, parent), teardown=partial(pop_parent, subdm, parent), call_setup=True) if ctx is not None: ctx, = ctx.split([(idx, )]) add_hook(parent, setup=partial(push_appctx, subdm, ctx), teardown=partial(pop_appctx, subdm, ctx), call_setup=True) add_hook(parent, setup=partial(push_ctx_coarsener, subdm, coarsen), teardown=partial(pop_ctx_coarsener, subdm, coarsen), call_setup=True) return iset, subdm else: # Need to build an MFS for the subspace subspace = firedrake.MixedFunctionSpace([W[f] for f in fields]) # Pass any transfer operators over transfer = get_transfer_operators(dm) add_hook(parent, setup=partial(push_transfer_operators, subspace.dm, transfer), teardown=partial(pop_transfer_operators, subspace.dm, transfer), call_setup=True) add_hook(parent, setup=partial(push_parent, subspace.dm, parent), teardown=partial(pop_parent, subspace.dm, parent), call_setup=True) # Index set mapping from W into subspace. iset = PETSc.IS().createGeneral(numpy.concatenate( [W._ises[f].indices for f in fields]), comm=W.comm) if ctx is not None: ctx, = ctx.split([fields]) add_hook(parent, setup=partial(push_appctx, subspace.dm, ctx), teardown=partial(pop_appctx, subspace.dm, ctx), call_setup=True) add_hook(parent, setup=partial(push_ctx_coarsener, subspace.dm, coarsen), teardown=partial(pop_ctx_coarsener, subspace.dm, coarsen), call_setup=True) return iset, subspace.dm