Exemplo n.º 1
0
    def initialize(self, init_solution):
        self.solution_old.assign(init_solution)
        u, p = firedrake.split(self.solution)
        u_old, p_old = self.solution_old.split()
        u_star_theta = (1-self.theta)*u_old + self.theta*self.u_star
        u_theta = (1-self.theta)*u_old + self.theta*u
        p_theta = (1-self.theta_p)*p_old + self.theta_p*p
        u_lag, p_lag = self.solution_lag.split()
        u_lag_theta = (1-self.theta)*u_old + self.theta*u_lag
        p_lag_theta = (1-self.theta_p)*p_old + self.theta_p*p_lag

        # setup predictor solve, this solves for u_start only using a fixed p_lag_theta for pressure
        self.fields_star = self.fields.copy()
        self.fields_star['pressure'] = p_lag_theta

        self.Fstar = self.equations[0].mass_term(self.u_star_test, self.u_star-u_old)
        self.Fstar -= self.dt_const*self.equations[0].residual(self.u_star_test, u_star_theta, u_lag_theta, self.fields_star, bcs=self.bcs)
        self.predictor_problem = firedrake.NonlinearVariationalProblem(self.Fstar, self.u_star)
        self.predictor_solver = firedrake.NonlinearVariationalSolver(self.predictor_problem,
                                                                     solver_parameters=self.predictor_solver_parameters,
                                                                     options_prefix='predictor_momentum')

        # the correction solve, solving the coupled system:
        #   u1 = u* - dt*G ( p_theta - p_lag_theta)
        #   div(u1) = 0
        self.F = self.equations[0].mass_term(self.u_test, u-self.u_star)

        pg_term = [term for term in self.equations[0]._terms if isinstance(term, PressureGradientTerm)][0]
        pg_fields = self.fields.copy()
        # note that p_theta-p_lag_theta = theta_p*(p1-p_lag)
        pg_fields['pressure'] = self.theta_p * (p - p_lag)
        self.F -= self.dt_const*pg_term.residual(self.u_test, u_theta, u_lag_theta, pg_fields, bcs=self.bcs)

        div_term = [term for term in self.equations[1]._terms if isinstance(term, DivergenceTerm)][0]
        div_fields = self.fields.copy()
        div_fields['velocity'] = u
        self.F -= self.dt_const*div_term.residual(self.p_test, p_theta, p_lag_theta, div_fields, bcs=self.bcs)

        W = self.solution.function_space()
        if self.pressure_nullspace is None:
            mixed_nullspace = None
        else:
            mixed_nullspace = firedrake.MixedVectorSpaceBasis(W, [W.sub(0), self.pressure_nullspace])

        self.problem = firedrake.NonlinearVariationalProblem(self.F, self.solution)
        self.solver = firedrake.NonlinearVariationalSolver(self.problem,
                                                           solver_parameters=self.solver_parameters,
                                                           appctx={'a': firedrake.derivative(self.F, self.solution),
                                                                   'schur_nullspace': self.pressure_nullspace,
                                                                   'dt': self.dt_const, 'dx': self.equations[1].dx,
                                                                   'ds': self.equations[1].ds, 'bcs': self.bcs, 'n': div_term.n},
                                                           nullspace=mixed_nullspace, transpose_nullspace=mixed_nullspace,
                                                           options_prefix=self.name)

        self._initialized = True
Exemplo n.º 2
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.º 3
0
    def initialize(self, init_solution):
        self.solution_old.assign(init_solution)
        u, p = firedrake.split(self.solution)
        u_old, p_old = self.solution_old.split()
        u_theta = (1-self.theta)*u_old + self.theta*u
        p_theta = (1-self.theta)*p_old + self.theta*p
        z_theta = [u_theta, p_theta]
        self._fields = []
        for i, cpl in enumerate(self.coupling):
            cfields = self.fields.copy()
            for field_name, eqno in cpl.items():
                assert 0 <= eqno <= 2 and not eqno == i
                cfields[field_name] = z_theta[eqno]
            self._fields.append(cfields)

        self.F = self.equations[0].mass_term(self.test[0], u-u_old)
        self.F -= self.dt_const * self.equations[0].residual(self.test[0], u_theta, u_old, self._fields[0],
                                                             bcs=self.bcs)  # linearise using u_old
        self.F -= self.dt_const*self.equations[1].residual(self.test[1], p_theta, p_theta, self._fields[1], bcs=self.bcs)

        self.problem = firedrake.NonlinearVariationalProblem(self.F, self.solution, self.strong_bcs)
        self.solver = firedrake.NonlinearVariationalSolver(self.problem,
                                                           solver_parameters=self.solver_parameters,
                                                           options_prefix=self.name)
        self._initialized = True
Exemplo n.º 4
0
    def initialize(self, init_solution):
        self.solution_old.assign(init_solution)
        z_theta = (1-self.theta)*self.solution_old + self.theta*self.solution

        self._fields = []
        for fields in self.fields:
            cfields = fields.copy()
            for field_name, field_expr in fields.items():
                if isinstance(field_expr, float):
                    continue
                cfields[field_name] = firedrake.replace(field_expr, {self.solution: z_theta})
            self._fields.append(cfields)

        F = 0
        for test, u, u_old, eq, mass_term, fields, bcs in zip(self.test, firedrake.split(self.solution), firedrake.split(self.solution_old), self.equations, self.mass_terms, self._fields, self.bcs):
            if mass_term:
                F += eq.mass_term(test, u-u_old)

            u_theta = (1-self.theta)*u_old + self.theta*u
            F -= self.dt_const * eq.residual(test, u_theta, u_theta, fields, bcs=bcs)

        self.problem = firedrake.NonlinearVariationalProblem(F, self.solution, bcs=self.strong_bcs)
        self.solver = firedrake.NonlinearVariationalSolver(self.problem,
                                                           solver_parameters=self.solver_parameters,
                                                           options_prefix=self.name)
        self._initialized = True
