コード例 #1
0
def test_2D_cartesian_recovery(geometry, element, mesh, expr):

    family = "RTCF" if element == "quadrilateral" else "BDM"

    # horizontal base spaces
    cell = mesh.ufl_cell().cellname()

    # DG1
    DG1_elt = FiniteElement("DG", cell, 1, variant="equispaced")
    DG1 = FunctionSpace(mesh, DG1_elt)
    vec_DG1 = VectorFunctionSpace(mesh, DG1_elt)

    # spaces
    DG0 = FunctionSpace(mesh, "DG", 0)
    CG1 = FunctionSpace(mesh, "CG", 1)
    Vu = FunctionSpace(mesh, family, 1)
    vec_CG1 = VectorFunctionSpace(mesh, "CG", 1)

    # our actual theta and rho and v
    rho_CG1_true = Function(CG1).interpolate(expr)
    v_CG1_true = Function(vec_CG1).interpolate(as_vector([expr, expr]))

    # make the initial fields by projecting expressions into the lowest order spaces
    rho_DG0 = Function(DG0).interpolate(expr)
    rho_CG1 = Function(CG1)
    v_Vu = Function(Vu).project(as_vector([expr, expr]))
    v_CG1 = Function(vec_CG1)

    # make the recoverers and do the recovery
    rho_recoverer = Recoverer(rho_DG0,
                              rho_CG1,
                              VDG=DG1,
                              boundary_method=Boundary_Method.dynamics)
    v_recoverer = Recoverer(v_Vu,
                            v_CG1,
                            VDG=vec_DG1,
                            boundary_method=Boundary_Method.dynamics)

    rho_recoverer.project()
    v_recoverer.project()

    rho_diff = errornorm(rho_CG1, rho_CG1_true) / norm(rho_CG1_true)
    v_diff = errornorm(v_CG1, v_CG1_true) / norm(v_CG1_true)

    tolerance = 1e-7
    error_message = ("""
                     Incorrect recovery for {variable} with {boundary} boundary method
                     on {geometry} 2D Cartesian plane with {element} elements
                     """)
    assert rho_diff < tolerance, error_message.format(variable='rho',
                                                      boundary='dynamics',
                                                      geometry=geometry,
                                                      element=element)
    assert v_diff < tolerance, error_message.format(variable='v',
                                                    boundary='dynamics',
                                                    geometry=geometry,
                                                    element=element)
コード例 #2
0
def setup_2d_recovery(dirname):

    L = 100.
    W = 100.

    deltax = L / 5.
    deltay = W / 5.
    ncolumnsx = int(L / deltax)
    ncolumnsy = int(W / deltay)

    mesh = PeriodicRectangleMesh(ncolumnsx,
                                 ncolumnsy,
                                 L,
                                 W,
                                 direction='y',
                                 quadrilateral=True)
    x, y = SpatialCoordinate(mesh)

    # spaces
    VDG0 = FunctionSpace(mesh, "DG", 0)
    VCG1 = FunctionSpace(mesh, "CG", 1)
    VDG1 = FunctionSpace(mesh, "DG", 1)
    Vu = FunctionSpace(mesh, "RTCF", 1)
    VuCG1 = VectorFunctionSpace(mesh, "CG", 1)
    VuDG1 = VectorFunctionSpace(mesh, "DG", 1)

    # set up initial conditions
    np.random.seed(0)
    expr = np.random.randn() + np.random.randn() * x

    # our actual theta and rho and v
    rho_CG1_true = Function(VCG1).interpolate(expr)
    v_CG1_true = Function(VuCG1).interpolate(as_vector([expr, expr]))

    # make the initial fields by projecting expressions into the lowest order spaces
    rho_DG0 = Function(VDG0).interpolate(expr)
    rho_CG1 = Function(VCG1)
    v_Vu = Function(Vu).project(as_vector([expr, expr]))
    v_CG1 = Function(VuCG1)

    # make the recoverers and do the recovery
    rho_recoverer = Recoverer(rho_DG0,
                              rho_CG1,
                              VDG=VDG1,
                              boundary_method=Boundary_Method.dynamics)
    v_recoverer = Recoverer(v_Vu,
                            v_CG1,
                            VDG=VuDG1,
                            boundary_method=Boundary_Method.dynamics)

    rho_recoverer.project()
    v_recoverer.project()

    rho_diff = errornorm(rho_CG1, rho_CG1_true) / norm(rho_CG1_true)
    v_diff = errornorm(v_CG1, v_CG1_true) / norm(v_CG1_true)

    return (rho_diff, v_diff)
コード例 #3
0
def test_scalar_diffusion(tmpdir, DG, tracer_setup):

    setup = tracer_setup(tmpdir, geometry="slice", blob=True)
    state = setup.state
    f_init = setup.f_init
    tmax = setup.tmax
    tol = 5.e-2
    kappa = 1.

    f_end_expr = (1 / (1 + 4 * tmax)) * f_init**(1 / (1 + 4 * tmax))

    if DG:
        V = state.spaces("DG", "DG", 1)
    else:
        V = state.spaces("theta", degree=1)

    mu = 5.

    diffusion_params = DiffusionParameters(kappa=kappa, mu=mu)
    eqn = DiffusionEquation(state,
                            V,
                            "f",
                            diffusion_parameters=diffusion_params)

    diffusion_scheme = [(eqn, BackwardEuler(state))]

    state.fields("f").interpolate(f_init)
    f_end = run(state, diffusion_scheme, tmax)
    assert errornorm(f_end_expr, f_end) < tol
コード例 #4
0
ファイル: test_recovery_1d.py プロジェクト: dorugeber/gusto
def test_1D_recovery(geometry, mesh, expr):

    # horizontal base spaces
    cell = mesh.ufl_cell().cellname()

    # DG1
    DG1_elt = FiniteElement("DG", cell, 1, variant="equispaced")
    DG1 = FunctionSpace(mesh, DG1_elt)

    # spaces
    DG0 = FunctionSpace(mesh, "DG", 0)
    CG1 = FunctionSpace(mesh, "CG", 1)

    # our actual theta and rho and v
    rho_CG1_true = Function(CG1).interpolate(expr)

    # make the initial fields by projecting expressions into the lowest order spaces
    rho_DG0 = Function(DG0).interpolate(expr)
    rho_CG1 = Function(CG1)

    # make the recoverers and do the recovery
    rho_recoverer = Recoverer(rho_DG0, rho_CG1, VDG=DG1, boundary_method=Boundary_Method.dynamics)

    rho_recoverer.project()

    rho_diff = errornorm(rho_CG1, rho_CG1_true) / norm(rho_CG1_true)

    tolerance = 1e-7
    error_message = ("""
                     Incorrect recovery for {variable} with {boundary} boundary method
                     on {geometry} 1D domain
                     """)
    assert rho_diff < tolerance, error_message.format(variable='rho', boundary='dynamics', geometry=geometry)
