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)
     })
Exemplo n.º 2
0
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
Exemplo n.º 3
0
    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.)
Exemplo n.º 4
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)
Exemplo n.º 5
0
    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)
Exemplo n.º 6
0
    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
Exemplo n.º 7
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)
Exemplo n.º 8
0
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
Exemplo n.º 9
0
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))
Exemplo n.º 10
0
    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)
Exemplo n.º 11
0
 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)
Exemplo n.º 13
0
 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)
Exemplo n.º 14
0
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)
Exemplo n.º 15
0
    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
Exemplo n.º 16
0
    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)
        ]
Exemplo n.º 17
0
    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)
        ]
Exemplo n.º 18
0
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
Exemplo n.º 19
0
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
Exemplo n.º 20
0
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
Exemplo n.º 21
0
    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)
        ]
Exemplo n.º 22
0
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)
Exemplo n.º 23
0
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
Exemplo n.º 24
0
    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()
Exemplo n.º 25
0
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
Exemplo n.º 26
0
    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
Exemplo n.º 27
0
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']]
Exemplo n.º 30
0
    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)