Exemplo n.º 5
0
    def setup(self, **kwargs):
        for name, field in kwargs.items():
            if name in self._fields.keys():
                self._fields[name].assign(field)
            else:
                self._fields[name] = utilities.copy(field)

        # Create homogeneous BCs for the Dirichlet part of the boundary
        u = self._fields.get('velocity', self._fields.get('u'))
        V = u.function_space()
        bcs = firedrake.DirichletBC(V, u, 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)
        F = firedrake.derivative(action, u)

        degree = self._model.quadrature_degree(**self._fields)
        params = {'form_compiler_parameters': {'quadrature_degree': degree}}
        problem = firedrake.NonlinearVariationalProblem(F, u, bcs, **params)
        self._solver = firedrake.NonlinearVariationalSolver(
            problem, solver_parameters=self._solver_parameters)
Exemplo n.º 6
0
    def solve(
        self,
        parameters={
            "snes_type": "newtonls",
            "snes_monitor": True,
            "ksp_type": "preonly",
            "pc_type": "lu",
            "mat_type": "aij",
            "pc_factor_mat_solver_type": "mumps"
        }):

        problem = fe.NonlinearVariationalProblem(
            F=self.variational_form_residual,
            u=self.solution,
            bcs=self.dirichlet_boundary_conditions,
            J=fe.derivative(self.variational_form_residual, self.solution))

        solver = fe.NonlinearVariationalSolver(problem=problem,
                                               solver_parameters=parameters)

        solver.solve()

        self.snes_iteration_count += solver.snes.getIterationNumber()

        return self.solution
Exemplo n.º 7
0
    def __init__(self, mesh_m):
        super().__init__()
        self.mesh_m = mesh_m

        # Setup problem
        self.V = fd.FunctionSpace(self.mesh_m, "CG", 1)

        # Preallocate solution variables for state and adjoint equations
        self.solution = fd.Function(self.V, name="State")

        # Weak form of Poisson problem
        u = self.solution
        v = fd.TestFunction(self.V)
        self.f = fd.Constant(4.)
        self.F = (fd.inner(fd.grad(u), fd.grad(v)) - self.f * v) * fd.dx
        self.bcs = fd.DirichletBC(self.V, 0., "on_boundary")

        # PDE-solver parameters
        self.params = {
            "ksp_type": "cg",
            "mat_type": "aij",
            "pc_type": "hypre",
            "pc_factor_mat_solver_package": "boomerang",
            "ksp_rtol": 1e-11,
            "ksp_atol": 1e-11,
            "ksp_stol": 1e-15,
        }

        stateproblem = fd.NonlinearVariationalProblem(self.F,
                                                      self.solution,
                                                      bcs=self.bcs)
        self.solver = fd.NonlinearVariationalSolver(
            stateproblem, solver_parameters=self.params)
Exemplo n.º 8
0
    def _setup(self, **kwargs):
        for name, field in kwargs.items():
            if name in self.fields.keys():
                self.fields[name].assign(field)
            else:
                self.fields[name] = utilities.copy(field)

        dt = Constant(1.)

        aflux = self.model.advective_flux(**self.fields)
        dflux = self.model.diffusive_flux(**self.fields)
        sources = self.model.sources(**self.fields)
        dE_dt = sources - aflux - dflux
        E = self.fields.get('energy', self.fields.get('E'))
        h = self.fields.get('thickness', self.fields.get('h'))
        E_0 = E.copy(deepcopy=True)
        ψ = firedrake.TestFunction(E.function_space())
        F = (E - E_0) * ψ * h * dx - dt * dE_dt

        degree = E.ufl_element().degree()
        fc_params = {'quadrature_degree': (3 * degree[0], 2 * degree[1])}
        problem = firedrake.NonlinearVariationalProblem(
            F, E, form_compiler_parameters=fc_params
        )

        self._solver = firedrake.NonlinearVariationalSolver(
            problem, solver_parameters=self._solver_parameters
        )

        self._energy_old = E_0
        self._timestep = dt
Exemplo n.º 9
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)))

        dt = Constant(1.0)

        aflux = self.model.advective_flux(**self.fields)
        dflux = self.model.diffusive_flux(**self.fields)
        sources = self.model.sources(**self.fields)
        dE_dt = sources - aflux - dflux
        E, h = itemgetter("energy", "thickness")(self.fields)
        E_0 = E.copy(deepcopy=True)
        ψ = firedrake.TestFunction(E.function_space())
        F = (E - E_0) * ψ * h * dx - dt * dE_dt

        degree = E.ufl_element().degree()
        fc_params = {"quadrature_degree": (3 * degree[0], 2 * degree[1])}
        problem = firedrake.NonlinearVariationalProblem(
            F, E, form_compiler_parameters=fc_params)

        self._solver = firedrake.NonlinearVariationalSolver(
            problem, solver_parameters=self._solver_parameters)

        self._energy_old = E_0
        self._timestep = dt