コード例 #5
0
def heat(n, deg, time_stages, stage_type="deriv", splitting=IA):
    N = 2**n
    msh = UnitIntervalMesh(N)

    params = {
        "snes_type": "ksponly",
        "ksp_type": "preonly",
        "mat_type": "aij",
        "pc_type": "lu"
    }

    V = FunctionSpace(msh, "CG", deg)
    x, = SpatialCoordinate(msh)

    t = Constant(0.0)
    dt = Constant(2.0 / N)

    uexact = exp(-t) * sin(pi * x)
    rhs = expand_derivatives(diff(uexact, t)) - div(grad(uexact))

    butcher_tableau = GaussLegendre(time_stages)

    u = project(uexact, V)

    v = TestFunction(V)

    F = (inner(Dt(u), v) * dx + inner(grad(u), grad(v)) * dx -
         inner(rhs, v) * dx)

    bc = DirichletBC(V, Constant(0), "on_boundary")

    stepper = TimeStepper(F,
                          butcher_tableau,
                          t,
                          dt,
                          u,
                          bcs=bc,
                          solver_parameters=params,
                          stage_type=stage_type,
                          splitting=splitting)

    while (float(t) < 1.0):
        if (float(t) + float(dt) > 1.0):
            dt.assign(1.0 - float(t))
        stepper.advance()
        t.assign(float(t) + float(dt))

    return errornorm(uexact, u) / norm(uexact)
コード例 #6
0
ファイル: test_navier_stokes.py プロジェクト: LLNL/lestofire
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
コード例 #7
0
ファイル: test_navier_stokes.py プロジェクト: LLNL/lestofire
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
コード例 #8
0
def test_cone_cg_2D():
    mesh = fd.UnitSquareMesh(100, 100)
    V = fd.FunctionSpace(mesh, "CG", 1)

    radius = 0.2
    x, y = fd.SpatialCoordinate(mesh)
    x_shift = 0.5
    phi_init = ((x - x_shift) * (x - x_shift) + (y - 0.5) * (y - 0.5) -
                radius**2)
    phi0 = fd.Function(V).interpolate(phi_init)

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

    reinit_solver = ReinitSolverCG(V)
    phin = reinit_solver.solve(phi0, iters=10)
    phi_pvd.write(phin)

    phi_solution = fd.interpolate(
        sqrt((x - x_shift) * (x - x_shift) + (y - 0.5) * (y - 0.5)) - radius,
        V,
    )
    error_numeri = fd.errornorm(phin, phi_solution)
    print(f"error: {error_numeri}")
    assert error_numeri < 1e-4
コード例 #9
0
def test_vector_diffusion(tmpdir, DG, tracer_setup):

    setup = tracer_setup(tmpdir, geometry="slice", blob=True)
    state = setup.state
    f_init = setup.f_init
    tmax = setup.tmax
    tol = 3.e-2
    kappa = 1.

    f_end_expr = (1 / (1 + 4 * tmax)) * f_init**(1 / (1 + 4 * tmax))

    kappa = Constant([[kappa, 0.], [0., kappa]])
    if DG:
        V = VectorFunctionSpace(state.mesh, "DG", 1)
    else:
        V = state.spaces("HDiv", "CG", 1)
    f_init = as_vector([f_init, 0.])
    f_end_expr = as_vector([f_end_expr, 0.])

    mu = 5.

    diffusion_params = DiffusionParameters(kappa=kappa, mu=mu)
    eqn = DiffusionEquation(state,
                            V,
                            "f",
                            diffusion_parameters=diffusion_params)

    if DG:
        state.fields("f").interpolate(f_init)
    else:
        state.fields("f").project(f_init)

    diffusion_scheme = [(eqn, BackwardEuler(state))]

    f_end = run(state, diffusion_scheme, tmax)
    assert errornorm(f_end_expr, f_end) < tol
コード例 #10
0
    'friction': 'manning',

    # I/O
    'plot_bathymetry': True,
    'plot_pvd': True,
    'input_dir': inputdir,
    'output_dir': outputdir,
}

op = BeachOptions(**kwargs)
if os.getenv('REGRESSION_TEST') is not None:
    op.end_time = op.dt * op.dt_per_export
swp = AdaptiveProblem(op)

t1 = time.time()
swp.solve_forward()
t2 = time.time()
if os.getenv('REGRESSION_TEST') is not None:
    sys.exit(0)

print(t2 - t1)

new_mesh = RectangleMesh(880, 20, 220, 10)

bath = Function(FunctionSpace(new_mesh, "CG",
                              1)).project(swp.fwd_solutions_bathymetry[0])
bath_real = initialise_bathymetry(new_mesh, 'hydrodynamics_beach_bath_new_880')

print('L2')
print(fire.errornorm(bath, bath_real))
コード例 #11
0
def setup_3d_recovery(dirname):

    L = 100.
    H = 10.
    W = 1.

    deltax = L / 5.
    deltay = W / 5.
    deltaz = H / 5.
    nlayers = int(H / deltaz)
    ncolumnsx = int(L / deltax)
    ncolumnsy = int(W / deltay)

    m = RectangleMesh(ncolumnsx, ncolumnsy, L, W, quadrilateral=True)
    mesh = ExtrudedMesh(m, layers=nlayers, layer_height=H / nlayers)
    x, y, z = SpatialCoordinate(mesh)

    # horizontal base spaces
    cell = mesh._base_mesh.ufl_cell().cellname()
    u_hori = FiniteElement("RTCF", cell, 1)
    w_hori = FiniteElement("DG", cell, 0)

    # vertical base spaces
    u_vert = FiniteElement("DG", interval, 0)
    w_vert = FiniteElement("CG", interval, 1)

    # build elements
    u_element = HDiv(TensorProductElement(u_hori, u_vert))
    w_element = HDiv(TensorProductElement(w_hori, w_vert))
    theta_element = TensorProductElement(w_hori, w_vert)
    v_element = u_element + w_element

    # spaces
    VDG0 = FunctionSpace(mesh, "DG", 0)
    VCG1 = FunctionSpace(mesh, "CG", 1)
    VDG1 = FunctionSpace(mesh, "DG", 1)
    Vt = FunctionSpace(mesh, theta_element)
    Vt_brok = FunctionSpace(mesh, BrokenElement(theta_element))
    Vu = FunctionSpace(mesh, v_element)
    VuCG1 = VectorFunctionSpace(mesh, "CG", 1)
    VuDG1 = VectorFunctionSpace(mesh, "DG", 1)

    # set up initial conditions
    np.random.seed(0)
    expr = np.random.randn(
    ) + np.random.randn() * x + np.random.randn() * y + np.random.randn(
    ) * z + np.random.randn() * x * y + np.random.randn(
    ) * x * z + np.random.randn() * y * z + np.random.randn() * x * y * z

    # our actual theta and rho and v
    rho_CG1_true = Function(VCG1).interpolate(expr)
    theta_CG1_true = Function(VCG1).interpolate(expr)
    v_CG1_true = Function(VuCG1).interpolate(as_vector([expr, expr, expr]))
    rho_Vt_true = Function(Vt).interpolate(expr)

    # make the initial fields by projecting expressions into the lowest order spaces
    rho_DG0 = Function(VDG0).interpolate(expr)
    rho_CG1 = Function(VCG1)
    theta_Vt = Function(Vt).interpolate(expr)
    theta_CG1 = Function(VCG1)
    v_Vu = Function(Vu).project(as_vector([expr, expr, expr]))
    v_CG1 = Function(VuCG1)
    rho_Vt = Function(Vt)

    # make the recoverers and do the recovery
    rho_recoverer = Recoverer(rho_DG0,
                              rho_CG1,
                              VDG=VDG1,
                              boundary_method=Boundary_Method.dynamics)
    theta_recoverer = Recoverer(theta_Vt,
                                theta_CG1,
                                VDG=VDG1,
                                boundary_method=Boundary_Method.dynamics)
    v_recoverer = Recoverer(v_Vu,
                            v_CG1,
                            VDG=VuDG1,
                            boundary_method=Boundary_Method.dynamics)
    rho_Vt_recoverer = Recoverer(rho_DG0,
                                 rho_Vt,
                                 VDG=Vt_brok,
                                 boundary_method=Boundary_Method.physics)

    rho_recoverer.project()
    theta_recoverer.project()
    v_recoverer.project()
    rho_Vt_recoverer.project()

    rho_diff = errornorm(rho_CG1, rho_CG1_true) / norm(rho_CG1_true)
    theta_diff = errornorm(theta_CG1, theta_CG1_true) / norm(theta_CG1_true)
    v_diff = errornorm(v_CG1, v_CG1_true) / norm(v_CG1_true)
    rho_Vt_diff = errornorm(rho_Vt, rho_Vt_true) / norm(rho_Vt_true)

    return (rho_diff, theta_diff, v_diff, rho_Vt_diff)
