Пример #1
0
 def facet_normal(self, o):
     mesh = coarsen(o.ufl_domain())
     return firedrake.FacetNormal(mesh)
Пример #2
0
def heat_exchanger_optimization(mu=0.03, n_iters=1000):

    output_dir = "2D/"

    path = os.path.abspath(__file__)
    dir_path = os.path.dirname(path)
    mesh = fd.Mesh(f"{dir_path}/2D_mesh.msh")
    # 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)
    phi_expr = sin(y * pi / 0.2) * cos(x * pi / 0.2) - fd.Constant(0.8)
    # 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
    mu = fd.Constant(mu)  # viscosity
    alphamin = 1e-12
    alphamax = 2.5 / (2e-4)
    parameters = {
        "mat_type": "aij",
        "ksp_type": "preonly",
        "ksp_converged_reason": None,
        "pc_type": "lu",
        "pc_factor_mat_solver_type": "mumps",
    }
    stokes_parameters = parameters
    temperature_parameters = parameters
    u_inflow = 2e-3
    tin1 = fd.Constant(10.0)
    tin2 = fd.Constant(100.0)

    P2 = fd.VectorElement("CG", mesh.ufl_cell(), 2)
    P1 = fd.FiniteElement("CG", mesh.ufl_cell(), 1)
    TH = P2 * P1
    W = fd.FunctionSpace(mesh, TH)

    U = fd.TrialFunction(W)
    u, p = fd.split(U)
    V = fd.TestFunction(W)
    v, q = fd.split(V)

    epsilon = fd.Constant(10000.0)

    def hs(phi, epsilon):
        return fd.Constant(alphamax) * fd.Constant(1.0) / (
            fd.Constant(1.0) + exp(-epsilon * phi)) + fd.Constant(alphamin)

    def stokes(phi, BLOCK_INLET_MOUTH, BLOCK_OUTLET_MOUTH):
        a_fluid = mu * inner(grad(u), grad(v)) - div(v) * p - q * div(u)
        darcy_term = inner(u, v)
        return (a_fluid * dx + hs(phi, epsilon) * darcy_term * dx(0) +
                alphamax * darcy_term *
                (dx(BLOCK_INLET_MOUTH) + dx(BLOCK_OUTLET_MOUTH)))

    # Dirichlet boundary conditions
    inflow1 = fd.as_vector([
        u_inflow * sin(
            ((y - (line_sep -
                   (dist_center + inlet_width))) * pi) / inlet_width),
        0.0,
    ])
    inflow2 = fd.as_vector([
        u_inflow * sin(((y - (line_sep + dist_center)) * pi) / inlet_width),
        0.0,
    ])

    noslip = fd.Constant((0.0, 0.0))

    # Stokes 1
    bcs1_1 = fd.DirichletBC(W.sub(0), noslip, WALLS)
    bcs1_2 = fd.DirichletBC(W.sub(0), inflow1, INLET1)
    bcs1_3 = fd.DirichletBC(W.sub(1), fd.Constant(0.0), OUTLET1)
    bcs1_4 = fd.DirichletBC(W.sub(0), noslip, INLET2)
    bcs1_5 = fd.DirichletBC(W.sub(0), noslip, OUTLET2)
    bcs1 = [bcs1_1, bcs1_2, bcs1_3, bcs1_4, bcs1_5]

    # Stokes 2
    bcs2_1 = fd.DirichletBC(W.sub(0), noslip, WALLS)
    bcs2_2 = fd.DirichletBC(W.sub(0), inflow2, INLET2)
    bcs2_3 = fd.DirichletBC(W.sub(1), fd.Constant(0.0), OUTLET2)
    bcs2_4 = fd.DirichletBC(W.sub(0), noslip, INLET1)
    bcs2_5 = fd.DirichletBC(W.sub(0), noslip, OUTLET1)
    bcs2 = [bcs2_1, bcs2_2, bcs2_3, bcs2_4, bcs2_5]

    # Forward problems
    U1, U2 = fd.Function(W), fd.Function(W)
    L = inner(fd.Constant((0.0, 0.0, 0.0)), V) * dx
    problem = fd.LinearVariationalProblem(stokes(-phi, INMOUTH2, OUTMOUTH2),
                                          L,
                                          U1,
                                          bcs=bcs1)
    solver_stokes1 = fd.LinearVariationalSolver(
        problem,
        solver_parameters=stokes_parameters,
        options_prefix="stokes_1")
    solver_stokes1.solve()
    problem = fd.LinearVariationalProblem(stokes(phi, INMOUTH1, OUTMOUTH1),
                                          L,
                                          U2,
                                          bcs=bcs2)
    solver_stokes2 = fd.LinearVariationalSolver(
        problem,
        solver_parameters=stokes_parameters,
        options_prefix="stokes_2")
    solver_stokes2.solve()

    # Convection difussion equation
    ks = fd.Constant(1e0)
    cp_value = 5.0e5
    cp = fd.Constant(cp_value)
    T = fd.FunctionSpace(mesh, "DG", 1)
    t = fd.Function(T, name="Temperature")
    w = fd.TestFunction(T)

    # Mesh-related functions
    n = fd.FacetNormal(mesh)
    h = fd.CellDiameter(mesh)
    u1, p1 = fd.split(U1)
    u2, p2 = fd.split(U2)

    def upwind(u):
        return (dot(u, n) + abs(dot(u, n))) / 2.0

    u1n = upwind(u1)
    u2n = upwind(u2)

    # Penalty term
    alpha = fd.Constant(500.0)
    # Bilinear form
    a_int = dot(grad(w), ks * grad(t) - cp * (u1 + u2) * t) * dx

    a_fac = (fd.Constant(-1.0) * ks * dot(avg(grad(w)), jump(t, n)) * dS +
             fd.Constant(-1.0) * ks * dot(jump(w, n), avg(grad(t))) * dS +
             ks("+") *
             (alpha("+") / avg(h)) * dot(jump(w, n), jump(t, n)) * dS)

    a_vel = (dot(
        jump(w),
        cp * (u1n("+") + u2n("+")) * t("+") - cp *
        (u1n("-") + u2n("-")) * t("-"),
    ) * dS + dot(w,
                 cp * (u1n + u2n) * t) * ds)

    a_bnd = (dot(w,
                 cp * dot(u1 + u2, n) * t) * (ds(INLET1) + ds(INLET2)) +
             w * t * (ds(INLET1) + ds(INLET2)) - w * tin1 * ds(INLET1) -
             w * tin2 * ds(INLET2) + alpha / h * ks * w * t *
             (ds(INLET1) + ds(INLET2)) - ks * dot(grad(w), t * n) *
             (ds(INLET1) + ds(INLET2)) - ks * dot(grad(t), w * n) *
             (ds(INLET1) + ds(INLET2)))

    aT = a_int + a_fac + a_vel + a_bnd

    LT_bnd = (alpha / h * ks * tin1 * w * ds(INLET1) +
              alpha / h * ks * tin2 * w * ds(INLET2) -
              tin1 * ks * dot(grad(w), n) * ds(INLET1) -
              tin2 * ks * dot(grad(w), n) * ds(INLET2))

    problem = fd.LinearVariationalProblem(derivative(aT, t), LT_bnd, t)
    solver_temp = fd.LinearVariationalSolver(
        problem,
        solver_parameters=temperature_parameters,
        options_prefix="temperature",
    )
    solver_temp.solve()
    # fd.solve(eT == 0, t, solver_parameters=temperature_parameters)

    # Cost function: Flux at the cold outlet
    scale_factor = 4e-4
    Jform = fd.assemble(
        fd.Constant(-scale_factor * cp_value) * inner(t * u1, n) * ds(OUTLET1))
    # Constraints: Pressure drop on each fluid
    power_drop = 1e-2
    Power1 = fd.assemble(p1 / power_drop * ds(INLET1))
    Power2 = fd.assemble(p2 / power_drop * ds(INLET2))

    phi_pvd = fd.File("phi_evolution.pvd")

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

    c = fda.Control(s)

    # Reduced Functionals
    Jhat = LevelSetFunctional(Jform, c, phi, derivative_cb_pre=deriv_cb)
    P1hat = LevelSetFunctional(Power1, c, phi)
    P1control = fda.Control(Power1)

    P2hat = LevelSetFunctional(Power2, c, phi)
    P2control = fda.Control(Power2)

    Jhat_v = Jhat(phi)
    print("Initial cost function value {:.5f}".format(Jhat_v), flush=True)
    print("Power drop 1 {:.5f}".format(Power1), flush=True)
    print("Power drop 2 {:.5f}".format(Power2), flush=True)

    beta_param = 0.08
    # Regularize the shape derivatives only in the domain marked with 0
    reg_solver = RegularizationSolver(S,
                                      mesh,
                                      beta=beta_param,
                                      gamma=1e5,
                                      dx=dx,
                                      design_domain=0)

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

    solver_parameters = {
        "reinit_solver": {
            "h_factor": 2.0,
        }
    }
    # Optimization problem
    problem = InfDimProblem(
        Jhat,
        reg_solver,
        ineqconstraints=[
            Constraint(P1hat, 1.0, P1control),
            Constraint(P2hat, 1.0, P2control),
        ],
        solver_parameters=solver_parameters,
    )
    results = nlspace_solve(problem, params)

    return results