Exemplo n.º 10
0
    def __init__(self, problem: fd.NonlinearVariationalProblem,
                 **kwargs) -> None:
        """Same than NonlinearVariationalSolver, but with just the SIMPLE preconditioner by default
        Args:
            problem ([type]): [description]
            nullspace ([type], optional): [description]. Defaults to None.
            solver_parameters ([type], optional): [description]. Defaults to None.
        """
        solver_parameters_default = {
            # "snes_type": "ksponly",
            # "snes_no_convergence_test" : None,
            # "snes_max_it": 1,
            "snes_type": "newtonls",
            "snes_linesearch_type": "l2",
            "snes_linesearch_maxstep": 1.0,
            # "snes_monitor": None,
            # "snes_linesearch_monitor": None,
            "snes_rtol": 1.0e-4,
            "snes_atol": 1.0e-4,
            "snes_stol": 0.0,
            "snes_max_linear_solve_fail": 10,
            "snes_converged_reason": None,
            "ksp_type": "fgmres",
            "mat_type": "aij",
            # "default_sub_matrix_type": "aij",
            "ksp_rtol": 1.0e-4,
            "ksp_atol": 1.0e-4,
            "ksp_max_it": 2000,
            # "ksp_monitor": None,
            "ksp_converged_reason": None,
            "pc_type": "fieldsplit",
            "pc_fieldsplit_type": "schur",
            "pc_fieldsplit_schur_factorization_type": "full",
            "pc_fieldsplit_schur_precondition": "selfp",
            "fieldsplit_0": {
                "ksp_type": "richardson",
                "ksp_richardson_self_scale": False,
                "ksp_max_it": 1,
                "pc_type": "ml",
                "ksp_atol": 1e-2,
                "pc_mg_cycle_type": "v",
                "pc_mg_type": "full",
                # "ksp_converged_reason": None,
                # "ksp_monitor": None,
            },
            "fieldsplit_1": {
                "ksp_type": "preonly",
                "pc_type": "ml",
                # "ksp_monitor": None,
                # "ksp_converged_reason": None,
            },
            "fieldsplit_1_upper_ksp_type": "preonly",
            "fieldsplit_1_upper_pc_type": "jacobi",
        }
        solver_parameters = kwargs.pop("solver_parameters", None)
        if solver_parameters:
            solver_parameters_default.update(solver_parameters)

        self.solver = fd.NonlinearVariationalSolver(
            problem, solver_parameters=solver_parameters_default, **kwargs)
Exemplo n.º 11
0
def initial_values(sim):

    print("Solving steady heat driven cavity to obtain initial values")

    Ra = 2.518084e6

    Pr = 6.99

    sim.grashof_number = sim.grashof_number.assign(Ra / Pr)

    sim.prandtl_number = sim.prandtl_number.assign(Pr)

    dim = sim.mesh.geometric_dimension()

    T_c = sim.cold_wall_temperature.__float__()

    w = fe.interpolate(
        fe.Expression((0., ) + (0., ) * dim + (T_c, ), element=sim.element),
        sim.function_space)

    F = heat_driven_cavity_variational_form_residual(
        sim=sim, solution=w) * fe.dx(degree=sim.quadrature_degree)

    T_h = sim.hot_wall_temperature.__float__()

    problem = fe.NonlinearVariationalProblem(
        F=F,
        u=w,
        bcs=dirichlet_boundary_conditions(sim),
        J=fe.derivative(F, w))

    solver = fe.NonlinearVariationalSolver(problem=problem,
                                           solver_parameters={
                                               "snes_type": "newtonls",
                                               "snes_monitor": True,
                                               "ksp_type": "preonly",
                                               "pc_type": "lu",
                                               "mat_type": "aij",
                                               "pc_factor_mat_solver_type":
                                               "mumps"
                                           })

    def solve():

        solver.solve()

        return w

    w, _ = \
        sapphire.continuation.solve_with_bounded_regularization_sequence(
            solve = solve,
            solution = w,
            backup_solution = fe.Function(w),
            regularization_parameter = sim.grashof_number,
            initial_regularization_sequence = (
                0., sim.grashof_number.__float__()))

    return w
Exemplo n.º 12
0
def temperature_solver(T, t, beta, PeInv, solver_parameters, *, t1, INLET1, t2,
                       INLET2):
    F_T = AdvectionDiffusionGLS(T, beta, t, PeInv=PeInv)

    bc1 = fd.DirichletBC(T, t1, INLET1)
    bc2 = fd.DirichletBC(T, t2, INLET2)
    bcs = [bc1, bc2]
    problem_T = fd.NonlinearVariationalProblem(F_T, t, bcs=bcs)
    return fd.NonlinearVariationalSolver(problem_T,
                                         solver_parameters=solver_parameters)
Exemplo n.º 13
0
 def update_solver(self):
     """Create solver objects"""
     self.solver = []
     for i in range(self.n_stages):
         p = firedrake.NonlinearVariationalProblem(self.F[i], self.k[i])
         sname = '{:}_stage{:}_'.format(self.name, i)
         self.solver.append(
             firedrake.NonlinearVariationalSolver(
                 p,
                 solver_parameters=self.solver_parameters,
                 options_prefix=sname))
Exemplo n.º 14
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 %s field has type %s, must be Constant or Function!"
                        % (name, type(field))
                    )

        dt = firedrake.Constant(1.0)
        h = self._fields["thickness"]
        u = self._fields["velocity"]
        h_0 = h.copy(deepcopy=True)

        Q = h.function_space()
        mesh = Q.mesh()
        n = FacetNormal(mesh)
        outflow = firedrake.max_value(0, inner(u, n))
        inflow = firedrake.min_value(0, inner(u, n))

        # Additional streamlining terms that give 2nd-order accuracy
        q = firedrake.TestFunction(Q)
        ds = firedrake.ds if mesh.layers is None else firedrake.ds_v
        flux_cells = -div(h * u) * inner(u, grad(q)) * dx
        flux_out = div(h * u) * q * outflow * ds
        flux_in = div(h_0 * u) * q * inflow * ds
        d2h_dt2 = flux_cells + flux_out + flux_in

        dh_dt = self._continuity(dt, **self._fields)
        F = (h - h_0) * q * dx - dt * (dh_dt + 0.5 * dt * d2h_dt2)

        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.º 15