コード例 #12
0
def unsaturated_hydrostatic_balance(state,
                                    theta_d,
                                    H,
                                    exner0=None,
                                    top=False,
                                    exner_boundary=Constant(1.0),
                                    max_outer_solve_count=40,
                                    max_inner_solve_count=20):
    """
    Given vertical profiles for dry potential temperature
    and relative humidity compute hydrostatically balanced
    virtual potential temperature, dry density and water vapour profiles.

    The general strategy is to split up the solving into two steps:
    1) finding rho to balance the theta profile
    2) finding theta_v and r_v to get back theta_d and H
    We iteratively solve these steps until we (hopefully)
    converge to a solution.

    :arg state: The :class:`State` object.
    :arg theta_d: The initial dry potential temperature profile.
    :arg H: The relative humidity profile.
    :arg exner0: Optional function to put exner pressure into.
    :arg top: If True, set a boundary condition at the top, otherwise
              it will be at the bottom.
    :arg exner_boundary: The value of exner on the specified boundary.
    :arg max_outer_solve_count: Max number of iterations for outer loop of balance solver.
    :arg max_inner_solve_count: Max number of iterations for inner loop of balanace solver.
    """

    theta0 = state.fields('theta')
    rho0 = state.fields('rho')
    mr_v0 = state.fields('vapour_mixing_ratio')

    # Calculate hydrostatic exner pressure
    Vt = theta0.function_space()
    Vr = rho0.function_space()
    R_d = state.parameters.R_d
    R_v = state.parameters.R_v
    epsilon = R_d / R_v

    VDG = state.spaces("DG")
    if any(deg > 2 for deg in VDG.ufl_element().degree()):
        logger.warning(
            "default quadrature degree most likely not sufficient for this degree element"
        )

    # apply first guesses
    theta0.assign(theta_d * 1.01)
    mr_v0.assign(0.01)

    v_deg = Vr.ufl_element().degree()[1]
    if v_deg == 0:
        method = Boundary_Method.physics
    else:
        method = None
    rho_h = Function(Vr)
    rho_averaged = Function(Vt)
    Vt_broken = FunctionSpace(state.mesh, BrokenElement(Vt.ufl_element()))
    rho_recoverer = Recoverer(rho0,
                              rho_averaged,
                              VDG=Vt_broken,
                              boundary_method=method)
    w_h = Function(Vt)
    delta = 1.0

    # make expressions for determining mr_v0
    exner = thermodynamics.exner_pressure(state.parameters, rho_averaged,
                                          theta0)
    p = thermodynamics.p(state.parameters, exner)
    T = thermodynamics.T(state.parameters, theta0, exner, mr_v0)
    r_v_expr = thermodynamics.r_v(state.parameters, H, T, p)

    # make expressions to evaluate residual
    exner_ev = thermodynamics.exner_pressure(state.parameters, rho_averaged,
                                             theta0)
    p_ev = thermodynamics.p(state.parameters, exner_ev)
    T_ev = thermodynamics.T(state.parameters, theta0, exner_ev, mr_v0)
    RH_ev = thermodynamics.RH(state.parameters, mr_v0, T_ev, p_ev)
    RH = Function(Vt)

    for i in range(max_outer_solve_count):
        # solve for rho with theta_vd and w_v guesses
        compressible_hydrostatic_balance(state,
                                         theta0,
                                         rho_h,
                                         top=top,
                                         exner_boundary=exner_boundary,
                                         mr_t=mr_v0,
                                         solve_for_rho=True)

        # damp solution
        rho0.assign(rho0 * (1 - delta) + delta * rho_h)

        # calculate averaged rho
        rho_recoverer.project()

        RH.assign(RH_ev)
        if errornorm(RH, H) < 1e-10:
            break

        # now solve for r_v
        for j in range(max_inner_solve_count):
            w_h.interpolate(r_v_expr)
            mr_v0.assign(mr_v0 * (1 - delta) + delta * w_h)

            # compute theta_vd
            theta0.assign(theta_d * (1 + mr_v0 / epsilon))

            # test quality of solution by re-evaluating expression
            RH.assign(RH_ev)
            if errornorm(RH, H) < 1e-10:
                break

        if i == max_outer_solve_count:
            raise RuntimeError(
                'Hydrostatic balance solve has not converged within %i' % i,
                'iterations')

    if exner0 is not None:
        exner = thermodynamics.exner_pressure(state.parameters, rho0, theta0)
        exner0.interpolate(exner)

    # do one extra solve for rho
    compressible_hydrostatic_balance(state,
                                     theta0,
                                     rho0,
                                     top=top,
                                     exner_boundary=exner_boundary,
                                     mr_t=mr_v0,
                                     solve_for_rho=True)
コード例 #13
0
ファイル: util.py プロジェクト: dbojanjac/scattering2D
def errornorm(uh, v):
    return fd.errornorm(uh, v)
