def coarsen_nlvp(problem, coefficient_mapping=None):
    # Build set of coefficients we need to coarsen
    seen = set()
    coefficients = problem.F.coefficients() + problem.J.coefficients()
    if problem.Jp is not None:
        coefficients = coefficients + problem.Jp.coefficients()

    # Coarsen them, and remember where from.
    if coefficient_mapping is None:
        coefficient_mapping = {}
    for c in coefficients:
        if c not in seen:
            coefficient_mapping[c] = coarsen(
                c, coefficient_mapping=coefficient_mapping)
            seen.add(c)

    u = coefficient_mapping[problem.u]

    bcs = [coarsen(bc) for bc in problem.bcs]
    J = coarsen(problem.J, coefficient_mapping=coefficient_mapping)
    Jp = coarsen(problem.Jp, coefficient_mapping=coefficient_mapping)
    F = coarsen(problem.F, coefficient_mapping=coefficient_mapping)

    problem = firedrake.NonlinearVariationalProblem(
        F,
        u,
        bcs=bcs,
        J=J,
        Jp=Jp,
        form_compiler_parameters=problem.form_compiler_parameters)
    return problem
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
Exemple #3
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)
 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))
Exemple #5
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
Exemple #6
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}
Exemple #7
0
def test_solver_no_flow_region():
    mesh = fd.Mesh("./2D_mesh.msh")
    no_flow = [2]
    no_flow_markers = [1]
    mesh = mark_no_flow_regions(mesh, no_flow, no_flow_markers)
    P2 = fd.VectorElement("CG", mesh.ufl_cell(), 1)
    P1 = fd.FiniteElement("CG", mesh.ufl_cell(), 1)
    TH = P2 * P1
    W = fd.FunctionSpace(mesh, TH)
    (v, q) = fd.TestFunctions(W)

    # Stokes 1
    w_sol1 = fd.Function(W)
    nu = fd.Constant(0.05)
    F = NavierStokesBrinkmannForm(W, w_sol1, nu, beta_gls=2.0)

    x, y = fd.SpatialCoordinate(mesh)
    u_mms = fd.as_vector(
        [sin(2.0 * pi * x) * sin(pi * y),
         sin(pi * x) * sin(2.0 * pi * y)])
    p_mms = -0.5 * (u_mms[0]**2 + u_mms[1]**2)
    f_mms_u = (grad(u_mms) * u_mms + grad(p_mms) -
               2.0 * nu * div(sym(grad(u_mms))))
    f_mms_p = div(u_mms)
    F += -inner(f_mms_u, v) * dx - f_mms_p * q * dx
    bc1 = fd.DirichletBC(W.sub(0), u_mms, "on_boundary")
    bc2 = fd.DirichletBC(W.sub(1), p_mms, "on_boundary")
    bc_no_flow = InteriorBC(W.sub(0), fd.Constant((0.0, 0.0)), no_flow_markers)

    solver_parameters = {"ksp_max_it": 500, "ksp_monitor": None}

    problem1 = fd.NonlinearVariationalProblem(F,
                                              w_sol1,
                                              bcs=[bc1, bc2, bc_no_flow])
    solver1 = NavierStokesBrinkmannSolver(
        problem1,
        options_prefix="navier_stokes",
        solver_parameters=solver_parameters,
    )
    solver1.solve()
    u_sol, _ = w_sol1.split()
    u_mms_func = fd.interpolate(u_mms, W.sub(0))
    error = fd.errornorm(u_sol, u_mms_func)
    assert error < 0.07