0
    def _setup(self, **kwargs):
        q = kwargs["q"].copy(deepcopy=True)
        f = kwargs["f"].copy(deepcopy=True)
        u = kwargs["u"].copy(deepcopy=True)

        L = self.model.action(u=u, q=q, f=f)
        F = firedrake.derivative(L, u)
        V = u.function_space()
        bc = firedrake.DirichletBC(V, u, self.dirichlet_ids)
        params = {
            "solver_parameters": {
                "ksp_type": "preonly",
                "pc_type": "lu"
            }
        }
        problem = firedrake.NonlinearVariationalProblem(F, u, bc)
        self._solver = firedrake.NonlinearVariationalSolver(problem, **params)
        self._fields = {"q": q, "f": f, "u": u}
Exemplo n.º 16
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.)
        h = self._fields.get('thickness', self._fields.get('h'))
        u = self._fields.get('velocity', self._fields.get('u'))
        h_0 = h.copy(deepcopy=True)

        Q = h.function_space()
        model = self._continuity
        n = model.facet_normal(Q.mesh())
        outflow = firedrake.max_value(0, inner(u, n))
        inflow = firedrake.min_value(0, inner(u, n))

        # Additional streamlining terms that give 2nd-order accuracy
        q = firedrake.TestFunction(Q)
        div, grad, ds = model.div, model.grad, model.ds
        flux_cells = -div(h * u) * inner(u, grad(q)) * dx
        flux_out = div(h * u) * q * outflow * ds
        flux_in = div(h_0 * u) * q * inflow * ds
        d2h_dt2 = flux_cells + flux_out + flux_in

        dh_dt = model(dt, **self._fields)
        F = (h - h_0) * q * dx - dt * (dh_dt + 0.5 * dt * d2h_dt2)

        problem = firedrake.NonlinearVariationalProblem(F, h)
        self._solver = firedrake.NonlinearVariationalSolver(
            problem, solver_parameters=self._solver_parameters)

        self._thickness_old = h_0
        self._timestep = dt
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.mesh_m = self.Q.mesh_m

        # Setup problem
        self.V = fd.FunctionSpace(self.mesh_m, "CG", 1)

        # Preallocate solution variables for state and adjoint equations
        self.solution = fd.Function(self.V, name="State")

        # Weak form of Poisson problem
        u = self.solution
        v = fd.TestFunction(self.V)
        self.f = fd.Constant(4.)
        self.F = (fd.inner(fd.grad(u), fd.grad(v)) - self.f * v) * fd.dx
        self.bcs = fd.DirichletBC(self.V, 0., "on_boundary")

        # PDE-solver parameters
        self.params = {
            "ksp_type": "cg",
            "mat_type": "aij",
            "pc_type": "hypre",
            "pc_factor_mat_solver_package": "boomerang",
            "ksp_rtol": 1e-11,
            "ksp_atol": 1e-11,
            "ksp_stol": 1e-15,
        }

        stateproblem = fd.NonlinearVariationalProblem(
            self.F, self.solution, bcs=self.bcs)
        self.solver = fd.NonlinearVariationalSolver(
            stateproblem, solver_parameters=self.params)

        # target function, exact soln is disc of radius 0.6 centered at
        # (0.5,0.5)
        (x, y) = fd.SpatialCoordinate(self.mesh_m)
        self.u_target = 0.36 - (x-0.5)*(x-0.5) - (y-0.5)*(y-0.5)
Exemplo n.º 18
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 homogeneous BCs for the Dirichlet part of the boundary
        u = self._fields["velocity"]
        V = u.function_space()
        bcs = firedrake.DirichletBC(V, u, 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)
        F = firedrake.derivative(action, u)

        problem = firedrake.NonlinearVariationalProblem(F, u, bcs)
        self._solver = firedrake.NonlinearVariationalSolver(
            problem, solver_parameters=self._solver_parameters
        )
Exemplo n.º 19
0
    def solve(self) -> fe.Function:
        """Set up the problem and solver, and solve.
        
        This is a JIT (just in time), ensuring that the problem and 
        solver setup are up-to-date before calling the solver.
        All compiled objects are cached, so the JIT problem and solver 
        setup does not have any significant performance overhead.
        """
        problem = fe.NonlinearVariationalProblem(
            F=self.weak_form_residual(),
            u=self.solution,
            bcs=self.dirichlet_boundary_conditions(),
            J=fe.derivative(self.weak_form_residual(), self.solution))

        solver = fe.NonlinearVariationalSolver(
            problem=problem,
            nullspace=self.nullspace(),
            solver_parameters=self.solver_parameters)

        solver.solve()

        self.snes_iteration_count += solver.snes.getIterationNumber()

        return self.solution
Exemplo n.º 20
0
    "mat_type": "matfree",
    "pmat_type": "matfree",
    "ksp_type": "preonly",
    "pc_type": "python",
    # Use the static condensation PC for hybridized problems
    # and use a direct solve on the reduced system for lambda_h
    "pc_python_type": "firedrake.SCPC",
    "pc_sc_eliminate_fields": "0, 1",
    "condensed_field": {
        "ksp_type": "preonly",
        "pc_type": "lu",
        "pc_factor_mat_solver_type": "mumps"
    }
}

solver = fd.NonlinearVariationalSolver(problem,
                                       solver_parameters=hybrid_solver_params)

# -----------------
wave_speed = fd.conditional(fd.lt(np.abs(vnorm), tol), h / tol, h / vnorm)
# CFL
dt_ = fd.interpolate(wave_speed, DG1).dat.data.min() * cfl
outfile = fd.File(f"plots/adr-hdg-n-{refine}-p-{order}.pvd",
                  project_output=True)