コード例 #14
0
def verify_spatial_order_of_accuracy(sim_module,
                                     manufactured_solution,
                                     meshes,
                                     norms,
                                     expected_orders,
                                     decimal_places,
                                     sim_kwargs={},
                                     endtime=0.,
                                     strong_residual=None,
                                     dirichlet_boundary_conditions=None,
                                     starttime=0.,
                                     outfile=None,
                                     write_simulation_outputs=False):

    MMSVerificationSimulation = make_mms_verification_sim_class(
        sim_module=sim_module,
        manufactured_solution=manufactured_solution,
        write_simulation_outputs=write_simulation_outputs,
        strong_residual=strong_residual,
        mms_dirichlet_boundary_conditions=dirichlet_boundary_conditions)

    table = sapphire.table.Table(
        ("h", "cellcount", "dofcount", "errors", "spatial_orders"))

    print("")

    for mesh in meshes:

        h = mesh.cell_sizes((0., ) * mesh.geometric_dimension())

        sim = MMSVerificationSimulation(mesh=mesh, **sim_kwargs)

        if sim.time_discrete_terms() is not None:
            # If time-dependent
            sim.states = sim.run(endtime=endtime)

        else:

            sim.solution = sim.solve()

        errors = []

        w = manufactured_solution(sim)

        wh = sim.solution

        if type(w) is not type((0, )):

            w = (w, )

        for w_i, wh_i, norm in zip(w, wh.split(), norms):

            if norm is not None:

                errors.append(fe.errornorm(w_i, wh_i, norm_type=norm))

            else:

                errors.append(None)

        cellcount = mesh.topology.num_cells()

        dofcount = len(wh.vector().array())

        table.append({
            "h": h,
            "cellcount": cellcount,
            "dofcount": dofcount,
            "errors": errors
        })

        if len(table) > 1:

            h, e = table.data["h"], table.data["errors"]

            log = math.log

            orders = []

            for i in range(len(sim.solution.split())):

                if e[0][i] is None:

                    orders.append(None)

                else:

                    r = h[-2] / h[-1]

                    orders.append(log(e[-2][i] / e[-1][i]) / log(r))

            table.data["spatial_orders"][-1] = orders

        print(str(table))

    print("Last observed spatial orders of accuracy are {}".format(orders))

    if outfile:

        print("Writing convergence table to {}".format(outfile.name))

        outfile.write(str(table))

    for order, expected_order in zip(orders, expected_orders):

        if expected_order is None:

            continue

        order = round(order, decimal_places)

        expected_order = round(float(expected_order), decimal_places)

        if not (order == expected_order):

            raise ValueError(
                "\n" + "\tObserved order {} differs from\n".format(order) +
                "\texpected order {}".format(expected_order))
コード例 #15
0
ファイル: compare.py プロジェクト: mc4117/adapt_utils
}


# --- Create solver and copy initial solution

ep = AdaptiveProblem(CosinePrescribedVelocityOptions(**kwargs))
ep.set_initial_condition()
init_sol = ep.fwd_solutions_tracer[0].copy(deepcopy=True)
init_norm = norm(init_sol)


# --- Eulerian interpretation

ep.solve_forward()
final_sol_eulerian = ep.fwd_solutions_tracer[-1]
relative_error_eulerian = abs(errornorm(init_sol, final_sol_eulerian)/init_norm)
print_output("Relative error in Eulerian case:   {:.2f}%".format(100*relative_error_eulerian))


# --- Lagrangian interpretation

kwargs['approach'] = 'lagrangian'
lp = AdaptiveProblem(CosinePrescribedVelocityOptions(**kwargs))
lp.set_initial_condition()
init_sol = lp.fwd_solutions_tracer[0].copy(deepcopy=True)
init_coords = lp.meshes[0].coordinates.dat.data.copy()
lp.solve_forward()
final_sol_lagrangian = lp.fwd_solutions_tracer[-1]

final_coords = lp.meshes[-1].coordinates.dat.data
final_coords[:] -= [10.0, 0.0]  # TODO: Implement periodicity
コード例 #16
0
ファイル: outputting.py プロジェクト: tommbendall/peakondrake
    def dump_diagnostics(self, t, failed=False):
        """
        Dump the diagnostic values.

        :arg t: time.
        """

        print(self.out_string, 't = %.3f' % t)
        self.data_file.variables['time'][self.t_idx:self.t_idx + 1] = t

        u = self.prognostic_variables.u
        if 'm' in self.prognostic_variables.fields.keys():
            m = self.prognostic_variables.m
        elif 'm' in self.diagnostic_variables.fields.keys():
            m = self.diagnostic_variables.fields['m']

        alphasq = self.simulation_parameters['alphasq'][-1]
        Ld = self.simulation_parameters['Ld'][-1]
        periodic = self.simulation_parameters['periodic'][-1]
        # Need to evaluate periodic factor because we need a number from Firedrake constants
        periodic_factor = (1 - exp(-Ld / sqrt(alphasq)))
        periodic_factor = periodic_factor.evaluate(0, 0, 0, 0)

        for diagnostic in self.diagnostic_values:
            if failed:
                output = [[np.nan], [np.nan]] if diagnostic == 'mu' else np.nan
            elif diagnostic == 'energy':
                output = assemble(
                    (dot(u, u) + alphasq * dot(u.dx(0), u.dx(0))) * dx)
            elif diagnostic == 'l2_m':
                output = norm(m, norm_type='L2')
            elif diagnostic == 'l2_u':
                output = norm(u, norm_type='L2')
            elif diagnostic == 'h1_u':
                output = norm(u, norm_type='H1')
            elif diagnostic == 'h1_m':
                output = norm(m, norm_type='H1')
            elif diagnostic == 'mass_m':
                output = assemble(m * dx)
            elif diagnostic == 'mass_m2':
                output = assemble(m * m * dx)
            elif diagnostic == 'mass_u':
                output = assemble(u * dx)
            elif diagnostic == 'min_u':
                output = 1 if norm(u_min, norm_type='L2') > 1e-10 else 0
            elif diagnostic == 'max_jump_local':
                output = find_max(self.diagnostic_variables.fields['jump_du'],
                                  self.diagnostic_variables.coords)[0]
            elif diagnostic == 'max_jump_global':
                output = find_max(
                    self.diagnostic_variables.fields['du'],
                    self.diagnostic_variables.coords)[0] - find_min(
                        self.diagnostic_variables.fields['du'],
                        self.diagnostic_variables.coords)[0]
            elif diagnostic == 'max_du_loc':
                output = find_max(self.diagnostic_variables.fields['du'],
                                  self.diagnostic_variables.coords)[1]
            elif diagnostic == 'min_du_loc':
                output = find_min(self.diagnostic_variables.fields['du'],
                                  self.diagnostic_variables.coords)[1]
            elif diagnostic == 'max_du_smooth_loc':
                output = find_max(
                    self.diagnostic_variables.fields['du_smooth'],
                    self.diagnostic_variables.smooth_coords)[1]
            elif diagnostic == 'min_du_smooth_loc':
                output = find_min(
                    self.diagnostic_variables.fields['du_smooth'],
                    self.diagnostic_variables.smooth_coords)[1]
            elif diagnostic == 'max_du':
                output = np.max(
                    self.diagnostic_variables.fields['du'].dat.data[:])
            elif diagnostic == 'min_du':
                output = np.min(
                    self.diagnostic_variables.fields['du'].dat.data[:])
            elif diagnostic == 'mu':
                old_mu, alt_mu = find_mus(
                    u, self.diagnostic_variables.fields['du'],
                    self.diagnostic_variables.coords)
                output = [old_mu, alt_mu]
            elif diagnostic == 'a':
                output = self.diagnostic_variables.fields['a'].at(
                    self.data_file['x'][:], tolerance=1e-6)
            elif diagnostic == 'b':
                output = self.diagnostic_variables.fields['b'].at(
                    self.data_file['x'][:], tolerance=1e-6)
            elif diagnostic == 'l2_kdv_1':
                output = norm(self.diagnostic_variables.fields['kdv_1'],
                              norm_type='L2')
            elif diagnostic == 'l2_kdv_2':
                output = norm(self.diagnostic_variables.fields['kdv_2'],
                              norm_type='L2')
            elif diagnostic == 'l2_kdv_3':
                output = norm(self.diagnostic_variables.fields['kdv_3'],
                              norm_type='L2')
            elif diagnostic == 'p_pde':
                if periodic:
                    output = np.max(u.dat.data[:]) * periodic_factor
                else:
                    output = np.max(u.dat.data[:])
            elif diagnostic == 'q_pde':
                output = self.diagnostic_variables.coords.dat.data[np.argmax(
                    u.dat.data[:])]
            elif diagnostic == 'm_max':
                output = np.max(m.dat.data[:])
            elif diagnostic == 'E_0':
                # use the calculated du
                du = self.diagnostic_variables.fields['du']
                output = assemble(0.5 * (u**2 + alphasq * du**2) * dx)
            elif diagnostic == 'E_1':
                # just straightforwardly use u
                output = assemble(0.5 * (u**2 + alphasq * u.dx(0)**2) * dx)
            elif diagnostic == 'E_2':
                # use m
                output = assemble(0.5 * u * m * dx)
            elif diagnostic == 'E_3':
                # solve for uxx
                u_xx = self.diagnostic_variables.fields['u_xx']
                output = assemble(0.5 * u * (u + alphasq * u_xx) * dx)
            elif diagnostic == 'u_error_with_sde':
                u_hat = self.diagnostic_variables.fields['u_sde']
                output = errornorm(u, u_hat)
            elif diagnostic == 'u_error_weak':
                u_hat_weak = self.diagnostic_variables.fields['u_sde_weak']
                output = norm(u_hat_weak)
            elif diagnostic == 'u_error_with_sde_mean':
                u_hat = self.diagnostic_variables.fields['u_sde_mean']
                output = errornorm(u, u_hat)
            elif diagnostic == 'u_error_weak_mean':
                u_hat_weak = self.diagnostic_variables.fields[
                    'u_sde_weak_mean']
                output = norm(u_hat_weak)
            elif diagnostic == 'u_field':
                output = u.dat.data[:]
            elif diagnostic == 'peakon_suite':
                output = peakon_diagnostics(
                    u, self.diagnostic_variables.fields['du'],
                    self.diagnostic_variables.coords)
            else:
                raise ValueError('Diagnostic %s not recgonised.' % diagnostic)

            if diagnostic in ('a', 'b'):
                self.data_file[diagnostic][[slice(self.t_idx, self.t_idx + 1)]
                                           + self.index_slices] = output
            elif diagnostic == 'mu':
                # we cannot store arrays of mus, so have to do them each separately
                for i in range(4):
                    if i < len(output[0]):
                        # output[0] is the old mu, output[1] is the new mu
                        self.data_file[diagnostic + '_' + str(i)][
                            [slice(self.t_idx, self.t_idx + 1)] +
                            self.index_slices] = output[0][i]
                        self.data_file['alt_' + diagnostic + '_' + str(i)][
                            [slice(self.t_idx, self.t_idx + 1)] +
                            self.index_slices] = output[1][i]
                    else:
                        self.data_file[diagnostic + '_' + str(i)][
                            [slice(self.t_idx, self.t_idx + 1)] +
                            self.index_slices] = np.nan
                        self.data_file['alt_' + diagnostic + '_' + str(i)][
                            [slice(self.t_idx, self.t_idx + 1)] +
                            self.index_slices] = np.nan
            elif diagnostic == 'peakon_suite':
                for peakon_diag in self.list_of_peakon_diagnostics:
                    self.data_file[peakon_diag][
                        [slice(self.t_idx, self.t_idx + 1)] +
                        self.index_slices] = output[peakon_diag]
            else:
                self.data_file[diagnostic][[slice(self.t_idx, self.t_idx + 1)]
                                           + self.index_slices] = output

        if self.peakon_equations is not None:
            self.data_file['p'][[slice(self.t_idx, self.t_idx + 1)] +
                                self.index_slices] = self.peakon_equations.p
            self.data_file['q'][[slice(self.t_idx, self.t_idx + 1)] +
                                self.index_slices] = self.peakon_equations.q

        self.t_idx += 1
