Esempio n. 1
0
    def diagnostic_solve(self, u0, h, s, dirichlet_ids, tol=1e-6, **kwargs):
        r"""Solve for the ice velocity from the thickness and surface
        elevation

        Parameters
        ----------
        u0 : firedrake.Function
            Initial guess for the ice velocity; the Dirichlet boundaries
            are taken from `u0`
        h : firedrake.Function
            Ice thickness
        s : firedrake.Function
            Ice surface elevation
        dirichlet_ids : list of int
            list of integer IDs denoting the parts of the boundary where
            Dirichlet boundary conditions should be applied
        tol : float
            dimensionless tolerance for when to terminate Newton's method

        Returns
        -------
        u : firedrake.Function
            Ice velocity

        Other parameters
        ----------------
        **kwargs
            All other keyword arguments will be passed on to the
            `viscosity`, `friction`, `gravity`, and `terminus` functions
            that were set when this model object was initialized
        """
        u = u0.copy(deepcopy=True)

        boundary_ids = u.ufl_domain().exterior_facets.unique_markers
        side_wall_ids = kwargs.get('side_wall_ids', [])
        kwargs['side_wall_ids'] = side_wall_ids
        kwargs['ice_front_ids'] = list(
            set(boundary_ids) - set(dirichlet_ids) - set(side_wall_ids))
        bcs = firedrake.DirichletBC(u.function_space(),
                                    firedrake.as_vector((0, 0)), dirichlet_ids)
        params = {'quadrature_degree': self.quadrature_degree(u, h, **kwargs)}

        action = self.action(u=u, h=h, s=s, **kwargs)
        scale = self.scale(u=u, h=h, s=s, **kwargs)
        problem = MinimizationProblem(action, scale, u, bcs, params)
        solver = NewtonSolver(problem, tol)
        solver.solve()
        return u
Esempio n. 2
0
class IcepackSolver:
    def __init__(self,
                 model,
                 fields,
                 solver_parameters,
                 dirichlet_ids=[],
                 side_wall_ids=[]):
        r"""Diagnostic solver implementation using hand-written Newton line
        search optimization algorithm"""
        self._model = model
        self._fields = fields
        self._solver_parameters = solver_parameters.copy()
        self._tolerance = self._solver_parameters.pop('tolerance', 1e-12)
        self._max_iterations = self._solver_parameters.pop(
            'max_iterations', 50)
        self._dirichlet_ids = dirichlet_ids
        self._side_wall_ids = side_wall_ids

    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 fields must be Constant or Function!')

        # Create homogeneous BCs for the Dirichlet part of the boundary
        u = self._fields.get('velocity', self._fields.get('u'))
        V = u.function_space()
        # NOTE: This will have to change when we do Stokes!
        bcs = firedrake.DirichletBC(V, Constant((0, 0)), self._dirichlet_ids)
        if not self._dirichlet_ids:
            bcs = None

        # Find the numeric IDs for the ice front
        boundary_ids = u.ufl_domain().exterior_facets.unique_markers
        ice_front_ids_comp = set(self._dirichlet_ids + self._side_wall_ids)
        ice_front_ids = list(set(boundary_ids) - ice_front_ids_comp)

        # Create the action and scale functionals
        _kwargs = {
            'side_wall_ids': self._side_wall_ids,
            'ice_front_ids': ice_front_ids
        }
        action = self._model.action(**self._fields, **_kwargs)
        scale = self._model.scale(**self._fields, **_kwargs)

        # Set up a minimization problem and solver
        quadrature_degree = self._model.quadrature_degree(**self._fields)
        params = {'quadrature_degree': quadrature_degree}
        problem = MinimizationProblem(action, scale, u, bcs, params)
        self._solver = NewtonSolver(problem,
                                    self._tolerance,
                                    solver_parameters=self._solver_parameters,
                                    max_iterations=self._max_iterations)

    def solve(self, **kwargs):
        r"""Solve the diagnostic model physics for the ice velocity"""
        if not hasattr(self, '_solver'):
            self.setup(**kwargs)
        else:
            for name, field in kwargs.items():
                self._fields[name].assign(field)

        # Solve the minimization problem and return the velocity field
        self._solver.solve()
        u = self._fields.get('velocity', self._fields.get('u'))
        return u.copy(deepcopy=True)