def Expression(f, V, degree_raise=None): if degree_raise != None: V = FunctionSpaceDegreeRaise(V, degree_raise) mesh_dim = V.mesh().cell_dimension() f_len = len(f) if mesh_dim == 1: x = SpatialCoordinate(V.mesh()) elif mesh_dim == 2: (x, y) = SpatialCoordinate(V.mesh()) elif mesh_dim == 3: (x, y, z) = SpatialCoordinate(V.mesh()) f_eval = [None] * f_len for i in range(f_len): if 'x' not in f[i] and 'y' not in f[i] and 'z' not in f[i]: f_eval[i] = Constant(eval(f[i])) else: f_eval[i] = eval(f[i]) if isinstance(f, list): if f_len == 1: out = interpolate(f_eval[0], V) elif f_len == 2: out = interpolate(as_vector([f_eval[0], f_eval[1]]), V) elif f_len == 3: out = interpolate(as_vector([f_eval[0], f_eval[1], f_eval[2]]), V) else: raise RuntimeError('Input list for function value is of ' 'dimension {}, need to be at most a 3D ' 'vector'.format(len(f))) return out else: raise RuntimeError('Input function f needs to be list')
def latlon_coords(mesh): x0, y0, z0 = SpatialCoordinate(mesh) unsafe = z0 / sqrt(x0 * x0 + y0 * y0 + z0 * z0) safe = Min(Max(unsafe, -1.0), 1.0) # avoid silly roundoff errors theta = asin(safe) # latitude lamda = atan_2(y0, x0) # longitude return theta, lamda
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 initialize(self, obj): if complex_mode: raise NotImplementedError("HypreAMS preconditioner not yet implemented in complex mode") Citations().register("Kolev2009") A, P = obj.getOperators() prefix = obj.getOptionsPrefix() V = get_function_space(obj.getDM()) mesh = V.mesh() family = str(V.ufl_element().family()) degree = V.ufl_element().degree() if family != 'Nedelec 1st kind H(curl)' or degree != 1: raise ValueError("Hypre AMS requires lowest order Nedelec elements! (not %s of degree %d)" % (family, degree)) P1 = FunctionSpace(mesh, "Lagrange", 1) G = Interpolator(grad(TestFunction(P1)), V).callable().handle pc = PETSc.PC().create(comm=obj.comm) pc.incrementTabLevel(1, parent=obj) pc.setOptionsPrefix(prefix + "hypre_ams_") pc.setOperators(A, P) pc.setType('hypre') pc.setHYPREType('ams') pc.setHYPREDiscreteGradient(G) zero_beta = PETSc.Options(prefix).getBool("pc_hypre_ams_zero_beta_poisson", default=False) if zero_beta: pc.setHYPRESetBetaPoissonMatrix(None) VectorP1 = VectorFunctionSpace(mesh, "Lagrange", 1) pc.setCoordinates(interpolate(SpatialCoordinate(mesh), VectorP1).dat.data_ro.copy()) pc.setUp() self.pc = pc
def compute(self, state): x, y, z = SpatialCoordinate(state.mesh) b = state.fields("b") bbar = state.fields("bbar") H = state.parameters.H potential = -(z - H / 2) * (b - bbar) return self.field.interpolate(potential)
def fdrake_mesh(request): mesh_name = request.param if mesh_name == "FiredrakeUnitIntervalMesh": return UnitIntervalMesh(100) elif mesh_name == "FiredrakeUnitSquareMesh": return UnitSquareMesh(10, 10) elif mesh_name == "FiredrakeUnitSquareMesh-order2": m = UnitSquareMesh(10, 10) fspace = VectorFunctionSpace(m, "CG", 2) coords = Function(fspace).interpolate(SpatialCoordinate(m)) from firedrake.mesh import Mesh return Mesh(coords) elif mesh_name == "FiredrakeUnitCubeMesh": return UnitCubeMesh(5, 5, 5) elif mesh_name not in ("annulus.msh", "blob2d-order1-h4e-2.msh", "blob2d-order1-h6e-2.msh", "blob2d-order1-h8e-2.msh"): raise ValueError("Unexpected value for request.param") # Firedrake can't read in higher order meshes from gmsh, # so we can only use the order1 blobs from firedrake import Mesh fd_mesh = Mesh(mesh_name) fd_mesh.init() return fd_mesh
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 test_upper_and_lower_bound_vector(self): """ Test that setting lower and upper bounds work as expected for vector functions. """ x = SpatialCoordinate(self.mesh) self.prob.to_bound = as_tensor([ Function(self.V).interpolate(x[0]), Function(self.V).interpolate(1 - x[0]) ]) self.prob.test_func = self.prob.to_bound + as_tensor([1, 1]) self.assertAlmostEqual(self.prob.test_func[0]([0.1, 0.1, 0.1]), 1.1) self.assertAlmostEqual(self.prob.test_func[1]([0.1, 0.1, 0.1]), 1.9) self.assertAlmostEqual(self.prob.test_func[0]([0.6, 0.1, 0.1]), 1.6) self.assertAlmostEqual(self.prob.test_func[1]([0.6, 0.1, 0.1]), 1.4) self.prob.bound('to_bound', lower=0.45, upper=0.55) self.assertAlmostEqual(self.prob.test_func[0]([0.1, 0.1, 0.1]), 1.45) self.assertAlmostEqual(self.prob.test_func[1]([0.1, 0.1, 0.1]), 1.55) self.assertAlmostEqual(self.prob.test_func[0]([0.6, 0.1, 0.1]), 1.55) self.assertAlmostEqual(self.prob.test_func[1]([0.6, 0.1, 0.1]), 1.45)
def setup_values(geometry, DG0_field, weights): x = SpatialCoordinate(weights.function_space().mesh()) coords_CG1 = Function(weights.function_space()).interpolate(x) coords_DG0 = Function(DG0_field.function_space()).interpolate(x) if geometry == "1D": # Let us focus on the point at x = 1.0 # The test is if at CG_field[CG_index] we get the average of the corresponding DG_field values CG_index = set_val_at_point(coords_CG1, 1.0) set_val_at_point(coords_DG0, 0.5, DG0_field, 6.0) set_val_at_point(coords_DG0, 1.5, DG0_field, -10.0) set_val_at_point(coords_CG1, 1.0, weights, 2.0) true_values = 0.5 * (6.0 - 10.0) elif geometry == "2D": # Let us focus on the point at (1,1) # The test is if at CG_field[CG_index] we get the average of the corresponding DG_field values # We do it for both components of the vector field CG_index = set_val_at_point(coords_CG1, [1.0, 1.0]) set_val_at_point(coords_CG1, [1.0, 1.0], weights, [4.0, 4.0]) set_val_at_point(coords_DG0, [0.5, 0.5], DG0_field, [6.0, -3.0]) set_val_at_point(coords_DG0, [1.5, 0.5], DG0_field, [-7.0, -6.0]) set_val_at_point(coords_DG0, [0.5, 1.5], DG0_field, [0.0, 3.0]) set_val_at_point(coords_DG0, [1.5, 1.5], DG0_field, [-9.0, -1.0]) true_values = [ 0.25 * (6.0 - 7.0 + 0.0 - 9.0), 0.25 * (-3.0 - 6.0 + 3.0 - 1.0) ] return DG0_field, weights, true_values, CG_index
def build(self): """ Build the gaussian function. Raises: AttributeError: If required properties are not defined. Returns: Function: firedrake Constant set to the given value. """ for k in self.properties: if self._props[k] is None: raise AttributeError('"{}" has not been defined.'.format(k)) mean = self._props['mean'] sd = self._props['sd'] scale = self._props['scale'] xs = SpatialCoordinate(self.mesh) if not isinstance(mean, list): mean = [mean] * len(xs) if not isinstance(sd, list): sd = [sd] * len(xs) gaussian = Function(self.V) components = [exp(-(x - m)**2 / 2 / s**2) for x, m, s in zip(xs, mean, sd)] product = components[0] for c in components[1:]: product *= c gaussian.interpolate(scale * product) return gaussian
def setup_values(geometry, true_field): # The true values can be determined by the number of elements # that the DoF is shared between. x = SpatialCoordinate(true_field.function_space().mesh()) coords_CG1 = Function(true_field.function_space()).interpolate(x) if geometry == "1D": # List coords of DoFs edge_coords = [0.0, 3.0] internal_coords = [1.0, 2.0] for coord in edge_coords: set_val_at_point(coords_CG1, coord, true_field, 1.0) for coord in internal_coords: set_val_at_point(coords_CG1, coord, true_field, 2.0) elif geometry == "2D": # List coords of DoFs corner_coords = [[0.0, 0.0], [0.0, 3.0], [3.0, 0.0], [3.0, 3.0]] edge_coords = [[0.0, 1.0], [0.0, 2.0], [3.0, 1.0], [3.0, 2.0], [1.0, 0.0], [2.0, 0.0], [1.0, 3.0], [2.0, 3.0]] internal_coords = [[1.0, 1.0], [1.0, 2.0], [2.0, 1.0], [2.0, 2.0]] for coord in corner_coords: set_val_at_point(coords_CG1, coord, true_field, 1.0) for coord in edge_coords: set_val_at_point(coords_CG1, coord, true_field, 2.0) for coord in internal_coords: set_val_at_point(coords_CG1, coord, true_field, 4.0) return true_field
def eady_initial_v(state, p0, v): f = state.parameters.f x, y, z = SpatialCoordinate(state.mesh) # get pressure gradient Vu = state.spaces("HDiv") g = TrialFunction(Vu) wg = TestFunction(Vu) n = FacetNormal(state.mesh) a = inner(wg, g)*dx L = -div(wg)*p0*dx + inner(wg, n)*p0*ds_tb pgrad = Function(Vu) solve(a == L, pgrad) # get initial v Vp = p0.function_space() phi = TestFunction(Vp) m = TrialFunction(Vp) a = f*phi*m*dx L = phi*pgrad[0]*dx solve(a == L, v) return v
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 tracer_sphere(tmpdir, degree): radius = 1 mesh = IcosahedralSphereMesh(radius=radius, refinement_level=3, degree=1) x = SpatialCoordinate(mesh) mesh.init_cell_orientations(x) # Parameters chosen so that dt != 1 # Gaussian is translated from (lon=pi/2, lat=0) to (lon=0, lat=0) # to demonstrate that transport is working correctly dt = pi / 3. * 0.02 output = OutputParameters(dirname=str(tmpdir), dumpfreq=15) state = State(mesh, dt=dt, output=output) umax = 1.0 uexpr = as_vector([-umax * x[1] / radius, umax * x[0] / radius, 0.0]) tmax = pi / 2 f_init = exp(-x[2]**2 - x[0]**2) f_end = exp(-x[2]**2 - x[1]**2) tol = 0.05 return TracerSetup(state, tmax, f_init, f_end, "BDM", degree, uexpr, umax, radius, tol)
def b(mesh, fs): v = TestFunction(fs) f = Function(fs) x = SpatialCoordinate(mesh) f.interpolate((4.*pi*pi)*sin(x[0]*pi*2)) L = f * v * dx b = assemble(L) return b
def run_tracer(setup): # Get initial conditions from shared config state = setup.state mesh = state.mesh dt = state.dt output = state.output x = SpatialCoordinate(state.mesh) H = 0.1 parameters = ShallowWaterParameters(H=H) Omega = parameters.Omega g = parameters.g umax = setup.umax R = setup.radius fexpr = 2 * Omega * x[2] / R # Need to create a new state containing parameters state = State(mesh, dt=dt, output=output, parameters=parameters) # Equations eqns = LinearShallowWaterEquations(state, setup.family, setup.degree, fexpr=fexpr) tracer_eqn = AdvectionEquation(state, state.spaces("DG"), "tracer") # Specify initial prognostic fields u0 = state.fields("u") D0 = state.fields("D") tracer0 = state.fields("tracer", D0.function_space()) tracer_end = Function(D0.function_space()) # Expressions for initial fields corresponding to Williamson 2 test case Dexpr = H - ((R * Omega * umax) * (x[2] * x[2] / (R * R))) / g u0.project(setup.uexpr) D0.interpolate(Dexpr) tracer0.interpolate(setup.f_init) tracer_end.interpolate(setup.f_end) # set up transport schemes transport_schemes = [ForwardEuler(state, "D")] # Set up tracer transport tracer_transport = [(tracer_eqn, SSPRK3(state))] # build time stepper stepper = CrankNicolson(state, eqns, transport_schemes, auxiliary_equations_and_schemes=tracer_transport) stepper.run(t=0, tmax=setup.tmax) error = norm(state.fields("tracer") - tracer_end) / norm(tracer_end) return error
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 f_end(geometry, state): """ returns an expression for the expected final state """ x = SpatialCoordinate(state.mesh) if geometry == "sphere": fexpr = exp(-x[2]**2 - x[0]**2) if geometry == "slice": fexpr = sin(2 * pi * (x[0] - 0.5)) * sin(2 * pi * x[1]) return fexpr
def f_init(geometry, state): """ returns an expression for the initial condition """ x = SpatialCoordinate(state.mesh) if geometry == "sphere": fexpr = exp(-x[2]**2 - x[1]**2) if geometry == "slice": fexpr = sin(2 * pi * x[0]) * sin(2 * pi * x[1]) return fexpr
def expr(geometry, mesh): x, = SpatialCoordinate(mesh) if geometry == "periodic": # N.B. this is a very trivial test -- no boundary recovery should happen analytic_expr = np.random.randn() + 0.0 * x elif geometry == "non-periodic": analytic_expr = np.random.randn() + np.random.randn() * x return analytic_expr
def expr(geometry, mesh): x, z = SpatialCoordinate(mesh) if geometry == "periodic": analytic_expr = np.random.randn() + np.random.randn() * z elif geometry == "non-periodic": analytic_expr = np.random.randn( ) + np.random.randn() * x + np.random.randn() * z return analytic_expr
def setup_IPdiffusion(dirname, vector, DG): dt = 0.01 L = 10. m = PeriodicIntervalMesh(50, L) mesh = ExtrudedMesh(m, layers=50, layer_height=0.2) fieldlist = ['u', 'D'] timestepping = TimesteppingParameters(dt=dt) parameters = CompressibleParameters() output = OutputParameters(dirname=dirname) state = State(mesh, vertical_degree=1, horizontal_degree=1, family="CG", timestepping=timestepping, parameters=parameters, output=output, fieldlist=fieldlist) x = SpatialCoordinate(mesh) if vector: kappa = Constant([[0.05, 0.], [0., 0.05]]) if DG: Space = VectorFunctionSpace(mesh, "DG", 1) else: Space = state.spaces("HDiv") fexpr = as_vector([exp(-(L / 2. - x[0])**2 - (L / 2. - x[1])**2), 0.]) else: kappa = 0.05 if DG: Space = state.spaces("DG") else: Space = state.spaces("HDiv_v") fexpr = exp(-(L / 2. - x[0])**2 - (L / 2. - x[1])**2) f = state.fields("f", Space) try: f.interpolate(fexpr) except NotImplementedError: # finat elements raise NotImplementedError if they don't # advertise a dual for interpolation. f.project(fexpr) mu = 5. f_diffusion = InteriorPenalty(state, f.function_space(), kappa=kappa, mu=mu) diffused_fields = [("f", f_diffusion)] stepper = AdvectionDiffusion(state, diffused_fields=diffused_fields) return stepper
def test_upper_bound_scalar(self): """ Test that setting upper bounds work as expected for normal functions. """ x = SpatialCoordinate(self.mesh) self.prob.to_bound.interpolate(x[0]) self.assertAlmostEqual(self.prob.test_func([0.1, 0.1, 0.1]), 1.1) self.assertAlmostEqual(self.prob.test_func([0.6, 0.1, 0.1]), 1.6) self.prob.bound('to_bound', upper=0.2) self.assertAlmostEqual(self.prob.test_func([0.1, 0.1, 0.1]), 1.1) self.assertAlmostEqual(self.prob.test_func([0.6, 0.1, 0.1]), 1.2)
def forcing_term(self): L = Forcing.forcing_term(self) dbdy = self.state.parameters.dbdy H = self.state.parameters.H Vp = self.state.spaces("DG") _, _, z = SpatialCoordinate(self.state.mesh) eady_exp = Function(Vp).interpolate(z - H / 2.) L -= self.scaling * dbdy * eady_exp * inner( self.test, as_vector([0., 1., 0.])) * dx return L
def state(tmpdir, geometry): """ returns an instance of the State class, having set up either spherical geometry or 2D vertical slice geometry """ output = OutputParameters(dirname=str(tmpdir), dumplist=["f"], dumpfreq=15) if geometry == "sphere": mesh = IcosahedralSphereMesh(radius=1, refinement_level=3, degree=1) x = SpatialCoordinate(mesh) mesh.init_cell_orientations(x) family = "BDM" vertical_degree = None fieldlist = ["u", "D"] dt = pi / 3. * 0.01 uexpr = as_vector([-x[1], x[0], 0.0]) if geometry == "slice": m = PeriodicIntervalMesh(15, 1.) mesh = ExtrudedMesh(m, layers=15, layer_height=1. / 15.) family = "CG" vertical_degree = 1 fieldlist = ["u", "rho", "theta"] dt = 0.01 x = SpatialCoordinate(mesh) uexpr = as_vector([1.0, 0.0]) timestepping = TimesteppingParameters(dt=dt) state = State(mesh, vertical_degree=vertical_degree, horizontal_degree=1, family=family, timestepping=timestepping, output=output, fieldlist=fieldlist) u0 = state.fields("u") u0.project(uexpr) return state
def run_advection_diffusion(tmpdir): # Mesh, state and equation L = 10 mesh = PeriodicIntervalMesh(20, L) dt = 0.02 tmax = 1.0 diffusion_params = DiffusionParameters(kappa=0.75, mu=5) output = OutputParameters(dirname=str(tmpdir), dumpfreq=25) state = State(mesh, dt=dt, output=output) V = state.spaces("DG", "DG", 1) Vu = VectorFunctionSpace(mesh, "CG", 1) equation = AdvectionDiffusionEquation( state, V, "f", Vu=Vu, diffusion_parameters=diffusion_params) problem = [(equation, ((SSPRK3(state), transport), (BackwardEuler(state), diffusion)))] # Initial conditions x = SpatialCoordinate(mesh) xc_init = 0.25 * L xc_end = 0.75 * L umax = 0.5 * L / tmax # Get minimum distance on periodic interval to xc x_init = conditional( sqrt((x[0] - xc_init)**2) < 0.5 * L, x[0] - xc_init, L + x[0] - xc_init) x_end = conditional( sqrt((x[0] - xc_end)**2) < 0.5 * L, x[0] - xc_end, L + x[0] - xc_end) f_init = 5.0 f_end = f_init / 2.0 f_width_init = L / 10.0 f_width_end = f_width_init * 2.0 f_init_expr = f_init * exp(-(x_init / f_width_init)**2) f_end_expr = f_end * exp(-(x_end / f_width_end)**2) state.fields('f').interpolate(f_init_expr) state.fields('u').interpolate(as_vector([Constant(umax)])) f_end = state.fields('f_end', V).interpolate(f_end_expr) # Time stepper timestepper = PrescribedTransport(state, problem) timestepper.run(0, tmax=tmax) error = norm(state.fields('f') - f_end) / norm(f_end) return error
def compute(self, state): x, y, z = SpatialCoordinate(state.mesh) g = state.parameters.g cp = state.parameters.cp cv = state.parameters.cv Pi0 = state.parameters.Pi0 rho = state.fields("rho") theta = state.fields("theta") Pi = thermodynamics.pi(state.parameters, rho, theta) potential = rho * (g * z + cv * Pi * theta - cp * Pi0 * theta) return self.field.interpolate(potential)
def set_initial_value(mesh, T, extent): """ Setup T to hold the initial value for the problem. mesh: Mesh, The mesh to define the function for T: Function, The function to define the initial value on extent: list<float>, The length of each side of the mesh (assumes rect) """ x = SpatialCoordinate(mesh) val = 1 for pos, length in zip(x, extent): val *= sin(2*pos/length*pi) T.interpolate(100 + 1000**val)
def create_S(mesh, V, extent): """ This is the source term. mesh: Mesh, The mesh to define the function for. V: FunctionSpace, The function space that the function should be in extent: list<float>, The length of each side of the mesh (assumes rect) """ x = SpatialCoordinate(mesh) val = 1 for pos, length in zip(x, extent): val *= sin(pos / length * pi)**2 return Function(V).interpolate(1e9 * val)
def tracer_blob_slice(tmpdir, degree): dt = 0.01 L = 10. m = PeriodicIntervalMesh(10, L) mesh = ExtrudedMesh(m, layers=10, layer_height=1.) output = OutputParameters(dirname=str(tmpdir), dumpfreq=25) state = State(mesh, dt=dt, output=output) tmax = 1. x = SpatialCoordinate(mesh) f_init = exp(-((x[0] - 0.5 * L)**2 + (x[1] - 0.5 * L)**2)) return TracerSetup(state, tmax, f_init, family="CG", degree=degree)