dt = dt_  # dtime
dtc.assign(dt_)

# %%
# solve problem

# initialize timestep
t = 0.0
Exemplo n.º 21
0
# shock capturing parameters
if add_shock_term:
    cnorm = fd.sqrt(fd.dot(fd.grad(c0), fd.grad(c0)))
    vshock = fd.conditional(
        fd.gt(cnorm, 1e-15),
        beta * h / (2 * cnorm),  # *cnorm,
        fd.Constant(0.))

    # shock terms
    # F1 += vshock*fd.dot(fd.grad(w), fd.grad(c_mid))*fd.dx
    F1 += vshock * np.abs(R) * fd.inner(fd.grad(w), fd.grad(c_mid)) * fd.dx

F = F1

prob = fd.NonlinearVariationalProblem(F, c, bcs=t_bc)
transport = fd.NonlinearVariationalSolver(prob)

# %%
# 4) Solve problem
c0.assign(0.)
t = it = 0
outfile = fd.File("plots/adr_supg_shock.pvd")
c0.rename("c")

dt = CFL * fd.interpolate(h / vnorm, DG0).dat.data.min()
Dt.assign(dt)
dt0 = dt

Pe = vnorm * h / (2.0 * Diff)
print('Peclet = {}; dt = {}'.format(
    fd.interpolate(Pe, DG0).dat.data.mean(), dt))
Exemplo n.º 22
0
def test_set_para_form_mixed():
    # checks that the all-at-once system is the same as solving
    # timesteps sequentially using the mixed wave equation as an
    # example by substituting the sequential solution and evaluating
    # the residual

    mesh = fd.PeriodicUnitSquareMesh(20, 20)
    V = fd.FunctionSpace(mesh, "BDM", 1)
    Q = fd.FunctionSpace(mesh, "DG", 0)
    W = V * Q

    x, y = fd.SpatialCoordinate(mesh)
    w0 = fd.Function(W)
    u0, p0 = w0.split()
    p0.interpolate(fd.exp(-((x - 0.5)**2 + (y - 0.5)**2) / 0.5**2))
    dt = 0.01
    theta = 0.5
    alpha = 0.001
    M = 4
    solver_parameters = {
        'ksp_type': 'gmres',
        'pc_type': 'none',
        'ksp_rtol': 1.0e-8,
        'ksp_atol': 1.0e-8,
        'ksp_monitor': None
    }

    def form_function(uu, up, vu, vp):
        return (fd.div(vu) * up - fd.div(uu) * vp) * fd.dx

    def form_mass(uu, up, vu, vp):
        return (fd.inner(uu, vu) + up * vp) * fd.dx

    PD = asQ.paradiag(form_function=form_function,
                      form_mass=form_mass,
                      W=W,
                      w0=w0,
                      dt=dt,
                      theta=theta,
                      alpha=alpha,
                      M=M,
                      solver_parameters=solver_parameters,
                      circ="none")

    # sequential solver
    un = fd.Function(W)
    unp1 = fd.Function(W)

    un.assign(w0)
    v = fd.TestFunction(W)

    eqn = (1.0 / dt) * form_mass(*(fd.split(unp1)), *(fd.split(v)))
    eqn -= (1.0 / dt) * form_mass(*(fd.split(un)), *(fd.split(v)))
    eqn += fd.Constant(
        (1 - theta)) * form_function(*(fd.split(un)), *(fd.split(v)))
    eqn += fd.Constant(theta) * form_function(*(fd.split(unp1)),
                                              *(fd.split(v)))

    sprob = fd.NonlinearVariationalProblem(eqn, unp1)
    solver_parameters = {
        'ksp_type': 'preonly',
        'pc_type': 'lu',
        'pc_factor_mat_solver_type': 'mumps',
        'mat_type': 'aij'
    }
    ssolver = fd.NonlinearVariationalSolver(
        sprob, solver_parameters=solver_parameters)

    for i in range(M):
        ssolver.solve()
        for k in range(2):
            PD.w_all.sub(2 * i + k).assign(unp1.sub(k))
        un.assign(unp1)

    Pres = fd.assemble(PD.para_form)
    for i in range(M):
        assert (dt * np.abs(Pres.sub(i).dat.data[:]).max() < 1.0e-16)
Exemplo n.º 23
0
# Upwind normal velocity: (dot(vD, n) + |dot(vD, n)|)/2.0
un = 0.5 * (fd.dot(u0, n) + abs(fd.dot(u0, n)))

F_s = r*phi*(s - s0)*fd.dx - \
    dtc*(fd.dot(fd.grad(r), Fw(s_mid)*u)*fd.dx - r*Fw(s_mid)*un*fd.ds
         - fd.conditional(fd.dot(u0, n) < 0, r *
                          fd.dot(u0, n)*Fw(s_in), 0.0)*fd.ds
         - (r('+') - r('-'))*(un('+')*Fw(s_mid)('+') -
                              un('-')*Fw(s_mid)('-'))*fd.dS)

# Res.
R = F_p + F_s

prob = fd.NonlinearVariationalProblem(R, U, bcs=[bc0, bc1, bc3])
solver2ph = fd.NonlinearVariationalSolver(prob)

# %%
# 4) Solve problem
# initialize variables
xv, xp, xs = U.split()
vel = fd.project(u0, P1)
xp.rename('pressure')
xs.rename('saturation')
vel.rename('velocity')

outfile = fd.File(oFile)
it = 0
t = 0.0
while t < sim_time:
    t += dt
