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 update_constants(self): """ Update p and q constants from true peakon data. """ self.p.assign(self.true_peakon_file['p'][self.outputting.t_idx] * 0.5 * (1 + exp(-self.Ld / sqrt(self.alphasq))) / (1 - exp(-self.Ld / sqrt(self.alphasq)))) self.q.assign(self.true_peakon_file['q'][self.outputting.t_idx])
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 get_true_sol_expr(spatial_coord, kappa): if mesh_dim == 3: x, y, z = spatial_coord norm = sqrt(x**2 + y**2 + z**2) return Constant(1j / (4 * pi)) / norm * exp(1j * kappa * norm) elif mesh_dim == 2: x, y = spatial_coord return Constant(1j / 4) * hankel_function(kappa * sqrt(x**2 + y**2), n=hankel_cutoff) raise ValueError("Only meshes of dimension 2, 3 supported")
def _K(self): """ Create the function that defines the conductivity. Returns: Function: The Spitzer-Harm conductivity """ tmp = 288 * pi * sqrt(2) * epsilon_0**2 / sqrt(e * m_e) tmp = tmp * pow(self.T, 5 / 2) / (self.coulomb_ln * self.ionisation) return tmp
def get_true_sol_expr(spatial_coord, wave_number): mesh_dim = len(spatial_coord) if mesh_dim == 3: x, y, z = spatial_coord norm = sqrt(x**2 + y**2 + z**2) return Constant(1j / (4 * pi)) / norm * exp(1j * wave_number * norm) elif mesh_dim == 2: x, y = spatial_coord return Constant(1j / 4) * hankel_function( wave_number * sqrt(x**2 + y**2), n=80) raise ValueError("Only meshes of dimension 2, 3 supported")
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 write_output(diag, t, counter, dfr, nc_h5_dfr, outf, outf_ll, fld_out, fld_out_ll): """Function to write vtu, txt output""" # Update and output diagnostics energy = e_form(un, Dn) En.interpolate(energy) if 'Energy' in diag.keys(): diag['Energy'] = assemble(energy * dx) if 'Mass' in diag.keys(): diag['Mass'] = assemble(Dn * dx) if 'Enstrophy' in diag.keys(): diag['Enstrophy'] = assemble(qn**2 * Dn * dx) if 'L2_error_D' in diag.keys(): diag['L2_error_D'] = sqrt(assemble((Dn - D0) * (Dn - D0) * dx)) if 'L2_error_u' in diag.keys(): diag['L2_error_u'] = sqrt(assemble(inner(un - u0, un - u0) * dx)) _c = 0 for k in diag: nc_temp[counter % nc_h5_dfr][_c] = diag[k] _c += 1 # Save I/O time by not writing at each timestep if (counter % nc_h5_dfr) == nc_h5_dfr - 1: if COMM_WORLD.Get_rank() == 0: print("Timestep nr", counter, ": Writing nc files at", ctime()) write_to_nc_file(t, nc_temp) if nc_safe: write_to_nc_file(t, nc_temp, '_bckp') # Write to checkpoint chkpt.store(xn) chkpt.write_attribute("/", "time", t) if h5_safe: chkpt_bckp.store(xn) chkpt_bckp.write_attribute("/", "time", t) # Output vtu file if t in field_dumptimes: #q2Dn.project(qn**2*Dn) #eta_out.interpolate(Dn + b) #vortsolver.solve() u_err.assign(un - u0) D_err.assign(Dn - D0) q_err.assign(qn - q0) outf.write(*fld_out) if write_latlon: outf_ll.write(*fld_out_ll)
def norm(u, norm_type="L2"): r"""Compute the norm of a field Computes one of any number of norms of a scalar or vector field. The available options are: - ``L2``: :math:`\|u\|^2 = \int_\Omega|u|^2dx` - ``H01``: :math:`\|u\|^2 = \int_\Omega|\nabla u|^2dx` - ``H1``: :math:`\|u\|^2 = \int_\Omega\left(|u|^2 + L^2|\nabla u|^2\right)dx` - ``L1``: :math:`\|u\| = \int_\Omega|u|dx` - ``TV``: :math:`\|u\| = \int_\Omega|\nabla u|dx` - ``Linfty``: :math:`\|u\| = \max_{x\in\Omega}|u(x)|` The extra factor :math:`L` in the :math:`H^1` norm is the diameter of the domain in the infinity metric. This extra factor is included to make the norm scale appropriately with the size of the domain. """ if norm_type == "L2": form, p = inner(u, u) * dx, 2 if norm_type == "H01": form, p = inner(grad(u), grad(u)) * dx, 2 if norm_type == "H1": L = utilities.diameter(u.ufl_domain()) form, p = inner(u, u) * dx + L**2 * inner(grad(u), grad(u)) * dx, 2 if norm_type == "L1": form, p = sqrt(inner(u, u)) * dx, 1 if norm_type == "TV": form, p = sqrt(inner(grad(u), grad(u))) * dx, 1 if norm_type == "Linfty": data = u.dat.data_ro if len(data.shape) == 1: local_max = np.max(np.abs(data)) elif len(data.shape) == 2: local_max = np.max(np.sqrt(np.sum(data**2, 1))) return u.comm.allreduce(local_max, op=max) return assemble(form)**(1 / p)
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 _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 referencemesh(mesh, b, hinitial, Href): '''In-place modification of an extruded mesh to create the reference mesh. Changes the top surface to lambda = b + sqrt(Href^2 + (Hinitial - b)^2). Assumes b,hinitial are Functions defined on the base mesh. Assumes the input mesh is extruded 3D mesh with 0 <= z <= 1.''' if not _admissible(b, hinitial): assert ValueError('input hinitial not admissible') P1base = fd.FunctionSpace(mesh._base_mesh, 'P', 1) HH = fd.Function(P1base).interpolate(hinitial - b) # alternative: #lambase = fd.Function(P1base).interpolate(b + fd.max_value(Href, Hstart)) lambase = fd.Function(P1base).interpolate(b + fd.sqrt(HH**2 + Href**2)) lam = extend(mesh, lambase) Vcoord = mesh.coordinates.function_space() if mesh._base_mesh.cell_dimension() == 1: x, z = fd.SpatialCoordinate(mesh) XX = fd.Function(Vcoord).interpolate(fd.as_vector([x, lam * z])) elif mesh._base_mesh.cell_dimension() == 2: x, y, z = fd.SpatialCoordinate(mesh) XX = fd.Function(Vcoord).interpolate(fd.as_vector([x, y, lam * z])) else: raise ValueError('only 2D and 3D reference meshes are generated') mesh.coordinates.assign(XX) return 0
def Bueler_profile(mesh, R): x, y = firedrake.SpatialCoordinate(mesh) r = firedrake.sqrt(x**2 + y**2) h_divide = (2 * R * (alpha/A0)**(1/n) * (n-1)/n)**(n/(2*n+2)) h_part2 = (n+1)*(r/R) - n*(r/R)**((n+1)/n) + n*(max_value(1-(r/R),0))**((n+1)/n) - 1 h_expr = (h_divide/((n-1)**(n/(2*n+2)))) * (max_value(h_part2,0))**(n/(2*n+2)) return h_expr
def equation(z): Z = z.function_space() φ, v = firedrake.TestFunctions(Z) h, q = firedrake.split(z) F_h, F_q = _fluxes(h, q, g) mesh = Z.mesh() n = firedrake.FacetNormal(mesh) c = abs(inner(q / h, n)) + sqrt(g * h) sources = -inner(g * h * grad(b), v) * dx fluxes = (forms.cell_flux(F_h, φ) + forms.central_facet_flux(F_h, φ) + forms.lax_friedrichs_facet_flux(h, c, φ) + forms.cell_flux(F_q, v) + forms.central_facet_flux(F_q, v) + forms.lax_friedrichs_facet_flux(q, c, v)) boundary_ids = set(mesh.exterior_facets.unique_markers) wall_ids = tuple(boundary_ids - set(outflow_ids) - set(inflow_ids)) q_wall = q - 2 * inner(q, n) * n boundary_fluxes = ( _boundary_flux(z, h, q, g, outflow_ids) + _boundary_flux(z, h_in, q_in, g, inflow_ids) + _boundary_flux(z, h, q_wall, g, wall_ids) + forms.lax_friedrichs_boundary_flux(h, h, c, φ, outflow_ids) + forms.lax_friedrichs_boundary_flux(q, q, c, v, outflow_ids) + forms.lax_friedrichs_boundary_flux(h, h_in, c, φ, inflow_ids) + forms.lax_friedrichs_boundary_flux(q, q_in, c, v, inflow_ids) + forms.lax_friedrichs_boundary_flux(h, h, c, φ, wall_ids) + forms.lax_friedrichs_boundary_flux(q, q_wall, c, v, wall_ids)) return sources - fluxes - boundary_fluxes
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 _K_min(self): r_ii = (3 / (4 * pi * self.ion_density))**(1 / 3) tau_min = r_ii / self.v_th tmp = 48 * self.ionisation * self.ion_density * e**2 * self.T * tau_min tmp = tmp / sqrt(pi) / m_e return tmp
def create_conductivity(mesh, V, T): """ This is the conductivity term. Here we use the spitzer-harm conductivity. mesh: Mesh, The mesh to define the function for. V: FunctionSpace, The function space that the function should be in T: Function, The temperature of the plasma. """ coulomb_ln = create_coulomb_ln(mesh, V) Z = create_Z(mesh, V) tmp = 288 * pi * sqrt(2) * epsilon_0**2 / sqrt(e * m_e) tmp = tmp * pow(T, 5 / 2) / (coulomb_ln * Z) return tmp
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 setup_solver(self, up_init=None): """ Setup the solvers """ self.up0 = Function(self.W) if up_init is not None: chk_in = checkpointing.HDF5File(up_init, file_mode='r') chk_in.read(self.up0, "/up") chk_in.close() self.u0, self.p0 = split(self.up0) self.up = Function(self.W) if up_init is not None: chk_in = checkpointing.HDF5File(up_init, file_mode='r') chk_in.read(self.up, "/up") chk_in.close() self.u1, self.p1 = split(self.up) self.up.sub(0).rename("velocity") self.up.sub(1).rename("pressure") v, q = TestFunctions(self.W) h = CellVolume(self.mesh) u_norm = sqrt(dot(self.u0, self.u0)) if self.has_nullspace: nullspace = MixedVectorSpaceBasis( self.W, [self.W.sub(0), VectorSpaceBasis(constant=True)]) else: nullspace = None tau = ((2.0 / self.dt)**2 + (2.0 * u_norm / h)**2 + (4.0 * self.nu / h**2)**2)**(-0.5) # temporal discretization F = (1.0 / self.dt) * inner(self.u1 - self.u0, v) * dx # weak form F += (+inner(dot(self.u0, nabla_grad(self.u1)), v) * dx + self.nu * inner(grad(self.u1), grad(v)) * dx - (1.0 / self.rho) * self.p1 * div(v) * dx + div(self.u1) * q * dx - inner(self.forcing, v) * dx) # residual form R = (+(1.0 / self.dt) * (self.u1 - self.u0) + dot(self.u0, nabla_grad(self.u1)) - self.nu * div(grad(self.u1)) + (1.0 / self.rho) * grad(self.p1) - self.forcing) # GLS F += tau * inner( +dot(self.u0, nabla_grad(v)) - self.nu * div(grad(v)) + (1.0 / self.rho) * grad(q), R) * dx self.problem = NonlinearVariationalProblem(F, self.up, self.bcs) self.solver = NonlinearVariationalSolver( self.problem, nullspace=nullspace, solver_parameters=self.solver_parameters)
def eigenvalues(a): r"""Return a pair of symbolic expressions for the largest and smallest eigenvalues of a 2D rank-2 tensor""" tr_a = tr(a) det_a = det(a) # TODO: Fret about numerical stability Δ = sqrt(tr_a**2 - 4 * det_a) return ((tr_a + Δ) / 2, (tr_a - Δ) / 2)
def stresses(ε_x, ε_z, A): r"""Calculate the membrane and vertical shear stresses for the given horizontal and shear strain rates and fluidity""" I = Identity(2) tr = trace(ε_x) ε_e = sqrt((inner(ε_x, ε_x) + inner(ε_z, ε_z) + tr**2) / 2) μ = 0.5 * A**(-1 / n) * ε_e**(1 / n - 1) return 2 * μ * (ε_x + tr * I), 2 * μ * ε_z
def __init__(self, state, V, direction=[], supg_params=None): super(SUPGAdvection, self).__init__(state) dt = state.timestepping.dt params = supg_params.copy() if supg_params else {} params.setdefault('a0', dt/sqrt(15.)) params.setdefault('a1', dt/sqrt(15.)) gamma = TestFunction(V) theta = TrialFunction(V) self.theta0 = Function(V) # make SUPG test function taus = [params["a0"], params["a1"]] for i in direction: taus[i] = 0.0 tau = Constant(((taus[0], 0.), (0., taus[1]))) dgamma = dot(dot(self.ubar, tau), grad(gamma)) gammaSU = gamma + dgamma n = FacetNormal(state.mesh) un = 0.5*(dot(self.ubar, n) + abs(dot(self.ubar, n))) a_mass = gammaSU*theta*dx arhs = a_mass - dt*gammaSU*dot(self.ubar, grad(theta))*dx if 1 in direction: arhs -= ( dt*dot(jump(gammaSU), (un('+')*theta('+') - un('-')*theta('-')))*dS_v - dt*(gammaSU('+')*dot(self.ubar('+'), n('+'))*theta('+') + gammaSU('-')*dot(self.ubar('-'), n('-'))*theta('-'))*dS_v ) if 2 in direction: arhs -= ( dt*dot(jump(gammaSU), (un('+')*theta('+') - un('-')*theta('-')))*dS_h - dt*(gammaSU('+')*dot(self.ubar('+'), n('+'))*theta('+') + gammaSU('-')*dot(self.ubar('-'), n('-'))*theta('-'))*dS_h ) self.theta1 = Function(V) self.dtheta = Function(V) problem = LinearVariationalProblem(a_mass, action(arhs,self.theta1), self.dtheta) self.solver = LinearVariationalSolver(problem, options_prefix='SUPGAdvection')
def M(ε, A): r"""Calculate the membrane stress for a given strain rate and fluidity""" I = Identity(2) tr_ε = trace(ε) ε_e = sqrt((inner(ε, ε) + tr_ε**2) / 2) μ = 0.5 * A**(-1 / n) * ε_e**(1 / n - 1) return 2 * μ * (ε + tr_ε * I)
class CompressibleEadyParameters(CompressibleParameters, EadyParameters): """ Physical parameters for Compressible Eady """ g = 10. N = sqrt(EadyParameters.Nsq) theta_surf = 300. dthetady = theta_surf / g * EadyParameters.dbdy Pi0 = 0.0
def profilePlots(t, plotData, u, s, h, zb, zF, melt, Q, first=False): '''Plot profiles every nYears/20 ''' # Return if not ready for plot if t < plotData['nextProfPlotTime'] or plotData['axesP'] is None \ and not first: return # Increment time for next plot: use max to kill initial -1 plotData['nextProfPlotTime'] = max(plotData['nextProfPlotTime'], 0.) plotData['nextProfPlotTime'] += plotData['profileDT'] myColor = plotData['cmap'][plotData['profNum']] myLabel = f'year={t:.1f}' # First is special case if first: myColor = 'k' zbProf = [zb((xy[0], xy[1])) for xy in plotData['profXY']] plotData['axesP'][1].plot(plotData['distance'], zbProf, color=myColor) myLabel = 'initial' zFProf = [zF((xy[0], xy[1])) for xy in plotData['profXY']] plotData['axesP'][1].plot(plotData['distance'], zFProf, color='b') # Now do plots speed = firedrake.interpolate(firedrake.sqrt(firedrake.inner(u, u)), Q) speedProf = [speed((xy[0], xy[1])) for xy in plotData['profXY']] plotData['axesP'][0].plot(plotData['distance'], speedProf, label=myLabel, color=myColor) plotData['axesP'][0].legend(ncol=2) # Geometry sProf = [s((xy[0], xy[1])) for xy in plotData['profXY']] bProf = [ s((xy[0], xy[1])) - h((xy[0], xy[1])) for xy in plotData['profXY'] ] zbProf = [zb((xy[0], xy[1])) for xy in plotData['profXY']] plotData['axesP'][1].plot(plotData['distance'], sProf, color=myColor) plotData['axesP'][1].plot(plotData['distance'], bProf, color=myColor) plotData['axesP'][1].plot(plotData['distance'], zbProf, color='k') # if melt is not None: meltProf = [melt((xy[0], xy[1])) for xy in plotData['profXY']] plotData['axesP'][2].plot(plotData['distance'], meltProf, label=myLabel, color=myColor) hProf = np.array([h((xy[0], xy[1])) for xy in plotData['profXY']]) dhdt = (hProf - plotData['lasth']) / plotData['profileDT'] plotData['axesP'][3].plot(plotData['distance'], dhdt, label=myLabel, color=myColor) plotData['lasth'] = hProf plotData['profNum'] += 1 # plt.draw() if plotData['plotResult']: plotData['figP'].canvas.draw()
def violation(self): gradSv = self.gradS.vector()[:] av = self.upper_bound.vector()[:] violv = self.viol.vector()[:].copy() for i in range(len(gradSv)): W, Sigma, V = svd(gradSv[i], full_matrices=False) for j in range(self.dim): Sigma[j] = max(Sigma[j] - av[i], 0)**2 violv[i] = self.c * 0.5 * np.sum(Sigma) self.viol.vector().set_local(violv.flatten()) return fd.sqrt(fd.assemble(self.viol * fd.dx))
def betaInit(s, h, speed, V, Q, Q1, grounded, inversionParams): """Compute intitial beta using 0.5 taud. Parameters ---------- s : firedrake function model surface elevation h : firedrake function model thickness speed : firedrake function modelled speed V : firedrake vector function space vector function space Q : firedrake function space scalar function space grounded : firedrake function Mask with 1s for grounded 0 for floating. """ # Use a result from prior inversion checkFile = inversionParams['initFile'] Quse = Q if inversionParams['initWithDeg1']: checkFile = f'{inversionParams["inversionResult"]}.deg1' Quse = Q1 if checkFile is not None: betaTemp = mf.getCheckPointVars(checkFile, 'betaInv', Quse)['betaInv'] beta1 = icepack.interpolate(betaTemp, Q) return beta1 # No prior result, so use fraction of taud tauD = firedrake.project(-rhoI * g * h * grad(s), V) # stress = firedrake.sqrt(firedrake.inner(tauD, tauD)) Print('stress', firedrake.assemble(stress * firedrake.dx)) fraction = firedrake.Constant(0.95) U = max_value(speed, 1) C = fraction * stress / U**(1/m) if inversionParams['friction'] == 'schoof': mExp = 1/m + 1 U0 = firedrake.Constant(inversionParams['uThresh']) C = C * (m/(m+1)) * (U0**mExp + U**mExp)**(1/(m+1)) beta = firedrake.interpolate(firedrake.sqrt(C) * grounded, Q) return beta
def friction(**kwargs): keys = ('velocity', 'thickness', 'surface', 'friction') u, h, s, C = map(kwargs.get, keys) p_W = ρ_W * g * max_value(0, -(s - h)) p_I = ρ_I * g * h N = p_I - p_W τ_c = N / 2 u_c = (τ_c / C)**m u_b = sqrt(inner(u, u)) return τ_c * ((u_c**(1 / m + 1) + u_b**(1 / m + 1))**(m / (m + 1)) - u_c)
def getModelVelocity(baseName, Q, V, minSigma=5, maxSigma=100): """Read in a tiff velocity data set and return firedrake interpolate functions. Parameters ---------- baseName : str baseName should be of the form pattern.*.abc or pattern The wildcard (*) will be filled with the suffixes (vx, vy.) e.g.,pattern.vx.abc.tif, pattern.vy.abc.tif. Q : firedrake function space function space V : firedrake vector space vector space Returns ------- uObs firedrake interp function on V velocity (m/yr) speed firedrake interp function on Q speed in (m) sigmaX firedrake interp function on Q vx error (m) sigmaY firedrake interp function on Q vy error (m) """ # suffixes for products used suffixes = ['vx', 'vy', 'ex', 'ey'] rasters = {} # prep baseName - baseName.*.xyz.tif or baseName.* if '*' not in baseName: baseName += '.*' if '.tif' not in baseName: baseName += '.tif' # read data for suffix in suffixes: myBand = baseName.replace('*', suffix) if not os.path.exists(myBand): u.myerror(f'Velocity/error file - {myBand} - does not exist') rasters[suffix] = rasterio.open(myBand, 'r') # Firedrake interpolators uObs = icepack.interpolate((rasters['vx'], rasters['vy']), V) # force error to be at least 1 to avoid 0 or negatives. sigmaX = icepack.interpolate(rasters['ex'], Q) sigmaX = icepack.interpolate(firedrake.max_value(sigmaX, minSigma), Q) sigmaX = icepack.interpolate(firedrake.min_value(sigmaX, maxSigma), Q) sigmaY = icepack.interpolate(rasters['ey'], Q) sigmaY = icepack.interpolate(firedrake.max_value(sigmaY, minSigma), Q) sigmaY = icepack.interpolate(firedrake.min_value(sigmaY, maxSigma), Q) speed = icepack.interpolate(firedrake.sqrt(inner(uObs, uObs)), Q) # return results return uObs, speed, sigmaX, sigmaY
def tracer_slice(tmpdir, degree): n = 30 if degree == 0 else 15 m = PeriodicIntervalMesh(n, 1.) mesh = ExtrudedMesh(m, layers=n, layer_height=1. / n) # Parameters chosen so that dt != 1 and u != 1 # Gaussian is translated by 1.5 times width of domain to demonstrate # that transport is working correctly dt = 0.01 tmax = 0.75 output = OutputParameters(dirname=str(tmpdir), dumpfreq=25) state = State(mesh, dt=dt, output=output) uexpr = as_vector([2.0, 0.0]) x = SpatialCoordinate(mesh) width = 1. / 10. f0 = 0.5 fmax = 2.0 xc_init = 0.25 xc_end = 0.75 r_init = sqrt((x[0] - xc_init)**2 + (x[1] - 0.5)**2) r_end = sqrt((x[0] - xc_end)**2 + (x[1] - 0.5)**2) f_init = f0 + (fmax - f0) * exp(-(r_init / width)**2) f_end = f0 + (fmax - f0) * exp(-(r_end / width)**2) tol = 0.12 return TracerSetup(state, tmax, f_init, f_end, "CG", degree, uexpr, tol=tol)
def min(f_in): fmin = op2.Global(1, [np.finfo(float).max], dtype=float) if len(f_in.ufl_shape) > 0: mesh = f_in.function_space().mesh() V = FunctionSpace(mesh, "DG", 1) f = Function(V).project(sqrt(inner(f_in, f_in))) else: f = f_in op2.par_loop( op2.Kernel( """void minify(double *a, double *b) { a[0] = a[0] > fabs(b[0]) ? fabs(b[0]) : a[0]; }""", "minify"), f.dof_dset.set, fmin(op2.MIN), f.dat(op2.READ)) return fmin.data[0]
def compute(self, state): u = state.field_dict['u'] dt = Constant(state.timestepping.dt) return self.field(state.mesh).project(sqrt(dot(u, u))/sqrt(self.area(state.mesh))*dt)
def l2(f): return sqrt(assemble(dot(f, f)*dx))