コード例 #17
0
def verify_temporal_order_of_accuracy(sim_module,
                                      manufactured_solution,
                                      timestep_sizes,
                                      endtime,
                                      norms,
                                      expected_orders,
                                      decimal_places,
                                      sim_kwargs={},
                                      starttime=0.,
                                      strong_residual=None,
                                      dirichlet_boundary_conditions=None,
                                      outfile=None,
                                      write_simulation_outputs=False):

    MMSVerificationSimulation = make_mms_verification_sim_class(
        sim_module=sim_module,
        manufactured_solution=manufactured_solution,
        write_simulation_outputs=write_simulation_outputs,
        strong_residual=strong_residual,
        mms_dirichlet_boundary_conditions=dirichlet_boundary_conditions)

    table = sapphire.table.Table(("Delta_t", "errors", "temporal_orders"))

    print("")

    for timestep_size in timestep_sizes:

        sim = MMSVerificationSimulation(**sim_kwargs)

        assert (len(sim.solutions) > 1)

        sim.timestep_size = sim.timestep_size.assign(timestep_size)

        sim.time = sim.time.assign(starttime)

        sim.states = sim.run(endtime=endtime)

        errors = []

        w = manufactured_solution(sim)

        wh = sim.solution

        if type(w) is not type((0, )):

            w = (w, )

        for w_i, wh_i, norm in zip(w, wh.split(), norms):

            if norm is not None:

                errors.append(fe.errornorm(w_i, wh_i, norm_type=norm))

            else:

                errors.append(None)

        table.append({"Delta_t": timestep_size, "errors": errors})

        if len(table) > 1:

            Delta_t, e = table.data["Delta_t"], table.data["errors"]

            log = math.log

            orders = []

            for i in range(len(sim.solution.split())):

                if e[0][i] is None:

                    orders.append(None)

                else:

                    r = Delta_t[-2] / Delta_t[-1]

                    orders.append(log(e[-2][i] / e[-1][i]) / log(r))

            table.data["temporal_orders"][-1] = orders

        print(str(table))

    print("Last observed temporal orders of accuracy are {}".format(orders))

    if outfile:

        print("Writing convergence table to {}".format(outfile.name))

        outfile.write(str(table))

    for order, expected_order in zip(orders, expected_orders):

        if expected_order is None:

            continue

        order = round(order, decimal_places)

        expected_order = round(float(expected_order), decimal_places)

        if not (order == expected_order):

            raise ValueError(
                "\n" + "\tObserved order {} differs from\n".format(order) +
                "\texpected order {}".format(expected_order))