Пример #3
0
def facet_normal_2(mesh):
    r"""Compute the horizontal component of the unit outward normal vector
    to a mesh"""
    ν = firedrake.FacetNormal(mesh)
    return firedrake.as_vector((ν[0], ν[1]))
Пример #4
0
    j = np.floor(y / (Ly / (ny * n))).astype(int)
    return kl[i, j]


Kinv.dat.data[:, 0, 0] = 1 / \
    fix_perm_map(ccenter.dat.data[:, 0], ccenter.dat.data[:, 1])
Kinv.dat.data[:, 1, 1] = 1 / \
    fix_perm_map(ccenter.dat.data[:, 0], ccenter.dat.data[:, 1])

# -------
# 3.4) Variational Form
# the bilinear and linear forms of the variational problem are defined as: ::
a = fd.dot(v, Kinv * u) * fd.dx - fd.div(v) * p * fd.dx + q * fd.div(u) * fd.dx

f = fd.Constant(0.0)
n = fd.FacetNormal(mesh)
L = q * f * fd.dx - fd.Constant(pbar) * fd.inner(v, n) * fd.ds(outlet)

# ----
# 3.5) set boundary conditions
# The strongly enforced boundary conditions on the BDM space on the top and
# bottom of the domain are declared as: ::
bc0 = fd.DirichletBC(W.sub(0), fd.Constant(qbar), inlet)
bc1 = fd.DirichletBC(W.sub(0), fd.Constant(q0bar), noflow)

