def test_recovered_space_setup(tmpdir, geometry, tracer_setup): # Make mesh and state using routine from conftest setup = tracer_setup(tmpdir, geometry, degree=0) state = setup.state mesh = state.mesh # Spaces for recovery VDG0 = FunctionSpace(mesh, "DG", 0) VDG1 = state.spaces("DG1_equispaced") VCG1 = FunctionSpace(mesh, "CG", 1) # Make equation eqn = ContinuityEquation(state, VDG0, "f", ufamily=setup.family, udegree=1) # Initialise fields state.fields("f").interpolate(setup.f_init) state.fields("u").project(setup.uexpr) # Declare transport scheme recovered_opts = RecoveredOptions(embedding_space=VDG1, recovered_space=VCG1, broken_space=VDG0, boundary_method=Boundary_Method.dynamics) transport_scheme = [(eqn, SSPRK3(state, options=recovered_opts))] # Run and check error error = run(state, transport_scheme, setup.tmax, setup.f_end) assert error < setup.tol, \ 'The transport error is greater than the permitted tolerance'
def test_gaussian_elimination(geometry, mesh): cell = mesh.ufl_cell().cellname() DG1_elt = FiniteElement("DG", cell, 1, variant="equispaced") DG1 = FunctionSpace(mesh, DG1_elt) vec_DG1 = VectorFunctionSpace(mesh, DG1_elt) act_coords = Function(vec_DG1) eff_coords = Function(vec_DG1) field_init = Function(DG1) field_true = Function(DG1) field_final = Function(DG1) # We now include things for the num of exterior values, which may be removed DG0 = FunctionSpace(mesh, "DG", 0) num_ext = Function(DG0) num_ext.dat.data[0] = 1.0 # Get initial and true conditions field_init, field_true, act_coords, eff_coords = setup_values( geometry, field_init, field_true, act_coords, eff_coords) kernel = kernels.GaussianElimination(DG1) kernel.apply(field_init, field_final, act_coords, eff_coords, num_ext) tolerance = 1e-12 assert abs(field_true.dat.data[0] - field_final.dat.data[0]) < tolerance assert abs(field_true.dat.data[1] - field_final.dat.data[1]) < tolerance if geometry == "2D": assert abs(field_true.dat.data[2] - field_final.dat.data[2]) < tolerance assert abs(field_true.dat.data[3] - field_final.dat.data[3]) < tolerance
def find_domain_boundaries(mesh): """ Makes a scalar DG0 function whose values are 0. everywhere except for in cells on the boundary of the domain, where the values are 1.0. This allows boundary cells to be identified easily. :arg mesh: the mesh. """ DG0 = FunctionSpace(mesh, "DG", 0) CG1 = FunctionSpace(mesh, "CG", 1) on_exterior_DG0 = Function(DG0) on_exterior_CG1 = Function(CG1) # we get values in CG1 initially as DG0 will not work for triangular elements bc_codes = ['on_boundary', 'top', 'bottom'] bcs = [DirichletBC(CG1, Constant(1.0), bc_code) for bc_code in bc_codes] for bc in bcs: try: bc.apply(on_exterior_CG1) except ValueError: pass on_exterior_DG0.interpolate(on_exterior_CG1) return on_exterior_DG0
def _bezier_plot(function, axes, **kwargs): """Plot a 1D function on a function space with order no more than 4 using Bezier curves within each cell :arg function: 1D :class:`~.Function` to plot :arg axes: :class:`Axes <matplotlib.axes.Axes>` for plotting :arg kwargs: additional key work arguments to plot :return: matplotlib :class:`PathPatch <matplotlib.patches.PathPatch>` """ deg = function.function_space().ufl_element().degree() mesh = function.function_space().mesh() if deg == 0: V = FunctionSpace(mesh, "DG", 1) func = Function(V).interpolate(function) return _bezier_plot(func, axes, **kwargs) y_vals = _bezier_calculate_points(function) x = SpatialCoordinate(mesh) coords = Function(FunctionSpace(mesh, 'DG', deg)) coords.interpolate(x[0]) x_vals = _bezier_calculate_points(coords) vals = np.dstack((x_vals, y_vals)) codes = {1: [Path.MOVETO, Path.LINETO], 2: [Path.MOVETO, Path.CURVE3, Path.CURVE3], 3: [Path.MOVETO, Path.CURVE4, Path.CURVE4, Path.CURVE4]} vertices = vals.reshape(-1, 2) path = Path(vertices, np.tile(codes[deg], function.function_space().cell_node_list.shape[0])) kwargs["facecolor"] = kwargs.pop("facecolor", "none") kwargs["linewidth"] = kwargs.pop("linewidth", 2.) patch = matplotlib.patches.PathPatch(path, **kwargs) axes.add_patch(patch) return patch
def __init__(self, mesh, conditions, timestepping, params, output, solver_params): self.timestepping = timestepping self.timestep = timestepping.timestep self.timescale = timestepping.timescale self.params = params if output is None: raise RuntimeError("You must provide a directory name for dumping results") else: self.output = output self.outfile = File(output.dirname) self.dump_count = 0 self.dump_freq = output.dumpfreq self.solver_params = solver_params self.mesh = mesh self.conditions = conditions if conditions.steady_state == True: self.ind = 1 else: self.ind = 1 family = conditions.family self.x, self.y = SpatialCoordinate(mesh) self.n = FacetNormal(mesh) self.V = VectorFunctionSpace(mesh, family, conditions.order + 1) self.U = FunctionSpace(mesh, family, conditions.order + 1) self.U1 = FunctionSpace(mesh, 'DG', conditions.order) self.S = TensorFunctionSpace(mesh, 'DG', conditions.order) self.D = FunctionSpace(mesh, 'DG', 0) self.W1 = MixedFunctionSpace([self.V, self.S]) self.W2 = MixedFunctionSpace([self.V, self.U1, self.U1]) self.W3 = MixedFunctionSpace([self.V, self.S, self.U1, self.U1])
def test_physics_recovery_kernels(boundary): m = IntervalMesh(3, 3) mesh = ExtrudedMesh(m, layers=3, layer_height=1.0) cell = m.ufl_cell().cellname() hori_elt = FiniteElement("DG", cell, 0) vert_elt = FiniteElement("CG", interval, 1) theta_elt = TensorProductElement(hori_elt, vert_elt) Vt = FunctionSpace(mesh, theta_elt) Vt_brok = FunctionSpace(mesh, BrokenElement(theta_elt)) initial_field = Function(Vt) true_field = Function(Vt_brok) new_field = Function(Vt_brok) initial_field, true_field = setup_values(boundary, initial_field, true_field) kernel = kernels.PhysicsRecoveryTop( ) if boundary == "top" else kernels.PhysicsRecoveryBottom() kernel.apply(new_field, initial_field) tolerance = 1e-12 index = 11 if boundary == "top" else 6 assert abs(true_field.dat.data[index] - new_field.dat.data[index]) < tolerance, \ "Value at %s from physics recovery is not correct" % boundary
def test_1D_recovery(geometry, mesh, expr): # horizontal base spaces cell = mesh.ufl_cell().cellname() # DG1 DG1_elt = FiniteElement("DG", cell, 1, variant="equispaced") DG1 = FunctionSpace(mesh, DG1_elt) # spaces DG0 = FunctionSpace(mesh, "DG", 0) CG1 = FunctionSpace(mesh, "CG", 1) # our actual theta and rho and v rho_CG1_true = Function(CG1).interpolate(expr) # make the initial fields by projecting expressions into the lowest order spaces rho_DG0 = Function(DG0).interpolate(expr) rho_CG1 = Function(CG1) # make the recoverers and do the recovery rho_recoverer = Recoverer(rho_DG0, rho_CG1, VDG=DG1, boundary_method=Boundary_Method.dynamics) rho_recoverer.project() rho_diff = errornorm(rho_CG1, rho_CG1_true) / norm(rho_CG1_true) tolerance = 1e-7 error_message = (""" Incorrect recovery for {variable} with {boundary} boundary method on {geometry} 1D domain """) assert rho_diff < tolerance, error_message.format(variable='rho', boundary='dynamics', geometry=geometry)
def setup_2d_recovery(dirname): L = 100. W = 100. deltax = L / 5. deltay = W / 5. ncolumnsx = int(L / deltax) ncolumnsy = int(W / deltay) mesh = PeriodicRectangleMesh(ncolumnsx, ncolumnsy, L, W, direction='y', quadrilateral=True) x, y = SpatialCoordinate(mesh) # spaces VDG0 = FunctionSpace(mesh, "DG", 0) VCG1 = FunctionSpace(mesh, "CG", 1) VDG1 = FunctionSpace(mesh, "DG", 1) Vu = FunctionSpace(mesh, "RTCF", 1) VuCG1 = VectorFunctionSpace(mesh, "CG", 1) VuDG1 = VectorFunctionSpace(mesh, "DG", 1) # set up initial conditions np.random.seed(0) expr = np.random.randn() + np.random.randn() * x # our actual theta and rho and v rho_CG1_true = Function(VCG1).interpolate(expr) v_CG1_true = Function(VuCG1).interpolate(as_vector([expr, expr])) # make the initial fields by projecting expressions into the lowest order spaces rho_DG0 = Function(VDG0).interpolate(expr) rho_CG1 = Function(VCG1) v_Vu = Function(Vu).project(as_vector([expr, expr])) v_CG1 = Function(VuCG1) # make the recoverers and do the recovery rho_recoverer = Recoverer(rho_DG0, rho_CG1, VDG=VDG1, boundary_method=Boundary_Method.dynamics) v_recoverer = Recoverer(v_Vu, v_CG1, VDG=VuDG1, boundary_method=Boundary_Method.dynamics) rho_recoverer.project() v_recoverer.project() rho_diff = errornorm(rho_CG1, rho_CG1_true) / norm(rho_CG1_true) v_diff = errornorm(v_CG1, v_CG1_true) / norm(v_CG1_true) return (rho_diff, v_diff)
def test_2D_cartesian_recovery(geometry, element, mesh, expr): family = "RTCF" if element == "quadrilateral" else "BDM" # horizontal base spaces cell = mesh.ufl_cell().cellname() # DG1 DG1_elt = FiniteElement("DG", cell, 1, variant="equispaced") DG1 = FunctionSpace(mesh, DG1_elt) vec_DG1 = VectorFunctionSpace(mesh, DG1_elt) # spaces DG0 = FunctionSpace(mesh, "DG", 0) CG1 = FunctionSpace(mesh, "CG", 1) Vu = FunctionSpace(mesh, family, 1) vec_CG1 = VectorFunctionSpace(mesh, "CG", 1) # our actual theta and rho and v rho_CG1_true = Function(CG1).interpolate(expr) v_CG1_true = Function(vec_CG1).interpolate(as_vector([expr, expr])) # make the initial fields by projecting expressions into the lowest order spaces rho_DG0 = Function(DG0).interpolate(expr) rho_CG1 = Function(CG1) v_Vu = Function(Vu).project(as_vector([expr, expr])) v_CG1 = Function(vec_CG1) # make the recoverers and do the recovery rho_recoverer = Recoverer(rho_DG0, rho_CG1, VDG=DG1, boundary_method=Boundary_Method.dynamics) v_recoverer = Recoverer(v_Vu, v_CG1, VDG=vec_DG1, boundary_method=Boundary_Method.dynamics) rho_recoverer.project() v_recoverer.project() rho_diff = errornorm(rho_CG1, rho_CG1_true) / norm(rho_CG1_true) v_diff = errornorm(v_CG1, v_CG1_true) / norm(v_CG1_true) tolerance = 1e-7 error_message = (""" Incorrect recovery for {variable} with {boundary} boundary method on {geometry} 2D Cartesian plane with {element} elements """) assert rho_diff < tolerance, error_message.format(variable='rho', boundary='dynamics', geometry=geometry, element=element) assert v_diff < tolerance, error_message.format(variable='v', boundary='dynamics', geometry=geometry, element=element)
def wave(n, deg, butcher_tableau, splitting=AI): N = 2**n msh = UnitIntervalMesh(N) params = { "snes_type": "ksponly", "ksp_type": "preonly", "mat_type": "aij", "pc_type": "lu" } V = FunctionSpace(msh, "CG", deg) W = FunctionSpace(msh, "DG", deg - 1) Z = V * W x, = SpatialCoordinate(msh) t = Constant(0.0) dt = Constant(2.0 / N) up = project(as_vector([0, sin(pi * x)]), Z) u, p = split(up) v, w = TestFunctions(Z) F = (inner(Dt(u), v) * dx + inner(u.dx(0), w) * dx + inner(Dt(p), w) * dx - inner(p, v.dx(0)) * dx) E = 0.5 * (inner(u, u) * dx + inner(p, p) * dx) stepper = TimeStepper(F, butcher_tableau, t, dt, up, solver_parameters=params, splitting=splitting) energies = [] while (float(t) < 1.0): if (float(t) + float(dt) > 1.0): dt.assign(1.0 - float(t)) stepper.advance() t.assign(float(t) + float(dt)) energies.append(assemble(E)) return np.array(energies)
def setUp(self): """ Create the parser. """ mesh = UnitCubeMesh(10, 10, 10) V = FunctionSpace(mesh, 'CG', 1) self.parser = InitialValParser(mesh=mesh, V=V)
def setup(self, state, vorticity_type=None): """Solver for vorticity. :arg state: The state containing model. :arg vorticity_type: must be "relative", "absolute" or "potential" """ if not self._initialised: vorticity_types = ["relative", "absolute", "potential"] if vorticity_type not in vorticity_types: raise ValueError("vorticity type must be one of %s, not %s" % (vorticity_types, vorticity_type)) try: space = state.spaces("CG") except AttributeError: dgspace = state.spaces("DG") cg_degree = dgspace.ufl_element().degree() + 2 space = FunctionSpace(state.mesh, "CG", cg_degree) super().setup(state, space=space) u = state.fields("u") gamma = TestFunction(space) q = TrialFunction(space) if vorticity_type == "potential": D = state.fields("D") a = q*gamma*D*dx else: a = q*gamma*dx L = (- inner(state.perp(grad(gamma)), u))*dx if vorticity_type != "relative": f = state.fields("coriolis") L += gamma*f*dx problem = LinearVariationalProblem(a, L, self.field) self.solver = LinearVariationalSolver(problem, solver_parameters={"ksp_type": "cg"})
def setup(self, state): if not self._initialised: space = state.fields("theta").function_space() broken_space = FunctionSpace(state.mesh, BrokenElement(space.ufl_element())) boundary_method = Boundary_Method.physics if (state.vertical_degree == 0 and state.horizontal_degree == 0) else None super().setup(state, space=space) # now let's attach all of our fields self.u = state.fields("u") self.rho = state.fields("rho") self.theta = state.fields("theta") self.rho_averaged = Function(space) self.recoverer = Recoverer(self.rho, self.rho_averaged, VDG=broken_space, boundary_method=boundary_method) try: self.r_v = state.fields("water_v") except NotImplementedError: self.r_v = Constant(0.0) try: self.r_c = state.fields("water_c") except NotImplementedError: self.r_c = Constant(0.0) try: self.rain = state.fields("rain") except NotImplementedError: self.rain = Constant(0.0) # now let's store the most common expressions self.pi = thermodynamics.pi(state.parameters, self.rho_averaged, self.theta) self.T = thermodynamics.T(state.parameters, self.theta, self.pi, r_v=self.r_v) self.p = thermodynamics.p(state.parameters, self.pi) self.r_l = self.r_c + self.rain self.r_t = self.r_v + self.r_c + self.rain
def _plot_2d_field(method_name, function, *args, complex_component="real", **kwargs): axes = kwargs.pop("axes", None) if axes is None: figure = plt.figure() axes = figure.add_subplot(111) Q = function.function_space() mesh = Q.mesh() if len(function.ufl_shape) == 1: element = function.ufl_element().sub_elements()[0] Q = FunctionSpace(mesh, element) function = interpolate(sqrt(inner(function, function)), Q) num_sample_points = kwargs.pop("num_sample_points", 10) function_plotter = FunctionPlotter(mesh, num_sample_points) triangulation = function_plotter.triangulation values = function_plotter(function) method = getattr(axes, method_name) return method(triangulation, toreal(values, complex_component), *args, **kwargs)
def setup(self, state): if not self._initialised: Vu = state.spaces("HDiv") space = FunctionSpace(state.mesh, Vu.ufl_element()._elements[-1]) super().setup(state, space=space) rho = state.fields("rho") rhobar = state.fields("rhobar") theta = state.fields("theta") thetabar = state.fields("thetabar") exner = thermodynamics.exner_pressure(state.parameters, rho, theta) exnerbar = thermodynamics.exner_pressure(state.parameters, rhobar, thetabar) cp = Constant(state.parameters.cp) n = FacetNormal(state.mesh) F = TrialFunction(space) w = TestFunction(space) a = inner(w, F) * dx L = (-cp * div((theta - thetabar) * w) * exnerbar * dx + cp * jump( (theta - thetabar) * w, n) * avg(exnerbar) * dS_v - cp * div(thetabar * w) * (exner - exnerbar) * dx + cp * jump(thetabar * w, n) * avg(exner - exnerbar) * dS_v) bcs = [ DirichletBC(space, 0.0, "bottom"), DirichletBC(space, 0.0, "top") ] imbalanceproblem = LinearVariationalProblem(a, L, self.field, bcs=bcs) self.imbalance_solver = LinearVariationalSolver(imbalanceproblem)
def __init__(self, mesh, nu, rho, dt=0.001, verbose=False): self.verbose = verbose self.mesh = mesh self.dt = dt self.nu = nu self.rho = rho self.mu = self.nu * self.rho self.has_nullspace = False self.forcing = Constant((0.0, 0.0, 0.0)) self.V = VectorFunctionSpace(self.mesh, "CG", 2) self.Q = FunctionSpace(self.mesh, "CG", 1) self.W = self.V * self.Q self.solver_parameters = { "mat_type": "aij", "snes_type": "ksponly", "ksp_type": "fgmres", "pc_type": "asm", "pc_asm_type": "restrict", "pc_asm_overlap": 2, "sub_ksp_type": "preonly", "sub_pc_type": "ilu", "sub_pc_factor_levels": 1, } if self.verbose: self.solver_parameters["snes_monitor"] = True self.solver_parameters["ksp_converged_reason"] = True
def setup(self, state): if not self._initialised: # check geometric dimension is 3D if state.mesh.geometric_dimension() != 3: raise ValueError( 'Spherical components only work when the geometric dimension is 3!' ) space = FunctionSpace(state.mesh, "CG", 1) super().setup(state, space=space) V = VectorFunctionSpace(state.mesh, "CG", 1) self.x, self.y, self.z = SpatialCoordinate(state.mesh) self.x_hat = Function(V).interpolate( Constant(as_vector([1.0, 0.0, 0.0]))) self.y_hat = Function(V).interpolate( Constant(as_vector([0.0, 1.0, 0.0]))) self.z_hat = Function(V).interpolate( Constant(as_vector([0.0, 0.0, 1.0]))) self.R = sqrt(self.x**2 + self.y**2) # distance from z axis self.r = sqrt(self.x**2 + self.y**2 + self.z**2) # distance from origin self.f = state.fields(self.fname) if np.prod(self.f.ufl_shape) != 3: raise ValueError( 'Components can only be found of a vector function space in 3D.' )
def __init__(self, state, V, ibp=IntegrateByParts.ONCE, equation_form="advective", vector_manifold=False, solver_params=None, outflow=False, options=None): if options is None: raise ValueError( "Must provide an instance of the AdvectionOptions class") else: self.options = options if options.name == "embedded_dg" and options.embedding_space is None: V_elt = BrokenElement(V.ufl_element()) options.embedding_space = FunctionSpace(state.mesh, V_elt) super().__init__(state=state, V=options.embedding_space, ibp=ibp, equation_form=equation_form, vector_manifold=vector_manifold, solver_params=solver_params, outflow=outflow)
def setUp(self): """ Create the parser. """ mesh = UnitCubeMesh(10, 10, 10) V = FunctionSpace(mesh, 'CG', 1) self.parser = BoundaryCondsParser(mesh=mesh, V=V)
def setUp(self): """ Define the function builder. """ m = UnitCubeMesh(10, 10, 10) V = FunctionSpace(m, 'CG', 1) self.func_builder = DummyFunctionBuilder(m, V)
def setUp(self): """ Create a builder. """ m = UnitIntervalMesh(100) V = FunctionSpace(m, 'CG', 1) self.builder = GaussianBuilder(m, V)
def trisurf(function, *args, **kwargs): r"""Create a 3D surface plot of a 2D Firedrake :class:`~.Function` If the input function is a vector field, the magnitude will be plotted. :arg function: the Firedrake :class:`~.Function` to plot :arg args: same as for matplotlib :meth:`plot_trisurf <mpl_toolkits.mplot3d.axes3d.Axes3D.plot_trisurf>` :arg kwargs: same as for matplotlib :return: matplotlib :class:`Poly3DCollection <mpl_toolkits.mplot3d.art3d.Poly3DCollection>` object """ axes = kwargs.pop("axes", None) if axes is None: figure = plt.figure() axes = figure.add_subplot(111, projection='3d') _kwargs = {"antialiased": False, "edgecolor": "none", "cmap": plt.rcParams["image.cmap"]} _kwargs.update(kwargs) mesh = function.ufl_domain() if mesh.geometric_dimension() == 3: return _trisurf_3d(axes, function, *args, **_kwargs) if len(function.ufl_shape) == 1: element = function.ufl_element().sub_elements()[0] Q = FunctionSpace(mesh, element) function = interpolate(sqrt(inner(function, function)), Q) num_sample_points = kwargs.pop("num_sample_points", 10) coords, vals, triangles = _two_dimension_triangle_func_val(function, num_sample_points) x, y = coords[:, 0], coords[:, 1] triangulation = matplotlib.tri.Triangulation(x, y, triangles=triangles) _kwargs.update({"shade": False}) return axes.plot_trisurf(triangulation, vals, *args, **_kwargs)
def setUp(self): """ Setup the mesh and function space. """ self.m = UnitCubeMesh(10, 10, 10) self.V = FunctionSpace(self.m, 'CG', 1) self.out_dir = TemporaryDirectory()
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
def __call__(self, name, mesh=None, family=None, degree=None): try: return getattr(self, name) except AttributeError: value = FunctionSpace(mesh, family, degree) setattr(self, name, value) return value
def setUp(self): """ Prepare for tests. """ mesh = UnitCubeMesh(10, 10, 10) V = FunctionSpace(mesh, 'CG', 1) self.problem = MockProblem(mesh, V)
def _plot_2d_field(method_name, function, *args, complex_component="real", **kwargs): axes = kwargs.pop("axes", None) if axes is None: figure = plt.figure() axes = figure.add_subplot(111) if len(function.ufl_shape) == 1: mesh = function.ufl_domain() element = function.ufl_element().sub_elements()[0] Q = FunctionSpace(mesh, element) function = interpolate(sqrt(inner(function, function)), Q) num_sample_points = kwargs.pop("num_sample_points", 10) coords, vals, triangles = _two_dimension_triangle_func_val( function, num_sample_points) coords = toreal(coords, "real") x, y = coords[:, 0], coords[:, 1] triangulation = matplotlib.tri.Triangulation(x, y, triangles=triangles) method = getattr(axes, method_name) return method(triangulation, toreal(vals, complex_component), *args, **kwargs)
def setUp(self): """ Create a factory. """ self.mesh = UnitCubeMesh(10, 10, 10) self.V = FunctionSpace(self.mesh, 'CG', 1) self.factory = FunctionBuilderFactory(self.mesh, self.V)
def build_theta_space(self, degree): assert self.extruded_mesh if not self._initialised_base_spaces: cell = self.mesh._base_mesh.ufl_cell().cellname() self.S2 = FiniteElement("DG", cell, degree) self.T0 = FiniteElement("CG", interval, degree + 1) V_elt = TensorProductElement(self.S2, self.T0) return FunctionSpace(self.mesh, V_elt, name='Vtheta')
def max_courant_number(self, u, dt): if not hasattr(self, "_area"): V = FunctionSpace(u.function_space().mesh(), "DG", 0) expr = TestFunction(V) * dx self._area = assemble(expr) self.Courant = Function(V) self.Courant.project(sqrt(inner(u, u)) / sqrt(self._area) * dt) return self.Courant.dat.data.max()
def argument(self, o): from ufl import split from firedrake import MixedFunctionSpace, FunctionSpace V = o.function_space() if len(V) == 1: # Not on a mixed space, just return ourselves. return o if o in self._arg_cache: return self._arg_cache[o] V_is = V.split() indices = self.blocks[o.number()] try: indices = tuple(indices) nidx = len(indices) except TypeError: # Only one index provided. indices = (indices, ) nidx = 1 if nidx == 1: W = V_is[indices[0]] W = FunctionSpace(W.mesh(), W.ufl_element()) a = (Argument(W, o.number(), part=o.part()), ) else: W = MixedFunctionSpace([V_is[i] for i in indices]) a = split(Argument(W, o.number(), part=o.part())) args = [] for i in range(len(V_is)): if i in indices: c = indices.index(i) a_ = a[c] if len(a_.ufl_shape) == 0: args += [a_] else: args += [a_[j] for j in numpy.ndindex(a_.ufl_shape)] else: args += [Zero() for j in numpy.ndindex( V_is[i].ufl_element().value_shape())] return self._arg_cache.setdefault(o, as_vector(args))