Exemplo n.º 24
0
def test_quasi():
    # tests the quasi-Newton option
    # using the heat equation as an example

    mesh = fd.UnitSquareMesh(20, 20)
    V = fd.FunctionSpace(mesh, "CG", 1)

    x, y = fd.SpatialCoordinate(mesh)
    u0 = fd.Function(V).interpolate(
        fd.exp(-((x - 0.5)**2 + (y - 0.5)**2) / 0.5**2))
    dt = 0.01
    theta = 0.5
    alpha = 0.001
    M = 4
    solver_parameters = {
        'ksp_type': 'preonly',
        'pc_type': 'lu',
        'pc_factor_mat_solver_type': 'mumps',
        'mat_type': 'aij',
        'snes_monitor': None
    }

    # Solving U_t + F(U) = 0
    # defining F(U)
    def form_function(u, v):
        return fd.inner(fd.grad(u), fd.grad(v)) * fd.dx

    # defining the structure of U_t
    def form_mass(u, v):
        return u * v * fd.dx

    PD = asQ.paradiag(form_function=form_function,
                      form_mass=form_mass,
                      W=V,
                      w0=u0,
                      dt=dt,
                      theta=theta,
                      alpha=alpha,
                      M=M,
                      solver_parameters=solver_parameters,
                      circ="quasi")
    PD.solve()

    # sequential solver
    un = fd.Function(V)
    unp1 = fd.Function(V)

    un.assign(u0)
    v = fd.TestFunction(V)

    eqn = (unp1 - un) * v * fd.dx
    eqn += fd.Constant(dt * (1 - theta)) * form_function(un, v)
    eqn += fd.Constant(dt * theta) * form_function(unp1, v)

    sprob = fd.NonlinearVariationalProblem(eqn, unp1)
    solver_parameters = {'ksp_type': 'preonly', 'pc_type': 'lu'}
    ssolver = fd.NonlinearVariationalSolver(
        sprob, solver_parameters=solver_parameters)

    err = fd.Function(V, name="err")
    pun = fd.Function(V, name="pun")
    for i in range(M):
        ssolver.solve()
        un.assign(unp1)
        pun.assign(PD.w_all.sub(i))
        err.assign(un - pun)
        assert (fd.norm(err) < 1.0e-10)
Exemplo n.º 25
0
    def __init__(self,
                 problem,
                 u_degree=1,
                 p_degree=1,
                 lambda_degree=1,
                 method="cgls"):
        self.problem = problem
        self.method = method
        mesh = problem.mesh
        bcs_p = problem.bcs_p
        bcs_u = problem.bcs_u

        if method == "cgls":
            pressure_family = "CG"
            velocity_family = "CG"
            dirichlet_method = "topological"
        elif method == "dgls":
            pressure_family = "DG"
            velocity_family = "DG"
            dirichlet_method = "geometric"
        elif method == "sdhm":
            pressure_family = "DG"
            velocity_family = "DG"
            trace_family = "HDiv Trace"
            dirichlet_method = "topological"
        else:
            raise ValueError(
                f"Invalid FEM for solving Darcy Flow. Method provided: {method}"
            )

        self._U = fire.VectorFunctionSpace(mesh, velocity_family, u_degree)
        self._V = fire.FunctionSpace(mesh, pressure_family, p_degree)

        if method == "cgls" or method == "dgls":
            self._W = self._U * self._V
        if method == "sdhm":
            self._T = fire.FunctionSpace(mesh, trace_family, lambda_degree)
            self._W = self._U * self._V * self._T

        self.solution = fire.Function(self._W)
        if method == "cgls":
            self.u, self.p = self.solution.split()
            self._a, self._L = self.cgls_form(problem, mesh, bcs_p)
        if method == "dgls":
            self.u, self.p = self.solution.split()
            self._a, self._L = self.dgls_form(problem, mesh, bcs_p)
        if method == "sdhm":
            self.u, self.p, self.tracer = self.solution.split()
            self._a, self._L = self.sdhm_form(problem, mesh, bcs_p, bcs_u)

        self.u.rename("u", "label")
        self.p.rename("p", "label")
        if method == "sdhm":
            self.solver_parameters = {
                "snes_type": "ksponly",
                "mat_type": "matfree",
                "pmat_type": "matfree",
                "ksp_type": "preonly",
                "pc_type": "python",
                # Use the static condensation PC for hybridized problems
                # and use a direct solve on the reduced system for lambda_h
                "pc_python_type": "firedrake.SCPC",
                "pc_sc_eliminate_fields": "0, 1",
                "condensed_field": {
                    "ksp_type": "preonly",
                    "pc_type": "lu",
                    "pc_factor_mat_solver_type": "mumps",
                },
            }

            F = self._a - self._L
            nvp = fire.NonlinearVariationalProblem(F, self.solution)

            self.solver = fire.NonlinearVariationalSolver(
                nvp, solver_parameters=self.solver_parameters)
        else:
            self.bcs = []
            rho = self.problem.rho
            for uboundary, iboundary, component in bcs_u:
                if component is not None:
                    self.bcs.append(
                        DirichletExpressionBC(
                            self._W.sub(0).sub(component),
                            rho * uboundary,
                            iboundary,
                            method=dirichlet_method,
                        ))
                else:
                    self.bcs.append(
                        DirichletExpressionBC(self._W.sub(0),
                                              rho * uboundary,
                                              iboundary,
                                              method=dirichlet_method))

            # self.solver_parameters = {
            #     # This setup is suitable for 3D
            #     'ksp_type': 'lgmres',
            #     'pc_type': 'lu',
            #     'mat_type': 'aij',
            #     'ksp_rtol': 1e-8,
            #     'ksp_max_it': 2000,
            #     'ksp_monitor': None
            # }
            self.solver_parameters = {
                "mat_type": "aij",
                "ksp_type": "preonly",
                "pc_type": "lu",
                "pc_factor_mat_solver_type": "mumps",
            }

            lvp = fire.LinearVariationalProblem(self._a,
                                                self._L,
                                                self.solution,
                                                bcs=self.bcs)

            self.solver = fire.LinearVariationalSolver(
                lvp, solver_parameters=self.solver_parameters)