Exemple #8
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
Exemple #9
0
def run_solver(r):
    mesh = fd.UnitSquareMesh(2**r, 2**r)
    P2 = fd.VectorElement("CG", mesh.ufl_cell(), 1)
    P1 = fd.FiniteElement("CG", mesh.ufl_cell(), 1)
    TH = P2 * P1
    W = fd.FunctionSpace(mesh, TH)
    (v, q) = fd.TestFunctions(W)

    # Stokes 1
    w_sol1 = fd.Function(W)
    nu = fd.Constant(0.05)
    F = NavierStokesBrinkmannForm(W, w_sol1, nu, beta_gls=2.0)

    from firedrake import sin, grad, pi, sym, div, inner

    x, y = fd.SpatialCoordinate(mesh)
    u_mms = fd.as_vector(
        [sin(2.0 * pi * x) * sin(pi * y),
         sin(pi * x) * sin(2.0 * pi * y)])
    p_mms = -0.5 * (u_mms[0]**2 + u_mms[1]**2)
    f_mms_u = (grad(u_mms) * u_mms + grad(p_mms) -
               2.0 * nu * div(sym(grad(u_mms))))
    f_mms_p = div(u_mms)
    F += -inner(f_mms_u, v) * dx - f_mms_p * q * dx
    bc1 = fd.DirichletBC(W.sub(0), u_mms, "on_boundary")
    bc2 = fd.DirichletBC(W.sub(1), p_mms, "on_boundary")

    solver_parameters = {"ksp_max_it": 200}

    problem1 = fd.NonlinearVariationalProblem(F, w_sol1, bcs=[bc1, bc2])
    solver1 = NavierStokesBrinkmannSolver(
        problem1,
        options_prefix="navier_stokes",
        solver_parameters=solver_parameters,
    )
    solver1.solve()
    u_sol, _ = w_sol1.split()
    fd.File("test_u_sol.pvd").write(u_sol)
    u_mms_func = fd.interpolate(u_mms, W.sub(0))
    error = fd.errornorm(u_sol, u_mms_func)
    print(f"Error: {error}")
    return error
def coarsen_problem(problem):
    u = problem.u
    h, lvl = utils.get_level(u)
    if lvl == -1:
        raise RuntimeError("No hierarchy to coarsen")
    if lvl == 0:
        return None
    new_u = ufl_utils.coarsen_thing(problem.u)
    new_bcs = [ufl_utils.coarsen_thing(bc) for bc in problem.bcs]
    new_J = ufl_utils.coarsen_form(problem.J)
    new_Jp = ufl_utils.coarsen_form(problem.Jp)
    new_F = ufl_utils.coarsen_form(problem.F)

    new_problem = firedrake.NonlinearVariationalProblem(new_F,
                                                        new_u,
                                                        bcs=new_bcs,
                                                        J=new_J,
                                                        Jp=new_Jp,
                                                        form_compiler_parameters=problem.form_compiler_parameters,
                                                        nest=problem._nest)
    return new_problem
Exemple #11
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:
                self._fields[name] = utilities.copy(field)

        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
Exemple #12
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 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()
        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)
Exemple #13
0
def flow_solver(
    W,
    w_sol,
    no_flow=None,
    phi=None,
    beta_gls=0.9,
    design_domain=None,
    solver_parameters=None,
    brinkmann_penalty=0.0,
    *,
    inflow,
    inlet,
    walls,
    nu,
):
    F = NavierStokesBrinkmannForm(
        W,
        w_sol,
        nu,
        phi=phi,
        brinkmann_penalty=brinkmann_penalty,
        design_domain=design_domain,
        beta_gls=beta_gls,
    )

    noslip = fd.Constant((0.0, 0.0, 0.0))
    bcs_1 = fd.DirichletBC(W.sub(0), noslip, walls)
    bcs_2 = fd.DirichletBC(W.sub(0), inflow, inlet)
    bcs = [bcs_1, bcs_2]
    if no_flow:
        bcs_no_flow = InteriorBC(W.sub(0), noslip, no_flow)
    bcs.append(bcs_no_flow)

    problem = fd.NonlinearVariationalProblem(F, w_sol, bcs=bcs)

    return NavierStokesBrinkmannSolver(problem,
                                       solver_parameters=solver_parameters)
    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)
Exemple #15
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
        )