コード例 #18
0
ファイル: test_pc.py プロジェクト: firedrakeproject/Irksome
def heat(butcher_tableau):
    N = 4
    dt = Constant(1.0 / N)
    t = Constant(0.0)

    msh = UnitSquareMesh(N, N)
    deg = 2
    V = FunctionSpace(msh, "CG", deg)

    x, y = SpatialCoordinate(msh)

    uexact = t * (x + y)
    rhs = expand_derivatives(diff(uexact, t)) - div(grad(uexact))

    sols = []

    luparams = {
        "mat_type": "aij",
        "snes_type": "ksponly",
        "ksp_type": "preonly",
        "pc_type": "lu"
    }

    ranaLD = {
        "mat_type": "aij",
        "snes_type": "ksponly",
        "ksp_type": "gmres",
        "ksp_monitor": None,
        "pc_type": "python",
        "pc_python_type": "irksome.RanaLD",
        "aux": {
            "pc_type": "fieldsplit",
            "pc_fieldsplit_type": "multiplicative"
        }
    }
    per_field = {"ksp_type": "preonly", "pc_type": "gamg"}

    for s in range(butcher_tableau.num_stages):
        ranaLD["fieldsplit_%s" % (s, )] = per_field

    ranaDU = {
        "mat_type": "aij",
        "snes_type": "ksponly",
        "ksp_type": "gmres",
        "ksp_monitor": None,
        "pc_type": "python",
        "pc_python_type": "irksome.RanaDU",
        "aux": {
            "pc_type": "fieldsplit",
            "pc_fieldsplit_type": "multiplicative"
        }
    }

    for s in range(butcher_tableau.num_stages):
        ranaLD["fieldsplit_%s" % (s, )] = per_field

    params = [luparams, ranaLD, ranaDU]

    for solver_parameters in params:
        F, u, bc = Fubc(V, uexact, rhs)

        stepper = TimeStepper(F,
                              butcher_tableau,
                              t,
                              dt,
                              u,
                              bcs=bc,
                              solver_parameters=solver_parameters)
        stepper.advance()
        sols.append(u)

    errs = [errornorm(sols[0], uu) for uu in sols[1:]]
    return numpy.max(errs)
コード例 #19
0
def test_3D_cartesian_recovery(geometry, element, mesh, expr):

    family = "RTCF" if element == "quadrilateral" else "BDM"

    # horizontal base spaces
    cell = mesh._base_mesh.ufl_cell().cellname()
    u_hori = FiniteElement(family, cell, 1)
    w_hori = FiniteElement("DG", cell, 0)

    # vertical base spaces
    u_vert = FiniteElement("DG", interval, 0)
    w_vert = FiniteElement("CG", interval, 1)

    # build elements
    u_element = HDiv(TensorProductElement(u_hori, u_vert))
    w_element = HDiv(TensorProductElement(w_hori, w_vert))
    theta_element = TensorProductElement(w_hori, w_vert)
    v_element = u_element + w_element

    # DG1
    DG1_hori = FiniteElement("DG", cell, 1, variant="equispaced")
    DG1_vert = FiniteElement("DG", interval, 1, variant="equispaced")
    DG1_elt = TensorProductElement(DG1_hori, DG1_vert)
    DG1 = FunctionSpace(mesh, DG1_elt)
    vec_DG1 = VectorFunctionSpace(mesh, DG1_elt)

    # spaces
    DG0 = FunctionSpace(mesh, "DG", 0)
    CG1 = FunctionSpace(mesh, "CG", 1)
    Vt = FunctionSpace(mesh, theta_element)
    Vt_brok = FunctionSpace(mesh, BrokenElement(theta_element))
    Vu = FunctionSpace(mesh, v_element)
    vec_CG1 = VectorFunctionSpace(mesh, "CG", 1)

    # our actual theta and rho and v
    rho_CG1_true = Function(CG1).interpolate(expr)
    theta_CG1_true = Function(CG1).interpolate(expr)
    v_CG1_true = Function(vec_CG1).interpolate(as_vector([expr, expr, expr]))
    rho_Vt_true = Function(Vt).interpolate(expr)

    # make the initial fields by projecting expressions into the lowest order spaces
    rho_DG0 = Function(DG0).interpolate(expr)
    rho_CG1 = Function(CG1)
    theta_Vt = Function(Vt).interpolate(expr)
    theta_CG1 = Function(CG1)
    v_Vu = Function(Vu).project(as_vector([expr, expr, expr]))
    v_CG1 = Function(vec_CG1)
    rho_Vt = Function(Vt)

    # make the recoverers and do the recovery
    rho_recoverer = Recoverer(rho_DG0, rho_CG1, VDG=DG1, boundary_method=Boundary_Method.dynamics)
    theta_recoverer = Recoverer(theta_Vt, theta_CG1, VDG=DG1, boundary_method=Boundary_Method.dynamics)
    v_recoverer = Recoverer(v_Vu, v_CG1, VDG=vec_DG1, boundary_method=Boundary_Method.dynamics)
    rho_Vt_recoverer = Recoverer(rho_DG0, rho_Vt, VDG=Vt_brok, boundary_method=Boundary_Method.physics)

    rho_recoverer.project()
    theta_recoverer.project()
    v_recoverer.project()
    rho_Vt_recoverer.project()

    rho_diff = errornorm(rho_CG1, rho_CG1_true) / norm(rho_CG1_true)
    theta_diff = errornorm(theta_CG1, theta_CG1_true) / norm(theta_CG1_true)
    v_diff = errornorm(v_CG1, v_CG1_true) / norm(v_CG1_true)
    rho_Vt_diff = errornorm(rho_Vt, rho_Vt_true) / norm(rho_Vt_true)

    tolerance = 1e-7
    error_message = ("""
                     Incorrect recovery for {variable} with {boundary} boundary method
                     on {geometry} 3D Cartesian domain with {element} elements
                     """)
    assert rho_diff < tolerance, error_message.format(variable='rho', boundary='dynamics',
                                                      geometry=geometry, element=element)
    assert v_diff < tolerance, error_message.format(variable='v', boundary='dynamics',
                                                    geometry=geometry, element=element)
    assert theta_diff < tolerance, error_message.format(variable='rho', boundary='dynamics',
                                                        geometry=geometry, element=element)
    assert rho_Vt_diff < tolerance, error_message.format(variable='rho', boundary='physics',
                                                         geometry=geometry, element=element)
コード例 #20
0
print(gamma)

new_mesh = RectangleMesh(880, 20, 220, 10)

bath = Function(FunctionSpace(new_mesh, "CG",
                              1)).project(swp.fwd_solutions_bathymetry[0])

fpath = "hydrodynamics_beach_bath_mov_{:d}_{:d}_{:d}_{:d}_{:d}"
fpath = fpath.format(op.dt_per_export, int(fac_x * 220), alpha, beta, gamma)
export_bathymetry(bath, os.path.join("adapt_output", fpath), op=op)

bath_real = initialise_bathymetry(
    new_mesh, 'fixed_output/hydrodynamics_beach_bath_fixed_440_10')

print('L2')
print(fire.errornorm(bath, bath_real))
print(kappa)

V = FunctionSpace(new_mesh, 'CG', 1)

x, y = SpatialCoordinate(new_mesh)

bath_mod = Function(V).interpolate(conditional(x > 70, bath, Constant(0.0)))
bath_real_mod = Function(V).interpolate(
    conditional(x > 70, bath_real, Constant(0.0)))

print('subdomain')

print(fire.errornorm(bath_mod, bath_real_mod))

print('tolerance value')
コード例 #21
0
    cg_ilu_params['ksp_monitor_true_residual'] = None

rho_solver = LinearVariationalSolver(rho_problem,
                                     solver_parameters=cg_ilu_params)

max_outer_solve_count = 20
max_inner_solve_count = 10

PETSc.Sys.Print("Starting rho solver loop...\n")