# ----
# 4) Define and solve the problem
#
# Now we're ready to solve the variational problem. We define `w` to be a
# function to hold the solution on the mixed space.
w = fd.Function(W)
Пример #5
0
    def cgls_form(self, problem, mesh, bcs_p):
        rho = problem.rho
        mu = problem.mu
        k = problem.k
        f = problem.f

        q, p = fire.TrialFunctions(self._W)
        w, v = fire.TestFunctions(self._W)

        n = fire.FacetNormal(mesh)

        # Stabilizing parameters
        h = fire.CellDiameter(mesh)
        has_mesh_characteristic_length = True
        delta_0 = fire.Constant(1)
        delta_1 = fire.Constant(-1 / 2)
        delta_2 = fire.Constant(1 / 2)
        delta_3 = fire.Constant(1 / 2)

        # Some good stabilizing methods that I use:
        # 1) CLGS (Correa and Loula method, it's a Galerkin Least-Squares residual formulation):
        #   * delta_0 = 1
        #   * delta_1 = -1/2
        #   * delta_2 = 1/2
        #   * delta_3 = 1/2
        # 2) CLGS (Div):
        #   * delta_0 = 1
        #   * delta_1 = -1/2
        #   * delta_2 = 1/2
        #   * delta_3 = 0
        # 3) Original Hughes's adjoint (variational multiscale) method (HVM):
        #   * delta_0 = -1
        #   * delta_1 = 1/2
        #   * delta_2 = 0
        #   * delta_3 = 0
        # 4) HVM (Div):
        #   * delta_0 = -1
        #   * delta_1 = 1/2
        #   * delta_2 = 1/2
        #   * delta_3 = 0
        # 5) Enhanced HVM (eHVM, this one is proposed by me. It was never published before):
        #   * delta_0 = -1
        #   * delta_1 = 1/2
        #   * delta_2 = 1/2
        #   * delta_3 = 1/2

        # I'm currently investigating these modifications in my thesis. They work good for DG methods.
        if has_mesh_characteristic_length:
            delta_2 = delta_2 * h * h
            delta_3 = delta_3 * h * h

        kappa = rho * k / mu
        inv_kappa = 1.0 / kappa

        # Classical mixed terms
        a = (dot(inv_kappa * q, w) - div(w) * p - delta_0 * v * div(q)) * dx
        L = -delta_0 * f * v * dx

        # Add the contributions of the pressure boundary conditions to L
        for pboundary, iboundary in bcs_p:
            L -= pboundary * dot(w, n) * ds(iboundary)

        # Stabilizing terms
        a += (delta_1 * inner(kappa * (inv_kappa * q + grad(p)),
                              delta_0 * inv_kappa * w + grad(v)) * dx)
        a += delta_2 * inv_kappa * div(q) * div(w) * dx
        a += delta_3 * inner(kappa * curl(inv_kappa * q), curl(
            inv_kappa * w)) * dx
        L += delta_2 * inv_kappa * f * div(w) * dx

        return a, L