Exemplo n.º 26
0
# full weak form
F = F_sb + F_t + F_a + F_d


# assign problem and solver
dw = fd.TrialFunction(W)
J = fd.derivative(F, w, dw)

problem = fd.NonlinearVariationalProblem(F, w, bcs, J)
param = {
    'snes_type': 'newtonls',
    'snes_max_it': 100,
    'ksp_type': 'gmres',
    'ksp_rtol': 1e-3
}
solver = fd.NonlinearVariationalSolver(problem, solver_parameters=param)


# %%
# 4) Solve problem
# -----------------
wave_speed = fd.conditional(fd.lt(abs(vnorm), tol), h_E/tol, h_E/vnorm)
outfile = fd.File("plots/sb_adr_fi.pvd")

w0.sub(2).assign(0.0)

# initialize timestep
t = 0.0
it = 0
dt = np.sqrt(tol)
element = fe.FiniteElement("P", mesh.ufl_cell(), 1)

V = fe.FunctionSpace(mesh, element)

u = fe.Function(V)

v = fe.TestFunction(V)

bc = fe.DirichletBC(V, 0., "on_boundary")

alpha = 1 + u/10.

x = fe.SpatialCoordinate(mesh)[0]

div, grad, dot, sin, pi, dx = fe.div, fe.grad, fe.dot, fe.sin, fe.pi, fe.dx

f = 10.*sin(pi*x)

R = (-dot(grad(v), alpha*grad(u)) - v*f)*dx


problem = fe.NonlinearVariationalProblem(R, u, bc, fe.derivative(R, u))

solver = fe.NonlinearVariationalSolver(
    problem, solver_parameters = {"snes_monitor": True})

solver.solve()

print("u_h = " + str(u.vector()[:]))
def initial_values(sim):

    print("Solving steady heat driven cavity to obtain initial values")

    Ra = 2.518084e6

    Pr = 6.99

    sim.reference_temperature_range__degC.assign(10.)

    sim.grashof_number = sim.grashof_number.assign(Ra / Pr)

    sim.prandtl_number = sim.prandtl_number.assign(Pr)

    w = fe.Function(sim.function_space)

    p, u, T = w.split()

    p.assign(0.)

    ihat, jhat = sim.unit_vectors()

    u.assign(0. * ihat + 0. * jhat)

    T.assign(sim.cold_wall_temperature)

    F = heat_driven_cavity_variational_form_residual(
        sim=sim, solution=w) * fe.dx(degree=sim.quadrature_degree)

    problem = fe.NonlinearVariationalProblem(
        F=F,
        u=w,
        bcs=dirichlet_boundary_conditions(sim),
        J=fe.derivative(F, w))

    solver = fe.NonlinearVariationalSolver(problem=problem,
                                           solver_parameters={
                                               "snes_type": "newtonls",
                                               "snes_monitor": None,
                                               "ksp_type": "preonly",
                                               "pc_type": "lu",
                                               "mat_type": "aij",
                                               "pc_factor_mat_solver_type":
                                               "mumps"
                                           })

    def solve():

        solver.solve()

        return w

    w, _ = \
        sapphire.continuation.solve_with_bounded_regularization_sequence(
            solve = solve,
            solution = w,
            backup_solution = fe.Function(w),
            regularization_parameter = sim.grashof_number,
            initial_regularization_sequence = (
                0., sim.grashof_number.__float__()))

    return w
Exemplo n.º 29
0
def compute_time_accuracy_via_mms(
        gridsize, element_degree, timestep_sizes, endtime):
    
    mesh = fe.UnitIntervalMesh(gridsize)
    
    element = fe.FiniteElement("P", mesh.ufl_cell(), element_degree)
    
    V = fe.FunctionSpace(mesh, element)
    
    u_h = fe.Function(V)
    
    v = fe.TestFunction(V)
    
    un = fe.Function(V)
    
    u_m = manufactured_solution(mesh)
    
    bc = fe.DirichletBC(V, u_m, "on_boundary")
    
    _F = F(u_h, v, un)
    
    problem = fe.NonlinearVariationalProblem(
        _F - v*R(u_m)*dx,
        u_h,
        bc,
        fe.derivative(_F, u_h))
    
    solver = fe.NonlinearVariationalSolver(problem)
    
    t.assign(0.)
    
    initial_values = fe.interpolate(u_m, V)
    
    L2_norm_errors = []
    
    print("Delta_t, L2_norm_error")
    
    for timestep_size in timestep_sizes:
        
        Delta_t.assign(timestep_size)
        
        un.assign(initial_values)
        
        time = 0.
        
        t.assign(time)
        
        while time < (endtime - TIME_EPSILON):
            
            time += timestep_size
            
            t.assign(time)
            
            solver.solve()
            
            un.assign(u_h)

        L2_norm_errors.append(
            math.sqrt(fe.assemble(fe.inner(u_h - u_m, u_h - u_m)*dx)))
        
        print(str(timestep_size) + ", " + str(L2_norm_errors[-1]))
    
    r = timestep_sizes[-2]/timestep_sizes[-1]
    
    e = L2_norm_errors
    
    log = math.log
    
    order = log(e[-2]/e[-1])/log(r)
    
    return order