for i in range(max_outer_solve_count):
    # calculate averaged rho
    rho_recoverer.project()

    RH.assign(RH_ev)
    if errornorm(RH, H) < 1e-10:
        break

    # first solve for r_v
    for j in range(max_inner_solve_count):
        w_h.interpolate(r_v_expr)
        water_v0.assign(water_v0 * (1 - delta) + delta * w_h)

        # compute theta_vd
        theta0.assign(theta_d * (1 + water_v0 / epsilon))

        # test quality of solution by re-evaluating expression
        RH.assign(RH_ev)
        if errornorm(RH, H) < 1e-10:
            break
コード例 #22
0
        # increase dt until error > error_threshold
        while error < error_threshold:
            # error < error_threshold so increase dt by small amount
            dt = dt + step
            # NB: prolong does not copy so we must re-assign ref sol.
            fine = Function(V_fine).assign(ref)
            # Run the simulation with this dt
            try:
                sol = solver_CG(mesh,
                                el=cell_type,
                                space=space,
                                deg=degree,
                                T=0.50,
                                dt=dt)
                error = errornorm(ref, prolong(sol, fine))
            except Exception:
                # numerical instability occurred, exit with last stable dt
                dt = dt - step
                error = 1e10
            print(
                "For degree {}, the error is {} using a {} s timestep".format(
                    degree, error, dt))
        # error > error_threshold,
        print(
            "Highest stable dt is {} s for a degree {} for a an error threshold of {}"
            .format(dt, degree, error_threshold))
        dts[i, j] = dt

print("------FINISHED------")
print(dts)
コード例 #23
0
    f.interpolate(fexpr)  # Coriolis frequency (1/s)

    u0.project(uexpr)
    D0.interpolate(Dexpr)
    state.initialise([('u', u0),
                      ('D', D0)])

    ueqn = VectorInvariant(state, u0.function_space())
    Deqn = AdvectionEquation(state, D0.function_space(),
                             equation_form="continuity")
    advected_fields = []
    advected_fields.append(("u", ThetaMethod(state, u0, ueqn)))
    advected_fields.append(("D", SSPRK3(state, D0, Deqn, subcycles=2)))

    linear_solver = ShallowWaterSolver(state)

    # Set up forcing
    sw_forcing = ShallowWaterForcing(state, euler_poincare=False)

    # build time stepper
    stepper = CrankNicolson(state, advected_fields, linear_solver,
                            sw_forcing)

    stepper.run(t=0, tmax=tmax)

    xn = state.xn
    un, Dn = xn.split()

    uerr = errornorm(u0, un, norm_type="L2")
    Derr = errornorm(D0, Dn, norm_type="L2")
コード例 #24
0
ファイル: mms.py プロジェクト: mfkiwl/sapphire
def verify_order_of_accuracy(
        discretization_parameter_name,
        discretization_parameter_values,
        Simulation,
        manufactured_solution,
        norms,
        points_in_rate_estimator=2,
        expected_orders=None,  # a.k.a. convergence rates
        decimal_places=2,
        time_dependent=True,
        sim_kwargs={},
        endtime=0.,
        strong_residual=None,
        dirichlet_boundary_conditions=None,
        starttime=0.,
        outfile=None,
        write_simulation_outputs=False):

    n = points_in_rate_estimator

    pname = discretization_parameter_name

    pvalues = discretization_parameter_values

    if n > 3:

        raise NotImplementedError("Max `points_in_rate_estimator` is 3.")

    if len(pvalues) < n:

        raise ValueError("There must be a discretization parameter value "
                         "for each point in the rate estimation.")

    fieldcount = len(norms)

    if expected_orders:

        assert (len(expected_orders) == len(norms))

    for pvalue in pvalues:

        if not pvalue > 0:

            raise ("`discretization_parameter_values` must be positive.")

    r = pvalues[0] / pvalues[1]  # Refinement rate

    if r < 0:

        raise ("`discretization_parameter_values` must be "
               "a descending sequence.")

    if n > 2:

        for iv in range(1, len(pvalues)):

            if not numpy.isclose(pvalues[iv - 1] / pvalues[iv], r):

                raise ("`discretization_parameter_values` must be "
                       "a geometric sequence when using more than two "
                       "points in the rate estimator.")

    MMSVerificationSimulation = make_mms_verification_sim_class(
        Simulation=Simulation,
        manufactured_solution=manufactured_solution,
        write_simulation_outputs=write_simulation_outputs,
        strong_residual=strong_residual,
        mms_dirichlet_boundary_conditions=dirichlet_boundary_conditions)

    columns = [
        pname,
    ]

    for i, norm in enumerate(norms):

        if norm is not None:

            columns += ["error{}".format(i), "order{}".format(i)]

    table = pandas.DataFrame(index=range(len(pvalues)), columns=columns)

    for iv, pval in enumerate(pvalues):

        table[pname][iv] = pval

    print()

    print(str(table).replace(" NaN", "None"))

    for iv, pval in enumerate(pvalues):

        sim_kwargs[pname] = pval

        sim = MMSVerificationSimulation(**sim_kwargs)

        wh = sim.solution

        assert (len(wh.split()) == fieldcount)

        if time_dependent:

            sim.states = sim.run(endtime=endtime)

        else:

            sim.solution = sim.solve()

        w = manufactured_solution(sim)

        if type(w) is not tuple:

            w = (w, )

        for iw, w_i, wh_i, norm in zip(range(fieldcount), w, wh.split(),
                                       norms):

            if norm is not None:

                table["error{}".format(iw)][iv] = fe.errornorm(w_i,
                                                               wh_i,
                                                               norm_type=norm)

        if iv >= (n - 1):

            h = table[pname]

            log = math.log

            for iw in range(fieldcount):

                if norms[iw] is not None:

                    e = table["error{}".format(iw)]

                    if n == 2:

                        order = log(e[iv - 1] / e[iv]) / log(r)

                    elif n == 3:

                        order = log((e[iv - 2] - e[iv - 1]) /
                                    (e[iv - 1] - e[iv])) / log(r)

                    table["order{}".format(iw)][iv] = order

        print()

        print(str(table).replace(" NaN", "None"))

    if outfile:

        print("Writing convergence table to {}".format(outfile.name))

        outfile.write(table.to_csv())

    if expected_orders:

        for iorder, expected_order in enumerate(expected_orders):

            if expected_order is not None:

                order = table.iloc[-1]["order{}".format(iorder)]

                order = round(order, decimal_places)

                expected_order = round(float(expected_order), decimal_places)

                if not (order == expected_order):

                    raise ValueError(
                        "\n" +
                        "\tObserved order {} differs from\n".format(order) +
                        "\texpected order {}".format(expected_order))

    print()

    print("Formatted for LaTeX:")

    print(format_for_latex(table, norms=norms))

    return table