Пример #6
0
    def sdhm_form(self, problem, mesh, bcs_p, bcs_u):
        rho = problem.rho
        mu = problem.mu
        k = problem.k
        f = problem.f

        q, p, lambda_h = fire.split(self.solution)
        w, v, mu_h = fire.TestFunctions(self._W)

        n = fire.FacetNormal(mesh)
        h = fire.CellDiameter(mesh)

        # Stabilizing parameters
        has_mesh_characteristic_length = True
        beta_0 = fire.Constant(1e-15)
        delta_0 = fire.Constant(1)
        delta_1 = fire.Constant(-1 / 2)
        delta_2 = fire.Constant(1 / 2)
        delta_3 = fire.Constant(1 / 2)

        # h_avg = (h('+') + h('-')) / 2.
        beta = beta_0 / h
        beta_avg = beta_0 / h("+")
        if has_mesh_characteristic_length:
            delta_2 = delta_2 * h * h
            delta_3 = delta_3 * h * h

        kappa = rho * k / mu
        inv_kappa = 1.0 / kappa

        # Classical mixed terms
        a = (dot(inv_kappa * q, w) - div(w) * p - delta_0 * v * div(q)) * dx
        L = -delta_0 * f * v * dx

        # Hybridization terms
        a += lambda_h("+") * dot(w, n)("+") * dS + mu_h("+") * dot(q,
                                                                   n)("+") * dS
        a += beta_avg * kappa("+") * (lambda_h("+") - p("+")) * (mu_h("+") -
                                                                 v("+")) * dS

        # Add the contributions of the pressure boundary conditions to L
        primal_bc_markers = list(mesh.exterior_facets.unique_markers)
        for pboundary, iboundary in bcs_p:
            primal_bc_markers.remove(iboundary)
            a += (pboundary * dot(w, n) + mu_h * dot(q, n)) * ds(iboundary)
            a += beta * kappa * (lambda_h - pboundary) * mu_h * ds(iboundary)

        unprescribed_primal_bc = primal_bc_markers
        for bc_marker in unprescribed_primal_bc:
            a += (lambda_h * dot(w, n) + mu_h * dot(q, n)) * ds(bc_marker)
            a += beta * kappa * lambda_h * mu_h * ds(bc_marker)

        # Add the (weak) contributions of the velocity boundary conditions to L
        for uboundary, iboundary, component in bcs_u:
            if component is not None:
                dim = mesh.geometric_dimension()
                bc_array = []
                for _ in range(dim):
                    bc_array.append(0.0)
                bc_array[component] = uboundary
                bc_as_vector = fire.Constant(bc_array)
                L += mu_h * dot(bc_as_vector, n) * ds(iboundary)
            else:
                L += mu_h * dot(uboundary, n) * ds(iboundary)

        # Stabilizing terms
        a += (delta_1 * inner(kappa * (inv_kappa * q + grad(p)),
                              delta_0 * inv_kappa * w + grad(v)) * dx)
        a += delta_2 * inv_kappa * div(q) * div(w) * dx
        a += delta_3 * inner(kappa * curl(inv_kappa * q), curl(
            inv_kappa * w)) * dx
        L += delta_2 * inv_kappa * f * div(w) * dx

        return a, L