Exemple #16
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
Exemple #17
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)
Exemple #18
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)
Exemple #19
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)
Exemple #20
0
    def coarsen(self, fdm, comm):
        fctx = get_appctx(fdm)
        test, trial = fctx.J.arguments()
        fV = test.function_space()
        fu = fctx._problem.u

        cele = self.coarsen_element(fV.ufl_element())
        cV = firedrake.FunctionSpace(fV.mesh(), cele)
        cdm = cV.dm

        cu = firedrake.Function(cV)
        interpolators = tuple(
            firedrake.Interpolator(fus, cus)
            for fus, cus in zip(fu.split(), cu.split()))

        def inject_state(interpolators):
            for interpolator in interpolators:
                interpolator.interpolate()

        parent = get_parent(fdm)
        assert parent is not None
        add_hook(parent,
                 setup=partial(push_parent, cdm, parent),
                 teardown=partial(pop_parent, cdm, parent),
                 call_setup=True)

        replace_d = {
            fu: cu,
            test: firedrake.TestFunction(cV),
            trial: firedrake.TrialFunction(cV)
        }
        cJ = replace(fctx.J, replace_d)
        cF = replace(fctx.F, replace_d)
        if fctx.Jp is not None:
            cJp = replace(fctx.Jp, replace_d)
        else:
            cJp = None

        cbcs = []
        for bc in fctx._problem.bcs:
            # Don't actually need the value, since it's only used for
            # killing parts of the matrix. This should be generalised
            # for p-FAS, if anyone ever wants to do that

            cV_ = cV
            for index in bc._indices:
                cV_ = cV_.sub(index)

            cbcs.append(
                firedrake.DirichletBC(cV_,
                                      firedrake.zero(cV_.shape),
                                      bc.sub_domain,
                                      method=bc.method))

        fcp = fctx._problem.form_compiler_parameters
        cproblem = firedrake.NonlinearVariationalProblem(
            cF,
            cu,
            cbcs,
            cJ,
            Jp=cJp,
            form_compiler_parameters=fcp,
            is_linear=fctx._problem.is_linear)

        cctx = _SNESContext(
            cproblem,
            fctx.mat_type,
            fctx.pmat_type,
            appctx=fctx.appctx,
            pre_jacobian_callback=fctx._pre_jacobian_callback,
            pre_function_callback=fctx._pre_function_callback,
            post_jacobian_callback=fctx._post_jacobian_callback,
            post_function_callback=fctx._post_function_callback,
            options_prefix=fctx.options_prefix,
            transfer_manager=fctx.transfer_manager)

        add_hook(parent,
                 setup=partial(push_appctx, cdm, cctx),
                 teardown=partial(pop_appctx, cdm, cctx),
                 call_setup=True)
        add_hook(parent,
                 setup=partial(inject_state, interpolators),
                 call_setup=True)

        cdm.setKSPComputeOperators(_SNESContext.compute_operators)
        cdm.setCreateInterpolation(self.create_interpolation)
        cdm.setOptionsPrefix(fdm.getOptionsPrefix())

        # If we're the coarsest grid of the p-hierarchy, don't
        # overwrite the coarsen routine; this is so that you can
        # use geometric multigrid for the p-coarse problem
        try:
            self.coarsen_element(cele)
            cdm.setCoarsen(self.coarsen)
        except ValueError:
            pass

        return cdm
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
Exemple #22
0
def main():
    mesh = fd.Mesh("./mesh_stokes.msh")
    mh = fd.MeshHierarchy(mesh, 1)
    mesh = mh[-1]
    # mesh = fd.Mesh("./mesh_stokes_inlets.msh")
    S = fd.VectorFunctionSpace(mesh, "CG", 1)
    s = fd.Function(S, name="deform")
    mesh.coordinates.assign(mesh.coordinates + s)

    x, y = fd.SpatialCoordinate(mesh)
    PHI = fd.FunctionSpace(mesh, "DG", 1)
    lx = 1.0
    # phi_expr = -0.5 * cos(3.0 / lx * pi * x + 1.0) * cos(3.0 * pi * y) - 0.3
    lx = 2.0
    phi_expr = -cos(6.0 / lx * pi * x + 1.0) * cos(4.0 * pi * y) - 0.6

    with stop_annotating():
        phi = fd.interpolate(phi_expr, PHI)
    phi.rename("LevelSet")

    nu = fd.Constant(1.0)
    V = fd.VectorFunctionSpace(mesh, "CG", 1)
    P = fd.FunctionSpace(mesh, "CG", 1)
    W = V * P
    w_sol = fd.Function(W)
    brinkmann_penalty = 1e6
    F = NavierStokesBrinkmannForm(W,
                                  w_sol,
                                  phi,
                                  nu,
                                  brinkmann_penalty=brinkmann_penalty)

    x, y = fd.SpatialCoordinate(mesh)
    u_inflow = 1.0
    y_inlet_1_1 = 0.2
    y_inlet_1_2 = 0.4
    inflow1 = fd.as_vector([
        u_inflow * 100 * (y - y_inlet_1_1) * (y - y_inlet_1_2),
        0.0,
    ])
    y_inlet_2_1 = 0.6
    y_inlet_2_2 = 0.8
    inflow2 = fd.as_vector([
        u_inflow * 100 * (y - y_inlet_2_1) * (y - y_inlet_2_2),
        0.0,
    ])

    noslip = fd.Constant((0.0, 0.0))
    bc1 = fd.DirichletBC(W.sub(0), noslip, 5)
    bc2 = fd.DirichletBC(W.sub(0), inflow1, (1))
    bc3 = fd.DirichletBC(W.sub(0), inflow2, (2))
    bcs = [bc1, bc2, bc3]

    problem = fd.NonlinearVariationalProblem(F, w_sol, bcs=bcs)
    solver_parameters = {
        "ksp_type": "preonly",
        "pc_type": "lu",
        "mat_type": "aij",
        "ksp_converged_reason": None,
        "pc_factor_mat_solver_type": "mumps",
    }
    # solver_parameters = {
    #    "ksp_type": "fgmres",
    #    "pc_type": "hypre",
    #    "pc_hypre_type": "euclid",
    #    "pc_hypre_euclid_level": 5,
    #    "mat_type": "aij",
    #    "ksp_converged_reason": None,
    #    "ksp_atol": 1e-3,
    #    "ksp_rtol": 1e-3,
    #    "snes_atol": 1e-3,
    #    "snes_rtol": 1e-3,
    # }
    solver = NavierStokesBrinkmannSolver(problem,
                                         solver_parameters=solver_parameters)
    solver.solve()
    pvd_file = fd.File("ns_solution.pvd")
    u, p = w_sol.split()
    pvd_file.write(u, p)

    u, p = fd.split(w_sol)

    Vol = fd.assemble(hs(-phi) * fd.Constant(1.0) * dx(0, domain=mesh))
    VControl = fda.Control(Vol)
    Vval = fd.assemble(fd.Constant(0.5) * dx(domain=mesh), annotate=False)
    with stop_annotating():
        print("Initial constraint function value {}".format(Vol))

    J = fd.assemble(
        fd.Constant(brinkmann_penalty) * hs(phi) * inner(u, u) * dx(0) +
        nu / fd.Constant(2.0) * inner(grad(u), grad(u)) * dx)

    c = fda.Control(s)

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

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

    Jhat = LevelSetFunctional(J, c, phi, derivative_cb_pre=deriv_cb)
    Vhat = LevelSetFunctional(Vol, c, phi)

    bcs_vel_1 = fd.DirichletBC(S, noslip, (1, 2, 3, 4))
    bcs_vel = [bcs_vel_1]
    reg_solver = RegularizationSolver(S,
                                      mesh,
                                      beta=0.5,
                                      gamma=1e5,
                                      dx=dx,
                                      bcs=bcs_vel,
                                      design_domain=0)

    tol = 1e-5
    dt = 0.0002
    params = {
        "alphaC": 1.0,
        "debug": 5,
        "alphaJ": 1.0,
        "dt": dt,
        "K": 0.1,
        "maxit": 2000,
        "maxtrials": 5,
        "itnormalisation": 10,
        "tol_merit": 1e-4,  # new merit can be within 5% of the previous merit
        # "normalize_tol" : -1,
        "tol": tol,
    }

    problem = InfDimProblem(
        Jhat,
        reg_solver,
        ineqconstraints=[Constraint(Vhat, Vval, VControl)],
    )
    _ = nullspace_shape(problem, params)
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()[:]))
Exemple #24
0
    - q*f*fd.dx + fd.Constant(pbar)*fd.inner(v, n)*fd.ds(outlet)