コード例 #25
0
def saturated_hydrostatic_balance(state,
                                  theta_e,
                                  mr_t,
                                  exner0=None,
                                  top=False,
                                  exner_boundary=Constant(1.0),
                                  max_outer_solve_count=40,
                                  max_theta_solve_count=5,
                                  max_inner_solve_count=3):
    """
    Given a wet equivalent potential temperature, theta_e, and the total moisture
    content, mr_t, compute a hydrostatically balance virtual potential temperature,
    dry density and water vapour profile.

    The general strategy is to split up the solving into two steps:
    1) finding rho to balance the theta profile
    2) finding theta_v and r_v to get back theta_e and saturation
    We iteratively solve these steps until we (hopefully)
    converge to a solution.

    :arg state: The :class:`State` object.
    :arg theta_e: The initial wet equivalent potential temperature profile.
    :arg mr_t: The total water pseudo-mixing ratio profile.
    :arg exner0: Optional function to put exner pressure into.
    :arg top: If True, set a boundary condition at the top, otherwise
              it will be at the bottom.
    :arg exner_boundary: The value of exner on the specified boundary.
    :arg max_outer_solve_count: Max number of outer iterations for balance solver.
    :arg max_theta_solve_count: Max number of iterations for theta solver (middle part of solve).
    :arg max_inner_solve_count: Max number of iterations on the inner most
                                loop for the water vapour solver.
    """

    theta0 = state.fields('theta')
    rho0 = state.fields('rho')
    mr_v0 = state.fields('vapour_mixing_ratio')

    # Calculate hydrostatic exner pressure
    Vt = theta0.function_space()
    Vr = rho0.function_space()

    VDG = state.spaces("DG")
    if any(deg > 2 for deg in VDG.ufl_element().degree()):
        logger.warning(
            "default quadrature degree most likely not sufficient for this degree element"
        )

    theta0.interpolate(theta_e)
    mr_v0.interpolate(mr_t)

    v_deg = Vr.ufl_element().degree()[1]
    if v_deg == 0:
        boundary_method = Boundary_Method.physics
    else:
        boundary_method = None
    rho_h = Function(Vr)
    Vt_broken = FunctionSpace(state.mesh, BrokenElement(Vt.ufl_element()))
    rho_averaged = Function(Vt)
    rho_recoverer = Recoverer(rho0,
                              rho_averaged,
                              VDG=Vt_broken,
                              boundary_method=boundary_method)
    w_h = Function(Vt)
    theta_h = Function(Vt)
    theta_e_test = Function(Vt)
    delta = 0.8

    # expressions for finding theta0 and mr_v0 from theta_e and mr_t
    exner = thermodynamics.exner_pressure(state.parameters, rho_averaged,
                                          theta0)
    p = thermodynamics.p(state.parameters, exner)
    T = thermodynamics.T(state.parameters, theta0, exner, mr_v0)
    r_v_expr = thermodynamics.r_sat(state.parameters, T, p)
    theta_e_expr = thermodynamics.theta_e(state.parameters, T, p, mr_v0, mr_t)

    for i in range(max_outer_solve_count):
        # solve for rho with theta_vd and w_v guesses
        compressible_hydrostatic_balance(state,
                                         theta0,
                                         rho_h,
                                         top=top,
                                         exner_boundary=exner_boundary,
                                         mr_t=mr_t,
                                         solve_for_rho=True)

        # damp solution
        rho0.assign(rho0 * (1 - delta) + delta * rho_h)

        theta_e_test.assign(theta_e_expr)
        if errornorm(theta_e_test, theta_e) < 1e-8:
            break

        # calculate averaged rho
        rho_recoverer.project()

        # now solve for r_v
        for j in range(max_theta_solve_count):
            theta_h.interpolate(theta_e / theta_e_expr * theta0)
            theta0.assign(theta0 * (1 - delta) + delta * theta_h)

            # break when close enough
            if errornorm(theta_e_test, theta_e) < 1e-6:
                break
            for k in range(max_inner_solve_count):
                w_h.interpolate(r_v_expr)
                mr_v0.assign(mr_v0 * (1 - delta) + delta * w_h)

                # break when close enough
                theta_e_test.assign(theta_e_expr)
                if errornorm(theta_e_test, theta_e) < 1e-6:
                    break

        if i == max_outer_solve_count:
            raise RuntimeError(
                'Hydrostatic balance solve has not converged within %i' % i,
                'iterations')

    if exner0 is not None:
        exner = thermodynamics.exner(state.parameters, rho0, theta0)
        exner0.interpolate(exner)

    # do one extra solve for rho
    compressible_hydrostatic_balance(state,
                                     theta0,
                                     rho0,
                                     top=top,
                                     exner_boundary=exner_boundary,
                                     mr_t=mr_t,
                                     solve_for_rho=True)
コード例 #26
0
def main():
    # make function space and function
    dim = 2  # 2 or 3
    order = 1

    logger.info(f"building {dim}D source and solution exprs")
    if dim == 2:
        m = UnitSquareMesh(32, 32)
    elif dim == 3:
        m = UnitCubeMesh(16, 16, 16)
    else:
        raise ValueError("dim must be 2 or 3, not %s" % dim)
    # get spatial coordinate, shifted so that [0,1]^2 -> [-0.5,0.5]^2
    xx = SpatialCoordinate(m)
    shifted_xx = as_tensor([xx_i - 0.5 for xx_i in xx])
    norm2 = sum([xx_i * xx_i for xx_i in shifted_xx])
    alpha = 10
    source_expr = -(4 * alpha**2 * norm2 - 2 * dim * alpha) * exp(
        -alpha * norm2)
    sol_expr = exp(-alpha * norm2)

    logger.info("source_expr : %s" % source_expr)
    logger.info("sol_expr : %s" % sol_expr)

    logger.info(f"Building FunctionSpace of order {order}")
    fspace = FunctionSpace(m, 'DG', order)
    logger.info("interpolating source and solution")
    source = Function(fspace).interpolate(source_expr)
    sol = Function(fspace).interpolate(sol_expr)

    from sumpy.kernel import LaplaceKernel
    kernel = LaplaceKernel(m.geometric_dimension())

    # We could set to a custom group factory if we wanted to,
    # defaults to recursive nodes with 'lgl' nodes
    #
    # from meshmode.discretization.poly_element import (
    #     PolynomialWarpAndBlendGroupFactory)
    # grp_factory = PolynomialWarpAndBlendGroupFactory(order)
    grp_factory = None

    # Build VolumePotential external operator
    cl_ctx = cl.create_some_context()
    queue = cl.CommandQueue(cl_ctx)
    potential_data = {
        'kernel': kernel,
        'kernel_type': "Laplace",
        'cl_ctx': cl_ctx,
        'queue': queue,
        'nlevels': 6,
        'm_order': 20,
        'dataset_filename': f"laplace-order{order}-{dim}D.hdf5",
        'grp_factory': grp_factory,
        'root_extent': 2,
        'table_compute_method': "DrosteSum",
        'table_kwargs': {
            'force_recompute': False,
            'n_brick_quad_points': 100,
            'adaptive_level': False,
            'use_symmetry': True,
            'alpha': 0.1,
            'nlevels': 15,
        },
        'fmm_kwargs': {},
    }

    logger.info("Creating volume potential")
    # pot = VolumePotential(source, function_space=source.function_space(), operator_data=potential_data)

    # logger.info("Evaluating potential and assembling L^2 Error")
    # ell2_difference = sqrt(assemble(inner(pot - sol, pot - sol) * dx))

    # print("L^2 difference: %e" % ell2_difference)
    print("interpolation error: %e" % errornorm(sol_expr, sol))