def setup_constants(self): self.constants.update({ 'deltat': fd.Constant(self.prm['dt']), 'n': fd.FacetNormal(self.mesh), 'f': fd.Constant((0.0, 0.0)), 'nu': fd.Constant(0.001) })
def defineProblemTheta(theta, model, uObs, h, s, u, A, beta, grounded, floating, groundedSmooth, floatingSmooth, sigmaX, sigmaY, inversionParams, opts): """Define problem for viscosity inversion """ # Convert params to firedrake constants uThresh = firedrake.Constant(inversionParams['uThresh']) regTheta = firedrake.Constant(inversionParams['regTheta']) # Define problem problem = icepack.inverse.InverseProblem( model=model, objective=makeObjectiveTheta(uObs, floatingSmooth, sigmaX, sigmaY), regularization=makeRegularizationTheta(regTheta), state_name='velocity', state=u, parameter_name='theta', parameter=theta, diagnostic_solve_kwargs={'thickness': h, 'surface': s, 'fluidity': A, 'beta': beta, 'grounded': grounded, 'floating': floating, 'uThresh': uThresh, 'groundedSmooth': groundedSmooth, 'floatingSmooth': floatingSmooth}, solver_kwargs={**opts, 'tolerance': 1e-6, 'diagnostic_solver_parameters': {'snes_max_it': 200}} ) return problem
def __init__(self, *args, meshsize, **kwargs): self.hot_wall_temperature = fe.Constant(1.) self.cold_wall_temperature = fe.Constant(-0.01) self.topwall_heatflux = fe.Constant(0.) super().__init__( *args, mesh=fe.UnitSquareMesh(meshsize, meshsize), initial_values=initial_values, dirichlet_boundary_conditions=dirichlet_boundary_conditions, **kwargs) q = self.topwall_heatflux _, _, psi_T = fe.TestFunctions(self.function_space) ds = fe.ds(domain=self.mesh, subdomain_id=4) self.variational_form_residual += psi_T * q * ds Ra = 3.27e5 Pr = 56.2 self.grashof_number = self.grashof_number.assign(Ra / Pr) self.prandtl_number = self.prandtl_number.assign(Pr) self.stefan_number = self.stefan_number.assign(0.045) self.liquidus_temperature = self.liquidus_temperature.assign(0.)
def __init__(self, *args, mesh_dimensions = (20, 20), hotwall_temperature = 0.5, coldwall_temperature = -0.5, reynolds_number = 1., rayleigh_number = 1.e6, prandtl_number = 0.71, **kwargs): if "solution" not in kwargs: kwargs["mesh"] = fe.UnitSquareMesh(*mesh_dimensions) self.hotwall_id = 1 self.coldwall_id = 2 self.hotwall_temperature = fe.Constant(hotwall_temperature) self.coldwall_temperature = fe.Constant(coldwall_temperature) super().__init__( *args, reynolds_number = reynolds_number, rayleigh_number = rayleigh_number, prandtl_number = prandtl_number, **kwargs)
def __init__(self, *args, mesh_dimensions=(24, 24), hotwall_temperature=1., initial_temperature=-0.01, reynolds_number=1., rayleigh_number=3.27e5, prandtl_number=56.2, stefan_number=0.045, liquidus_temperature=0., **kwargs): if "solution" not in kwargs: kwargs["mesh"] = fe.UnitSquareMesh(*mesh_dimensions) self.hotwall_temperature = fe.Constant(hotwall_temperature) self.initial_temperature = fe.Constant(initial_temperature) super().__init__(*args, liquidus_temperature=liquidus_temperature, reynolds_number=reynolds_number, rayleigh_number=rayleigh_number, prandtl_number=prandtl_number, stefan_number=stefan_number, **kwargs)
def __init__(self, mesh, element, variational_form_residual, dirichlet_boundary_conditions, initial_values, quadrature_degree=None, time_dependent=True, time_stencil_size=2, output_directory_path="output/"): self.mesh = mesh self.element = element self.function_space = fe.FunctionSpace(mesh, element) self.quadrature_degree = quadrature_degree self.solutions = [ fe.Function(self.function_space) for i in range(time_stencil_size) ] self.solution = self.solutions[0] self.backup_solution = fe.Function(self.solution) if time_dependent: assert (time_stencil_size > 1) self.time = fe.Constant(0.) self.timestep_size = fe.Constant(1.) else: self.time = None self.timestep_size = None self.output_directory_path = pathlib.Path(output_directory_path) self.solution_file = None self.plotvars = None self.initial_values = initial_values(sim=self) for solution in self.solutions: solution.assign(self.initial_values) self.variational_form_residual = variational_form_residual( sim=self, solution=self.solution) self.dirichlet_boundary_conditions = \ dirichlet_boundary_conditions(sim = self) self.snes_iteration_count = 0
def test_firedrake_forward(): numpy_output, _, _, _, = evaluate_primal(assemble_firedrake, templates, *inputs) u1 = firedrake.interpolate(firedrake.Constant(1.0), V) J = assemble_firedrake(u1, firedrake.Constant(0.5), firedrake.Constant(0.6)) assert np.isclose(numpy_output, J)
def test_hybrid_prognostic_solve(): Lx, Ly = 20e3, 20e3 h0, dh = 500.0, 100.0 T = 254.15 u_in = 100.0 model = icepack.models.HybridModel() opts = {'dirichlet_ids': [1], 'side_wall_ids': [3, 4], 'tol': 1e-12} Nx, Ny = 32, 32 mesh2d = firedrake.RectangleMesh(Nx, Ny, Lx, Ly) mesh = firedrake.ExtrudedMesh(mesh2d, layers=1) V = firedrake.VectorFunctionSpace(mesh, dim=2, family='CG', degree=2, vfamily='GL', vdegree=1) Q = firedrake.FunctionSpace(mesh, family='CG', degree=2, vfamily='DG', vdegree=0) x, y, ζ = firedrake.SpatialCoordinate(mesh) height_above_flotation = 10.0 d = -ρ_I / ρ_W * (h0 - dh) + height_above_flotation ρ = ρ_I - ρ_W * d**2 / (h0 - dh)**2 Z = icepack.rate_factor(T) * (ρ * g * h0 / 4)**n q = 1 - (1 - (dh / h0) * (x / Lx))**(n + 1) ux = u_in + Z * q * Lx * (h0 / dh) / (n + 1) u0 = interpolate(firedrake.as_vector((ux, 0)), V) thickness = h0 - dh * x / Lx β = 1 / 2 α = β * ρ / ρ_I * dh / Lx h = interpolate(h0 - dh * x / Lx, Q) h_inflow = h.copy(deepcopy=True) ds = (1 + β) * ρ / ρ_I * dh s = interpolate(d + h0 - dh + ds * (1 - x / Lx), Q) b = interpolate(s - h, Q) C = interpolate(α * (ρ_I * g * thickness) * ux**(-1 / m), Q) A = firedrake.Constant(icepack.rate_factor(T)) final_time, dt = 1.0, 1.0 / 12 num_timesteps = int(final_time / dt) u = model.diagnostic_solve(u0=u0, h=h, s=s, C=C, A=A, **opts) a0 = firedrake.Constant(0) a = interpolate((model.prognostic_solve(dt, h0=h, a=a0, u=u) - h) / dt, Q) for k in range(num_timesteps): h = model.prognostic_solve(dt, h0=h, a=a, u=u, h_inflow=h_inflow) s = icepack.compute_surface(h=h, b=b) u = model.diagnostic_solve(u0=u, h=h, s=s, C=C, A=A, **opts) assert icepack.norm(h, norm_type='Linfty') < np.inf
def _newton_solve(z, E, scale, tolerance=1e-6, armijo=1e-4, max_iterations=50): F = derivative(E, z) H = derivative(F, z) Q = z.function_space() bc = firedrake.DirichletBC(Q, 0, 'on_boundary') p = firedrake.Function(Q) for iteration in range(max_iterations): firedrake.solve(H == -F, p, bc, solver_parameters={'ksp_type': 'preonly', 'pc_type': 'lu'}) dE_dp = assemble(action(F, p)) α = 1.0 E0 = assemble(E) Ez = assemble(replace(E, {z: z + firedrake.Constant(α) * p})) while (Ez > E0 + armijo * α * dE_dp) or np.isnan(Ez): α /= 2 Ez = assemble(replace(E, {z: z + firedrake.Constant(α) * p})) z.assign(z + firedrake.Constant(α) * p) if abs(dE_dp) < tolerance * assemble(scale): return z raise ValueError("Newton solver failed to converge after {0} iterations" .format(max_iterations))
def __init__(self, *args, mesh, element_degree, **kwargs): self.grashof_number = fe.Constant(1.) self.prandtl_number = fe.Constant(1.) self.stefan_number = fe.Constant(1.) self.pressure_penalty_factor = fe.Constant(1.e-7) self.liquidus_temperature = fe.Constant(0.) self.density_solid_to_liquid_ratio = fe.Constant(1.) self.heat_capacity_solid_to_liquid_ratio = fe.Constant(1.) self.thermal_conductivity_solid_to_liquid_ratio = fe.Constant(1.) self.solid_velocity_relaxation_factor = fe.Constant(1.e-12) self.smoothing = fe.Constant(1. / 256.) self.smoothing_sequence = None if "variational_form_residual" not in kwargs: kwargs["variational_form_residual"] = variational_form_residual super().__init__(*args, mesh=mesh, element=element(cell=mesh.ufl_cell(), degree=element_degree), **kwargs)
def __init__(self, *args, element_degree = 1, stefan_number = 1., liquidus_temperature = 0., liquidus_smoothing_factor = 0.01, solver_parameters = {"ksp_type": "cg"}, **kwargs): if "solution" not in kwargs: mesh = kwargs["mesh"] del kwargs["mesh"] element = fe.FiniteElement("P", mesh.ufl_cell(), element_degree) kwargs["solution"] = fe.Function(fe.FunctionSpace(mesh, element)) self.stefan_number = fe.Constant(stefan_number) self.liquidus_temperature = fe.Constant(liquidus_temperature) self.liquidus_smoothing_factor = fe.Constant( liquidus_smoothing_factor) super().__init__(*args, solver_parameters = solver_parameters, **kwargs)
def __init__(self, *args, element_degrees=(1, 2, 2), reynolds_number=1., rayleigh_number=1., prandtl_number=1., **kwargs): if "solution" not in kwargs: mesh = kwargs["mesh"] del kwargs["mesh"] kwargs["solution"] = fe.Function( fe.FunctionSpace(mesh, element(mesh.ufl_cell(), element_degrees))) self.reynolds_number = fe.Constant(reynolds_number) self.rayleigh_number = fe.Constant(rayleigh_number) self.prandtl_number = fe.Constant(prandtl_number) super().__init__(*args, **kwargs)
def __init__(self, *args, taylor_hood_pressure_degree = 1, temperature_degree = 2, reynolds_number = 1., rayleigh_number = 1., prandtl_number = 1., **kwargs): if "solution" not in kwargs: mesh = kwargs["mesh"] del kwargs["mesh"] kwargs["solution"] = fe.Function(fe.FunctionSpace( mesh, element( mesh.ufl_cell(), taylor_hood_pressure_degree, temperature_degree))) self.reynolds_number = fe.Constant(reynolds_number) self.rayleigh_number = fe.Constant(rayleigh_number) self.prandtl_number = fe.Constant(prandtl_number) super().__init__(*args, fieldnames=("p", "u", "T"), **kwargs)
def test_diagnostic_solver_side_friction(): model = icepack.models.IceShelf() opts = {"dirichlet_ids": [1], "side_wall_ids": [3, 4]} mesh = firedrake.RectangleMesh(32, 32, Lx, Ly) degree = 2 V = firedrake.VectorFunctionSpace(mesh, "CG", degree) Q = firedrake.FunctionSpace(mesh, "CG", degree) x, y = firedrake.SpatialCoordinate(mesh) u_initial = interpolate(as_vector((exact_u(x), 0)), V) h = interpolate(h0 - dh * x / Lx, Q) A = interpolate(firedrake.Constant(icepack.rate_factor(T)), Q) # Choose the side wall friction coefficient so that, assuming the ice is # sliding at the maximum speed for the solution without friction, the # stress is 10 kPa. from icepack.constants import weertman_sliding_law as m τ = 0.01 u_max = icepack.norm(u_initial, norm_type="Linfty") Cs = firedrake.Constant(τ * u_max**(-1 / m)) solver = icepack.solvers.FlowSolver(model, **opts) fields = { "velocity": u_initial, "thickness": h, "fluidity": A, "side_friction": Cs } u = solver.diagnostic_solve(**fields) assert icepack.norm(u) < icepack.norm(u_initial)
def setup(self, **kwargs): r"""Create the internal data structures that help reuse information from past prognostic solves""" for name, field in kwargs.items(): if name in self._fields.keys(): self._fields[name].assign(field) else: if isinstance(field, firedrake.Constant): self._fields[name] = firedrake.Constant(field) elif isinstance(field, firedrake.Function): self._fields[name] = field.copy(deepcopy=True) else: raise TypeError( 'Input fields must be Constant or Function!') dt = firedrake.Constant(1.) dh_dt = self._continuity(dt, **self._fields) h = self._fields.get('thickness', self._fields.get('h')) h_0 = h.copy(deepcopy=True) q = firedrake.TestFunction(h.function_space()) F = (h - h_0) * q * dx - dt * dh_dt problem = firedrake.NonlinearVariationalProblem(F, h) self._solver = firedrake.NonlinearVariationalSolver( problem, solver_parameters=self._solver_parameters) self._thickness_old = h_0 self._timestep = dt
def dirichlet_boundary_conditions(self): return [ fe.DirichletBC(self.solution_subspaces["u"], fe.Constant((0., 0.)), (1, 2, 3)), fe.DirichletBC(self.solution_subspaces["u"], fe.Constant((1., 0.)), 4) ]
def dirichlet_boundary_conditions(sim): W = sim.solution_space return [ fe.DirichletBC(W.sub(0), fe.Constant((0., 0.)), (1, 2, 3)), fe.DirichletBC(W.sub(0), fe.Constant((1., 0.)), 4) ]
def piecewiseWithDepth(h, floating, meltParams, Q, *argv, **kwargs): """ Melt function that is described piecewise by set of polynomials Melt is in units of m/yr w.e. Parameters ---------- h : firedrake function ice thickness floating : firedrake function floating mask meltParams : dict parameters for melt function Returns ------- firedrake function melt rates """ # compute depth melt = firedrake.Constant(0) for i in range(1, meltParams['numberOfPolynomials'] + 1): poly = meltParams[f'poly{i}'] tmpMelt = firedrake.Constant(poly['coeff'][0]) for j in range(1, poly['deg'] + 1): tmpMelt = tmpMelt + poly['coeff'][j] * h**j # Apply melt to all shelf ice (ice > 30 m) melt = melt + tmpMelt * \ (h > max(poly['min'], 30.1)) * (h < poly['max']) # Smooth result alpha = 4000 # Default if 'alpha' in meltParams: alpha = meltParams['alpha'] # # if filterWithFloatMask apply float mask before filter, which will shift # melt distribution up in the column. If filter applied afterwards, it # will be concentrated nearer the GL. filterWithFloatMask = False if 'filterWithFloatMask' in meltParams: filterWithFloatMask = meltParams['filterWithFloatMask'] if filterWithFloatMask: # Changed to avoid petsc memory issue on store # melt1 = icepack.interpolate(melt * floating, Q) melt1 = icepack.interpolate(melt, Q) melt1 = icepack.interpolate(floating * melt1, Q) else: melt1 = icepack.interpolate(melt, Q) melt1 = firedrakeSmooth(melt1, alpha=alpha) # 'totalMelt' given renormalize melt to produce this value if 'totalMelt' in meltParams.keys(): trend = 0. if 'trend' in kwargs.keys(): trend = kwargs['trend'] intMelt = firedrake.assemble(melt1 * floating * firedrake.dx) total = float(meltParams['totalMelt']) + trend scale = firedrake.Constant(-1.0 * total / float(intMelt)) else: scale = firedrake.Constant(1.) # melt = icepack.interpolate(melt1 * scale * floating, Q) return melt
def test_diagnostic_solver(): Nx, Ny = 32, 32 mesh2d = firedrake.RectangleMesh(Nx, Ny, Lx, Ly) mesh = firedrake.ExtrudedMesh(mesh2d, layers=1) Q = firedrake.FunctionSpace(mesh, family='CG', degree=2, vfamily='DG', vdegree=0) x, y, ζ = firedrake.SpatialCoordinate(mesh) h = firedrake.interpolate(h0 - dh * x / Lx, Q) s = firedrake.interpolate(d + h0 - dh + ds * (1 - x / Lx), Q) u_expr = firedrake.as_vector(((0.95 + 0.05 * ζ) * exact_u(x), 0)) A = firedrake.Constant(icepack.rate_factor(254.15)) C = firedrake.Constant(0.001) model = icepack.models.HybridModel() opts = {'dirichlet_ids': [1, 3, 4], 'tol': 1e-12} max_degree = 5 Nz = 32 xs = np.array([(Lx / 2, Ly / 2, k / Nz) for k in range(Nz + 1)]) us = np.zeros((max_degree + 1, Nz + 1)) for vdegree in range(max_degree, 0, -1): solver = icepack.solvers.FlowSolver(model, **opts) V = firedrake.VectorFunctionSpace(mesh, dim=2, family='CG', degree=2, vfamily='GL', vdegree=vdegree) u0 = firedrake.interpolate(u_expr, V) u = solver.diagnostic_solve(velocity=u0, thickness=h, surface=s, fluidity=A, friction=C) V0 = firedrake.VectorFunctionSpace(mesh, dim=2, family='CG', degree=2, vfamily='DG', vdegree=0) depth_avg_u = firedrake.project(u, V0) shear_u = firedrake.project(u - depth_avg_u, V) assert icepack.norm(shear_u, norm_type='Linfty') > 1e-2 us_center = np.array(u.at(xs, tolerance=1e-6)) us[vdegree, :] = np.sqrt(np.sum(us_center**2, 1)) norm = np.linalg.norm(us[max_degree, :]) error = np.linalg.norm(us[vdegree, :] - us[max_degree, :]) / norm print(error, flush=True) assert error < 1e-2
def test_order_0(): def h_expr(x): return h0 - dh * x / Lx def s_expr(x): return d + h0 - dh + ds * (1 - x / Lx) A = firedrake.Constant(icepack.rate_factor(254.15)) C = firedrake.Constant(0.001) opts = {'dirichlet_ids': [1], 'side_wall_ids': [3, 4], 'tolerance': 1e-14} Nx, Ny = 64, 64 mesh2d = firedrake.RectangleMesh(Nx, Ny, Lx, Ly) x, y = firedrake.SpatialCoordinate(mesh2d) Q2d = firedrake.FunctionSpace(mesh2d, family='CG', degree=2) V2d = firedrake.VectorFunctionSpace(mesh2d, family='CG', degree=2) h = firedrake.interpolate(h_expr(x), Q2d) s = firedrake.interpolate(s_expr(x), Q2d) u_expr = firedrake.as_vector((exact_u(x), 0)) u0 = firedrake.interpolate(u_expr, V2d) model2d = icepack.models.IceStream() solver2d = icepack.solvers.FlowSolver(model2d, **opts) u2d = solver2d.diagnostic_solve(velocity=u0, thickness=h, surface=s, fluidity=A, friction=C) mesh = firedrake.ExtrudedMesh(mesh2d, layers=1) x, y, ζ = firedrake.SpatialCoordinate(mesh) Q3d = firedrake.FunctionSpace(mesh, family='CG', degree=2, vfamily='DG', vdegree=0) V3d = firedrake.VectorFunctionSpace(mesh, dim=2, family='CG', degree=2, vfamily='GL', vdegree=0) h = firedrake.interpolate(h_expr(x), Q3d) s = firedrake.interpolate(s_expr(x), Q3d) u_expr = firedrake.as_vector((exact_u(x), 0)) u0 = firedrake.interpolate(u_expr, V3d) model3d = icepack.models.HybridModel() solver3d = icepack.solvers.FlowSolver(model3d, **opts) u3d = solver3d.diagnostic_solve(velocity=u0, thickness=h, surface=s, fluidity=A, friction=C) U2D, U3D = u2d.dat.data_ro, u3d.dat.data_ro assert np.linalg.norm(U3D - U2D) / np.linalg.norm(U2D) < 1e-2
def dirichlet_boundary_conditions(sim): W = sim.solution_space return [ fe.DirichletBC(sim.solution_subspaces["u"], fe.Constant((0, 0)), (1, 2, 3)), fe.DirichletBC(sim.solution_subspaces["u"], fe.Constant((1, 0)), 4) ]
def solve(dt, z0, u, **kwargs): z = z0.copy(deepcopy=True) J_diffusive = -k * S**2 / 2 * ln(1 - inner(grad(z), grad(z)) / S**2) * dx J_uplift = u * z * dx J = J_diffusive - J_uplift E = 0.5 * (z - z0)**2 * dx + firedrake.Constant(dt) * J scale = 0.5 * z**2 * dx + firedrake.Constant(dt) * J_diffusive return _newton_solve(z, E, scale, **kwargs)
def test_poisson_inverse(solver_type): Nx, Ny = 32, 32 mesh = firedrake.UnitSquareMesh(Nx, Ny) degree = 2 Q = firedrake.FunctionSpace(mesh, "CG", degree) x, y = firedrake.SpatialCoordinate(mesh) q_true = interpolate(-4 * ((x - 0.5)**2 + (y - 0.5)**2), Q) f = interpolate(firedrake.Constant(1), Q) dirichlet_ids = [1, 2, 3, 4] model = PoissonModel() poisson_solver = PoissonSolver(model, dirichlet_ids=dirichlet_ids) u_bdry = firedrake.Function(Q) u_obs = poisson_solver.diagnostic_solve(u=u_bdry, q=q_true, f=f) q0 = firedrake.Function(Q) u0 = poisson_solver.diagnostic_solve(u=u_bdry, q=q0, f=f) def callback(inverse_solver): misfit = firedrake.assemble(inverse_solver.objective) regularization = firedrake.assemble(inverse_solver.regularization) q = inverse_solver.parameter error = firedrake.norm(q - q_true) print(misfit, regularization, error) L = firedrake.Constant(1e-4) problem = icepack.inverse.InverseProblem( model=model, objective=lambda u: 0.5 * (u - u_obs)**2 * dx, regularization=lambda q: 0.5 * L**2 * inner(grad(q), grad(q)) * dx, state_name="u", state=u0, parameter_name="q", parameter=q0, solver_type=PoissonSolver, solver_kwargs={"dirichlet_ids": dirichlet_ids}, diagnostic_solve_kwargs={"f": f}, ) solver = solver_type(problem, callback) assert solver.state is not None assert icepack.norm(solver.state) > 0 assert icepack.norm(solver.adjoint_state) > 0 assert icepack.norm(solver.search_direction) > 0 max_iterations = 1000 iterations = solver.solve(rtol=2.5e-2, atol=1e-8, max_iterations=max_iterations) print(f"Number of iterations: {iterations}") assert iterations < max_iterations q = solver.parameter assert icepack.norm(q - q_true) < 0.25
def _coeff_initialise(self,mesh,coeff_pre): """Initialises self.coeff equal to coeff_pre, but sets up Firedrake Constant structure to allow for sampling. Parameters: mesh - a Firedrake mesh. coeff_pre - see init. """ if self._coeff_dims == [2,2]\ and coeff_pre != fd.as_matrix([[1.0,0.0],[0.0,1.0]]): warnings.warn("coeff_pre is not the identity. There is no\ guarantee that the randomly-generated matrices are\ positive-definite, or have the correct amount of noise.") d = mesh.geometric_dimension() # Bit of a hack, set up num_pieces num_pieces_list = [] [num_pieces_list.append(self._num_pieces) for ii in range(d)] # Set up all the Firedrake Constants: self._constant_array = np.empty(num_pieces_list,dtype=object) with np.nditer(self._constant_array,flags=['refs_ok'],op_flags=['writeonly']) as array_it: for const in array_it: if self._coeff_dims == [2,2]: const[...] = fd.Constant(np.array([[0.0,0.0],[0.0,0.0]]),domain=mesh) elif self._coeff_dims == [1]: const[...] = fd.Constant(0.0,domain=mesh) # Form coeff by looping over all the subdomains x = fd.SpatialCoordinate(mesh) self.coeff = coeff_pre array_it = np.nditer(self._constant_array,flags=['refs_ok','multi_index']) while not array_it.finished: const = array_it[0] loc_array = np.array((array_it.multi_index,1+np.array(array_it.multi_index)) ,dtype='float').T/float(self._num_pieces) self.coeff += utils.nd_indicator(x,const,loc_array) array_it.iternext()
def test_damage_transport(): nx, ny = 32, 32 Lx, Ly = 20e3, 20e3 mesh = firedrake.RectangleMesh(nx, ny, Lx, Ly) x, y = firedrake.SpatialCoordinate(mesh) V = firedrake.VectorFunctionSpace(mesh, "CG", 2) Q = firedrake.FunctionSpace(mesh, "CG", 2) u0 = 100.0 h0, dh = 500.0, 100.0 T = 268.0 ρ = ρ_I * (1 - ρ_I / ρ_W) Z = icepack.rate_factor(T) * (ρ * g * h0 / 4)**n q = 1 - (1 - (dh / h0) * (x / Lx))**(n + 1) du = Z * q * Lx * (h0 / dh) / (n + 1) u = interpolate(as_vector((u0 + du, 0)), V) h = interpolate(h0 - dh * x / Lx, Q) A = firedrake.Constant(icepack.rate_factor(T)) S = firedrake.TensorFunctionSpace(mesh, "DG", 1) ε = firedrake.project(sym(grad(u)), S) M = firedrake.project(membrane_stress(strain_rate=ε, fluidity=A), S) degree = 1 Δ = firedrake.FunctionSpace(mesh, "DG", degree) D_inflow = firedrake.Constant(0.0) D = firedrake.Function(Δ) damage_model = icepack.models.DamageTransport() damage_solver = icepack.solvers.DamageSolver(damage_model) final_time = Lx / u0 max_speed = u.at((Lx - 1.0, Ly / 2), tolerance=1e-10)[0] δx = Lx / nx timestep = δx / max_speed / (2 * degree + 1) num_steps = int(final_time / timestep) dt = final_time / num_steps for step in range(num_steps): D = damage_solver.solve( dt, damage=D, velocity=u, strain_rate=ε, membrane_stress=M, damage_inflow=D_inflow, ) Dmax = D.dat.data_ro[:].max() assert 0 < Dmax < 1
def _setup(self, **kwargs): for name, field in kwargs.items(): if name in self._fields.keys(): self._fields[name].assign(field) else: if isinstance(field, firedrake.Constant): self._fields[name] = firedrake.Constant(field) elif isinstance(field, firedrake.Function): self._fields[name] = field.copy(deepcopy=True) else: raise TypeError( "Input %s field has type %s, must be Constant or Function!" % (name, type(field)) ) # Create symbolic representations of the flux and sources of damage dt = firedrake.Constant(1.0) flux = self.model.flux(**self.fields) # Create the finite element mass matrix D = self.fields["damage"] Q = D.function_space() φ, ψ = firedrake.TrialFunction(Q), firedrake.TestFunction(Q) M = φ * ψ * dx L1 = -dt * flux D1 = firedrake.Function(Q) D2 = firedrake.Function(Q) L2 = firedrake.replace(L1, {D: D1}) L3 = firedrake.replace(L1, {D: D2}) dD = firedrake.Function(Q) parameters = { "solver_parameters": { "ksp_type": "preonly", "pc_type": "bjacobi", "sub_pc_type": "ilu", } } problem1 = LinearVariationalProblem(M, L1, dD) problem2 = LinearVariationalProblem(M, L2, dD) problem3 = LinearVariationalProblem(M, L3, dD) solver1 = LinearVariationalSolver(problem1, **parameters) solver2 = LinearVariationalSolver(problem2, **parameters) solver3 = LinearVariationalSolver(problem3, **parameters) self._solvers = [solver1, solver2, solver3] self._stages = [D1, D2] self._damage_change = dD self._timestep = dt
def test_poisson_inverse(solver_type): Nx, Ny = 32, 32 mesh = firedrake.UnitSquareMesh(Nx, Ny) degree = 2 Q = firedrake.FunctionSpace(mesh, 'CG', degree) x, y = firedrake.SpatialCoordinate(mesh) q_true = interpolate(-4 * ((x - 0.5)**2 + (y - 0.5)**2), Q) f = interpolate(firedrake.Constant(1), Q) dirichlet_ids = [1, 2, 3, 4] model = PoissonModel() u_obs = model.solve(q=q_true, f=f, dirichlet_ids=dirichlet_ids) q0 = interpolate(firedrake.Constant(0), Q) u0 = model.solve(q=q0, f=f, dirichlet_ids=dirichlet_ids) def callback(inverse_solver): misfit = firedrake.assemble(inverse_solver.objective) regularization = firedrake.assemble(inverse_solver.regularization) q = inverse_solver.parameter error = firedrake.norm(q - q_true) print(misfit, regularization, error) L = firedrake.Constant(1e-4) problem = icepack.inverse.InverseProblem( model=model, method=PoissonModel.solve, objective=lambda u: 0.5 * (u - u_obs)**2 * dx, regularization=lambda q: L**2 / 2 * inner(grad(q), grad(q)) * dx, state_name='u', state=u0, parameter_name='q', parameter=q0, model_args={'f': f}, dirichlet_ids=dirichlet_ids) solver = solver_type(problem, callback) assert solver.state is not None assert icepack.norm(solver.state) > 0 assert icepack.norm(solver.adjoint_state) > 0 assert icepack.norm(solver.search_direction) > 0 max_iterations = 1000 iterations = solver.solve(rtol=2.5e-2, atol=1e-8, max_iterations=max_iterations) print('Number of iterations: {}'.format(iterations)) assert iterations < max_iterations q = solver.parameter assert icepack.norm(q - q_true) < 0.25
def setup_bcs(self): x, y = fd.SpatialCoordinate(self.mesh) bcu = [ fd.DirichletBC(self.V['u'], fd.Constant((0, 0)), (1, 4)), # top-bottom and cylinder fd.DirichletBC(self.V['u'], ((4.0 * 1.5 * y * (0.41 - y) / 0.41**2), 0), 2) ] # inflow bcp = [fd.DirichletBC(self.V['p'], fd.Constant(0), 3)] # outflow self.bc['u'][0] = [bcu, None, None, None, 'fixed'] self.bc['p'] = [[bcp, None, None, None, 'fixed']]
def setup_bcs(self): x, y = fd.SpatialCoordinate(self.mesh) bcu = [ fd.DirichletBC(self.V['u'], fd.Constant((0, 0)), (10, 12)), # top-bottom fd.DirichletBC(self.V['u'], ((1.0 * (y - 1) * (2 - y)) / (0.5**2), 0), 9) ] # inflow bcp = [fd.DirichletBC(self.V['p'], fd.Constant(0), 11)] # outflow self.bc['u'][0] = [bcu, None, None, None, 'fixed'] self.bc['p'] = [[bcp, None, None, None, 'fixed']]
def __init__(self, *args, mesh, element_degree, **kwargs): self.grashof_number = fe.Constant(1.) self.prandtl_number = fe.Constant(1.) super().__init__(*args, mesh=mesh, element=element(cell=mesh.ufl_cell(), degree=element_degree), variational_form_residual=variational_form_residual, time_dependent=False, **kwargs)