# 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:
Exemple #25
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(
Exemple #26
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
G_q = mu_h*fd.inner(Diff*fd.grad(ch) + velocity * ch, n)*fd.ds(outflow) + \
    mu_h*fd.Constant(no_flow)*fd.ds(TOP) + \
    mu_h*fd.Constant(no_flow)*fd.ds(BOTTOM)

# G_q = 0

a = a_u + a_c + F_q
L = L_u + L_c + G_q

# %%
# 4) Solve problem
# solve

# set boundary conditions
bc = fd.DirichletBC(W.sub(2), cIn, inlet)
problem = fd.NonlinearVariationalProblem(a - L, w, bcs=bc)
rtol = 1e-4

# sparse_plt.plot_matrix(a, bcs=bc)
# plt.show()
# sparse_plt.plot_matrix_hybrid_multiplier_spp(a, bcs=bc)
# plt.show()

hybrid_solver_params = {
    "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
Exemple #28
0
F_a = Dt*((r('+') - r('-'))*(vn('+')*c_mid('+') -
                             vn('-')*c_mid('-'))*fd.dS
          - fd.div(u*r)*c_mid*fd.dx
          + fd.conditional(fd.dot(u0, n) < 0, r *
                           fd.dot(u0, n)*cIn, 0.0)*fd.ds
          + fd.conditional(fd.dot(u0, n) > 0, r *
                           fd.dot(u0, n)*c, 0.0)*fd.ds)
# 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")
Exemple #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
Exemple #30
0
    def coarsen(self, fdm, comm):
        # Coarsen the _SNESContext of a DM fdm
        # return the coarse DM cdm of the coarse _SNESContext
        fctx = get_appctx(fdm)
        parent = get_parent(fdm)
        assert parent is not None

        test, trial = fctx.J.arguments()
        fV = test.function_space()
        cele = self.coarsen_element(fV.ufl_element())

        # Have we already done this?
        cctx = fctx._coarse
        if cctx is not None:
            cV = cctx.J.arguments()[0].function_space()
            if (cV.ufl_element() == cele) and (cV.mesh() == fV.mesh()):
                return cV.dm

        cV = firedrake.FunctionSpace(fV.mesh(), cele)
        cdm = cV.dm

        fproblem = fctx._problem
        fu = fproblem.u
        cu = firedrake.Function(cV)

        def coarsen_quadrature(df, Nf, Nc):
            # Coarsen the quadrature degree in a dictionary
            # such that the ratio of quadrature nodes to interpolation nodes (Nq+1)/(Nf+1) is preserved
            if isinstance(df, dict):
                Nq = df.get("quadrature_degree", None)
                if Nq is not None:
                    dc = dict(df)
                    dc["quadrature_degree"] = max(
                        2 * Nc + 1, ((Nq + 1) * (Nc + 1) + Nf) // (Nf + 1) - 1)
                    return dc
            return df

        def coarsen_form(form, Nf, Nc, replace_d):
            # Coarsen a form, by replacing the solution, test and trial functions, and
            # reconstructing each integral with a coarsened quadrature degree.
            # If form is not a Form, then return form.
            return Form([
                f.reconstruct(
                    metadata=coarsen_quadrature(f.metadata(), Nf, Nc))
                for f in replace(form, replace_d).integrals()
            ]) if isinstance(form, Form) else form

        def coarsen_bcs(fbcs):
            cbcs = []
            for bc in fbcs:
                cV_ = cV
                for index in bc._indices:
                    cV_ = cV_.sub(index)
                cbc_value = self.coarsen_bc_value(bc, cV_)
                if type(bc) == firedrake.DirichletBC:
                    cbcs.append(
                        firedrake.DirichletBC(cV_, cbc_value, bc.sub_domain))
                else:
                    raise NotImplementedError(
                        "Unsupported BC type, please get in touch if you need this"
                    )
            return cbcs

        Nf = PMGBase.max_degree(fV.ufl_element())
        Nc = PMGBase.max_degree(cV.ufl_element())

        # Replace dictionary with coarse state, test and trial functions
        replace_d = {
            fu: cu,
            test: firedrake.TestFunction(cV),
            trial: firedrake.TrialFunction(cV)
        }

        cF = coarsen_form(fctx.F, Nf, Nc, replace_d)
        cJ = coarsen_form(fctx.J, Nf, Nc, replace_d)
        cJp = coarsen_form(fctx.Jp, Nf, Nc, replace_d)
        fcp = coarsen_quadrature(fproblem.form_compiler_parameters, Nf, Nc)
        cbcs = coarsen_bcs(fproblem.bcs)

        # Coarsen the appctx: the user might want to provide solution-dependant expressions and forms
        cappctx = dict(fctx.appctx)
        for key in cappctx:
            val = cappctx[key]
            if isinstance(val, dict):
                cappctx[key] = coarsen_quadrature(val, Nf, Nc)
            elif isinstance(val, Expr):
                cappctx[key] = replace(val, replace_d)
            elif isinstance(val, Form):
                cappctx[key] = coarsen_form(val, Nf, Nc, replace_d)

        cmat_type = fctx.mat_type
        cpmat_type = fctx.pmat_type
        if Nc == self.coarse_degree:
            cmat_type = self.coarse_mat_type
            cpmat_type = self.coarse_mat_type
            if fcp is None:
                fcp = dict()
            fcp["mode"] = self.coarse_form_compiler_mode

        # Coarsen the problem and the _SNESContext
        cproblem = firedrake.NonlinearVariationalProblem(
            cF,
            cu,
            bcs=cbcs,
            J=cJ,
            Jp=cJp,
            form_compiler_parameters=fcp,
            is_linear=fproblem.is_linear)

        cctx = type(fctx)(cproblem,
                          cmat_type,
                          cpmat_type,
                          appctx=cappctx,
                          pre_jacobian_callback=fctx._pre_jacobian_callback,
                          pre_function_callback=fctx._pre_function_callback,
                          post_jacobian_callback=fctx._post_jacobian_callback,
                          post_function_callback=fctx._post_function_callback,
                          options_prefix=fctx.options_prefix,
                          transfer_manager=fctx.transfer_manager)

        # FIXME setting up the _fine attribute triggers gmg injection.
        # cctx._fine = fctx
        fctx._coarse = cctx

        add_hook(parent,
                 setup=partial(push_parent, cdm, parent),
                 teardown=partial(pop_parent, cdm, parent),
                 call_setup=True)
        add_hook(parent,
                 setup=partial(push_appctx, cdm, cctx),
                 teardown=partial(pop_appctx, cdm, cctx),
                 call_setup=True)

        cdm.setOptionsPrefix(fdm.getOptionsPrefix())
        cdm.setKSPComputeOperators(_SNESContext.compute_operators)
        cdm.setCreateInterpolation(self.create_interpolation)
        cdm.setCreateInjection(self.create_injection)

        # If we're the coarsest grid of the p-hierarchy, don't
        # overwrite the coarsen routine; this is so that you can
        # use geometric multigrid for the p-coarse problem
        try:
            self.coarsen_element(cele)
            cdm.setCoarsen(self.coarsen)
        except ValueError:
            pass

        # injection of the initial state
        def inject_state(mat):
            with cu.dat.vec_wo as xc, fu.dat.vec_ro as xf:
                mat.multTranspose(xf, xc)

        injection = self.create_injection(cdm, fdm)
        add_hook(parent,
                 setup=partial(inject_state, injection),
                 call_setup=True)

        # restrict the nullspace basis
        def coarsen_nullspace(coarse_V, mat, fine_nullspace):
            if isinstance(fine_nullspace, MixedVectorSpaceBasis):
                if mat.type == 'python':
                    mat = mat.getPythonContext()
                submats = [
                    mat.getNestSubMatrix(i, i) for i in range(len(coarse_V))
                ]
                coarse_bases = []
                for fs, submat, basis in zip(coarse_V, submats,
                                             fine_nullspace._bases):
                    if isinstance(basis, VectorSpaceBasis):
                        coarse_bases.append(
                            coarsen_nullspace(fs, submat, basis))
                    else:
                        coarse_bases.append(coarse_V.sub(basis.index))
                return MixedVectorSpaceBasis(coarse_V, coarse_bases)
            elif isinstance(fine_nullspace, VectorSpaceBasis):
                coarse_vecs = []
                for xf in fine_nullspace._petsc_vecs:
                    wc = firedrake.Function(coarse_V)
                    with wc.dat.vec_wo as xc:
                        mat.multTranspose(xf, xc)
                    coarse_vecs.append(wc)
                vsb = VectorSpaceBasis(coarse_vecs,
                                       constant=fine_nullspace._constant)
                vsb.orthonormalize()
                return vsb
            else:
                return fine_nullspace

        I, _ = self.create_interpolation(cdm, fdm)
        ises = cV._ises
        cctx._nullspace = coarsen_nullspace(cV, I, fctx._nullspace)
        cctx.set_nullspace(cctx._nullspace, ises, transpose=False, near=False)
        cctx._nullspace_T = coarsen_nullspace(cV, I, fctx._nullspace_T)
        cctx.set_nullspace(cctx._nullspace_T, ises, transpose=True, near=False)
        cctx._near_nullspace = coarsen_nullspace(cV, I, fctx._near_nullspace)
        cctx.set_nullspace(cctx._near_nullspace,
                           ises,
                           transpose=False,
                           near=True)
        return cdm