Пример #7
0
 def facet_normal(self, o):
     mesh = o.ufl_domain()
     hierarchy, level = utils.get_level(mesh)
     new_mesh = hierarchy[level - 1]
     return firedrake.FacetNormal(new_mesh.ufl_domain())
Пример #8
0
def nearby_preconditioning_piecewise_experiment_set(
        A_pre_type,n_pre_type,dim,num_pieces,seed,num_repeats,
        k_list,h_list,p_list,noise_master_level_list,noise_modifier_list,
        save_location):
    """Test nearby preconditioning for a range of parameter values.

    Performs nearby preconditioning tests for a range of values of k,
    the mesh size h, and the size of the random noise (which can be
    specified in terms of k and h). The random noise is piecewise
    constant on a grid unrelated to the finite-element mesh.

    Parameters:

    A_pre_type - string - options are 'constant', giving A_pre =
    [[1.0,0.0],[0.0,1.0]].

    n_pre_type - string - options are 'constant', giving n_pre = 1.0;
    'jump_down' giving n_pre = 2/3 on a central square of side length
    1/3, and 1 otherwise; and 'jump_up' giving n_pre = 1.5 on a central
    square of side length 1/3, and 1 otherwise.

    dim - 2 or 3, the dimension of the problem.

    num_pieces - see
        helmholtz.coefficients.PieceWiseConstantCoeffGenerator.

    seed - see StochasticHelmholtzProblem.

    num_repeats - see nearby_preconditioning_test.

    k_list - list of positive floats - the values of k for which we will
    run experiments.

    h_list - list of 2-tuples; in each tuple (call it t) t[0] should be
    a positive float and t[1] should be a float. These specify the
    values of the mesh size h for which we will run experiments. h =
    t[0] * k**t[1].

    p_list - list of positive ints, the polynomial degrees to run
    experiments for. Degree >= 5 will be very slow because of the
    implementation in Firedrake.

    noise_master_level_list - list of 2-tuples, where each entry of the
    tuple is a positive float.  This defines the values of base_noise_A
    and base_noise_n to be used in the experiments. Call a given tuple
    t. Then base_noise_A = t[0] and base_noise_n = t[1].

    noise_modifier_list - list of 4-tuples; the entries of each tuple
    should be floats. Call a given tuple t. This modifies the base noise
    so that the L^\infty norms of A and n are less than or equal to
    (respectively) base_noise_A * h**t[0] * k**t[1] and base_noise_n *
    h**t[2] * k**t[3].

    save_location - see utils.write_repeats_to_csv.

    """

    if not(isinstance(A_pre_type,str)):
        raise TypeError("Input A_pre_type should be a string")
    elif A_pre_type is not "constant":
        raise HelmholtzNotImplementedError(
            "Currently only implemented A_pre_type = 'constant'.")

    if not(isinstance(n_pre_type,str)):
        raise TypeError("Input n_pre_type should be a string")

    if not(isinstance(k_list,list)):
        raise TypeError("Input k_list should be a list.")
    elif any(not(isinstance(k,float)) for k in k_list):
        raise TypeError("Input k_list should be a list of floats.")
    elif any(k <= 0 for k in k_list):
        raise TypeError(
            "Input k_list should be a list of positive floats.")

    if not(isinstance(h_list,list)):
        raise TypeError("Input h_list should be a list.")
    elif any(not(isinstance(h_tuple,tuple)) for h_tuple in h_list):
        raise TypeError("Input h_list should be a list of tuples.")
    elif any(len(h_tuple) is not 2 for h_tuple in h_list):
        raise TypeError("Input h_list should be a list of 2-tuples.")
    elif any(not(isinstance(h_tuple[0],float)) for h_tuple in h_list)\
             or any(h_tuple[0] <= 0 for h_tuple in h_list):
        raise TypeError(
            "The first item of every tuple in h_list\
            should be a positive float.")
    elif any(not(isinstance(h_tuple[1],float)) for h_tuple in h_list):
        raise TypeError(
            "The second item of every tuple in h_list should be a float.")

    if not(isinstance(noise_master_level_list,list)):
        raise TypeError(
            "Input noise_master_level_list should be a list.")
    elif any(not(isinstance(noise_tuple,tuple))
             for noise_tuple in noise_master_level_list):
        raise TypeError(
            "Input noise_master_level_list should be a list of tuples.")
    elif any(len(noise_tuple) is not 2
             for noise_tuple in noise_master_level_list):
        raise TypeError(
            "Input noise_master_level_list should be a list of 2-tuples.")
    elif any(any(not(isinstance(noise_tuple[i],float))
                 for i in range(len(noise_tuple)))
             for noise_tuple in noise_master_level_list):
        raise TypeError(
            "Input noise_master_level_list\
            should be a list of 2-tuples of floats.")

    if not(isinstance(noise_modifier_list,list)):
        raise TypeError("Input noise_modifier_list should be a list.")
    elif any(not(isinstance(mod_tuple,tuple))
             for mod_tuple in noise_modifier_list):
        raise TypeError(
            "Input noise_modifier_list should be a list of tuples.")
    elif any(len(mod_tuple) is not 4 for mod_tuple in noise_modifier_list):
        raise TypeError(
            "Input noise_modifier_list should be a list of 4-tuples.")
    elif any(any(not(isinstance(mod_tuple[i],float))
                 for i in range(len(mod_tuple)))
             for mod_tuple in noise_modifier_list):
        raise TypeError(
            "Input noise_modifier_list\
            should be a list of 4-tuples of floats.")


    
    for k in k_list:
        for h_tuple in h_list:
            for p in p_list:
                h = h_tuple[0] * k**h_tuple[1]
                mesh_points = hh_utils.h_to_num_cells(h,dim)
                mesh = fd.UnitSquareMesh(mesh_points,mesh_points)
                V = fd.FunctionSpace(mesh, "CG", p)
                f = 0.0
                d = fd.as_vector([1.0/fd.sqrt(2.0),1.0/fd.sqrt(2.0)])
                x = fd.SpatialCoordinate(mesh)
                nu = fd.FacetNormal(mesh)
                g=1j*k*fd.exp(1j*k*fd.dot(x,d))*(fd.dot(d,nu)-1)

                if A_pre_type is "constant":
                    A_pre = fd.as_matrix([[1.0,0.0],[0.0,1.0]])

                if n_pre_type is "constant":
                    n_pre = 1.0

                elif n_pre_type is "jump_down":
                    n_pre = (2.0/3.0)\
                            + hh_utils.nd_indicator(
                                x,1.0/3.0,
                                np.array([[1.0/3.0,2.0/3.0],
                                          [1.0/3.0,2.0/3.0],
                                          [1.0/3.0,2.0/3.0]]
                                )
                            )

                elif n_pre_type is "jump_up":
                    n_pre = 1.5\
                            + hh_utils.nd_indicator(
                                x,-1.0/2.0,
                                np.array([[1.0/3.0,2.0/3.0],
                                          [1.0/3.0,2.0/3.0],
                                          [1.0/3.0,2.0/3.0]]
                                )
                            )


                for noise_master in noise_master_level_list:
                    A_noise_master = noise_master[0]
                    n_noise_master = noise_master[1]

                    for modifier in noise_modifier_list:
                        if fd.COMM_WORLD.rank == 0:
                            print(k,h_tuple,noise_master,modifier)

                        A_modifier = h ** modifier[0] * k**modifier[1]
                        n_modifier = h ** modifier[2] * k**modifier[3]
                        A_noise_level = A_noise_master * A_modifier
                        n_noise_level = n_noise_master * n_modifier

                        A_stoch = coeff.PiecewiseConstantCoeffGenerator(
                            mesh,num_pieces,A_noise_level,A_pre,[2,2])
                        n_stoch = coeff.PiecewiseConstantCoeffGenerator(
                            mesh,num_pieces,n_noise_level,n_pre,[1])
                        np.random.seed(seed)

                        GMRES_its = nearby_preconditioning_experiment(
                            V,k,A_pre,A_stoch,n_pre,n_stoch,f,g,num_repeats)

                        if fd.COMM_WORLD.rank == 0:
                            hh_utils.write_GMRES_its(
                                GMRES_its,save_location,
                                {'k' : k,
                                 'h_tuple' : h_tuple,
                                 'p' : p,
                                 'num_pieces' : num_pieces,
                                 'A_pre_type' : A_pre_type,
                                 'n_pre_type' : n_pre_type,
                                 'noise_master' : noise_master,
                                 'modifier' : modifier,
                                 'num_repeats' : num_repeats
                                 }
                                )