Exemplo n.º 30
0
def compliance_optimization(n_iters=200):

    output_dir = "cantilever/"

    path = os.path.abspath(__file__)
    dir_path = os.path.dirname(path)
    m = fd.Mesh(f"{dir_path}/mesh_cantilever.msh")
    mesh = fd.MeshHierarchy(m, 0)[-1]

    # Perturb the mesh coordinates. Necessary to calculate shape derivatives
    S = fd.VectorFunctionSpace(mesh, "CG", 1)
    s = fd.Function(S, name="deform")
    mesh.coordinates.assign(mesh.coordinates + s)

    # Initial level set function
    x, y = fd.SpatialCoordinate(mesh)
    PHI = fd.FunctionSpace(mesh, "CG", 1)
    lx = 2.0
    ly = 1.0
    phi_expr = (
        -cos(6.0 / lx * pi * x) * cos(4.0 * pi * y)
        - 0.6
        + max_value(200.0 * (0.01 - x ** 2 - (y - ly / 2) ** 2), 0.0)
        + max_value(100.0 * (x + y - lx - ly + 0.1), 0.0)
        + max_value(100.0 * (x - y - lx + 0.1), 0.0)
    )
    # Avoid recording the operation interpolate into the tape.
    # Otherwise, the shape derivatives will not be correct
    with fda.stop_annotating():
        phi = fd.interpolate(phi_expr, PHI)
        phi.rename("LevelSet")
        fd.File(output_dir + "phi_initial.pvd").write(phi)

    # Physics. Elasticity
    rho_min = 1e-5
    beta = fd.Constant(200.0)

    def hs(phi, beta):
        return fd.Constant(1.0) / (
            fd.Constant(1.0) + exp(-beta * phi)
        ) + fd.Constant(rho_min)

    H1_elem = fd.VectorElement("CG", mesh.ufl_cell(), 1)
    W = fd.FunctionSpace(mesh, H1_elem)

    u = fd.TrialFunction(W)
    v = fd.TestFunction(W)

    # Elasticity parameters
    E, nu = 1.0, 0.3
    mu, lmbda = fd.Constant(E / (2 * (1 + nu))), fd.Constant(
        E * nu / ((1 + nu) * (1 - 2 * nu))
    )

    def epsilon(u):
        return sym(nabla_grad(u))

    def sigma(v):
        return 2.0 * mu * epsilon(v) + lmbda * tr(epsilon(v)) * Identity(2)

    a = inner(hs(-phi, beta) * sigma(u), nabla_grad(v)) * dx
    t = fd.Constant((0.0, -75.0))
    L = inner(t, v) * ds(2)

    bc = fd.DirichletBC(W, fd.Constant((0.0, 0.0)), 1)
    parameters = {
        "ksp_type": "preonly",
        "pc_type": "lu",
        "mat_type": "aij",
        "ksp_converged_reason": None,
        "pc_factor_mat_solver_type": "mumps",
    }
    u_sol = fd.Function(W)
    F = fd.action(a, u_sol) - L
    problem = fd.NonlinearVariationalProblem(F, u_sol, bcs=bc)
    solver = fd.NonlinearVariationalSolver(
        problem, solver_parameters=parameters
    )
    solver.solve()
    # fd.solve(
    #    a == L, u_sol, bcs=[bc], solver_parameters=parameters
    # )  # , nullspace=nullspace)
    with fda.stop_annotating():
        fd.File("u_sol.pvd").write(u_sol)

    # Cost function: Compliance
    J = fd.assemble(
        fd.Constant(1e-2)
        * inner(hs(-phi, beta) * sigma(u_sol), epsilon(u_sol))
        * dx
    )

    # Constraint: Volume
    with fda.stop_annotating():
        total_volume = fd.assemble(fd.Constant(1.0) * dx(domain=mesh))
    VolPen = fd.assemble(hs(-phi, beta) * dx)
    # Needed to track the value of the volume
    VolControl = fda.Control(VolPen)
    Vval = total_volume / 2.0

    phi_pvd = fd.File("phi_evolution.pvd", target_continuity=fd.H1)

    def deriv_cb(phi):
        with fda.stop_annotating():
            phi_pvd.write(phi[0])

    c = fda.Control(s)
    Jhat = LevelSetFunctional(J, c, phi, derivative_cb_pre=deriv_cb)
    Vhat = LevelSetFunctional(VolPen, c, phi)
    beta_param = 0.1
    # Boundary conditions for the shape derivatives.
    # They must be zero at the boundary conditions.
    bcs_vel = fd.DirichletBC(S, fd.Constant((0.0, 0.0)), (1, 2))
    # Regularize the shape derivatives
    reg_solver = RegularizationSolver(
        S,
        mesh,
        beta=beta_param,
        gamma=1.0e5,
        dx=dx,
        bcs=bcs_vel,
        output_dir=None,
    )
    # Hamilton-Jacobi equation to advect the level set
    dt = 0.05
    tol = 1e-5

    # Optimization problem
    vol_constraint = Constraint(Vhat, Vval, VolControl)
    problem = InfDimProblem(Jhat, reg_solver, ineqconstraints=vol_constraint)

    parameters = {
        "ksp_type": "preonly",
        "pc_type": "lu",
        "mat_type": "aij",
        "ksp_converged_reason": None,
        "pc_factor_mat_solver_type": "mumps",
    }

    params = {
        "alphaC": 3.0,
        "K": 0.1,
        "debug": 5,
        "alphaJ": 1.0,
        "dt": dt,
        "maxtrials": 10,
        "maxit": n_iters,
        "itnormalisation": 50,
        "tol": tol,
    }
    results = nlspace_solve(problem, params)

    return results