Пример #9
0
def _wall_flux(z, g, boundary_ids):
    n = firedrake.FacetNormal(z.ufl_domain())
    h, q = firedrake.split(z)
    # Mirror value of the fluid momentum
    q_ex = q - 2 * inner(q, n) * n
    return _boundary_flux(z, h, q_ex, g, boundary_ids)
Пример #10
0
    def solve(self, dt, D0, u, A, D_inflow=None, **kwargs):
        r"""Propogate the damage forward by one timestep

        This function uses a Runge-Kutta scheme to upwind damage
        (limiting damage diffusion) while sourcing and sinking
        damage assocaited with crevasse opening/crevasse healing

        Parameters
        ----------
        dt : float
            Timestep
        D0 : firedrake.Function
            initial damage feild should be discontinuous
        u : firedrake.Function
            Ice velocity
        A : firedrake.Function
            fluidity parameter
        D_inflow : firedrake.Function
            Damage of the upstream ice that advects into the domain

        Returns
        -------
        D : firedrake.Function
            Ice damage at `t + dt`
        """

        D_inflow = D_inflow if D_inflow is not None else D0
        Q = D0.function_space()
        dD, φ = firedrake.TrialFunction(Q), firedrake.TestFunction(Q)
        d = φ * dD * dx
        D = D0.copy(deepcopy=True)

        n = firedrake.FacetNormal(Q.mesh())

        un = 0.5 * (inner(u, n) + abs(inner(u, n)))
        L1 = dt * (D * div(φ * u) * dx - φ * max_value(inner(u, n), 0) * D * ds
                   - φ * min_value(inner(u, n), 0) * D_inflow * ds -
                   (φ('+') - φ('-')) *
                   (un('+') * D('+') - un('-') * D('-')) * dS)
        D1 = firedrake.Function(Q)
        D2 = firedrake.Function(Q)
        L2 = firedrake.replace(L1, {D: D1})
        L3 = firedrake.replace(L1, {D: D2})

        dq = firedrake.Function(Q)

        # Three-stage strong structure-preserving Runge Kutta (SSPRK3) method
        params = {
            'ksp_type': 'preonly',
            'pc_type': 'bjacobi',
            'sub_pc_type': 'ilu'
        }
        prob1 = firedrake.LinearVariationalProblem(d, L1, dq)
        solv1 = firedrake.LinearVariationalSolver(prob1,
                                                  solver_parameters=params)
        prob2 = firedrake.LinearVariationalProblem(d, L2, dq)
        solv2 = firedrake.LinearVariationalSolver(prob2,
                                                  solver_parameters=params)
        prob3 = firedrake.LinearVariationalProblem(d, L3, dq)
        solv3 = firedrake.LinearVariationalSolver(prob3,
                                                  solver_parameters=params)

        solv1.solve()
        D1.assign(D + dq)
        solv2.solve()
        D2.assign(0.75 * D + 0.25 * (D1 + dq))
        solv3.solve()
        D.assign((1.0 / 3.0) * D + (2.0 / 3.0) * (D2 + dq))

        # Increase/decrease damage depending on stress and strain rates
        ε = sym(grad(u))
        ε_1 = eigenvalues(ε)[0]

        σ = M(ε, A)
        σ_e = sqrt(inner(σ, σ) - det(σ))

        ε_h = firedrake.Constant(self.healing_strain_rate)
        σ_d = firedrake.Constant(self.damage_stress)
        γ_h = firedrake.Constant(self.healing_rate)
        γ_d = firedrake.Constant(self.damage_rate)

        healing = γ_h * min_value(ε_1 - ε_h, 0)
        fracture = γ_d * conditional(σ_e - σ_d > 0, ε_1, 0.) * (1 - D)

        # Clamp damage field to [0, 1]
        D.project(min_value(max_value(D + dt * (healing + fracture), 0), 1))
        return D
Пример #11
0
def heat_flux(w_sol, t, OUTLET):
    u_sol, _ = fd.split(w_sol)
    scale_factor = 5.0
    n = fd.FacetNormal(w_sol.ufl_domain())
    return fd.assemble(
        fd.Constant(-scale_factor) * inner(t * u_sol, n) * ds(OUTLET))