Beispiel #1
0
    def __init__(self, topoconfig: TopoConfig, grid: Gridlines, dtype: str):
        dtype = DummyDtype.validator(dtype)
        dem, _ = read_cf(topoconfig.file, [topoconfig.key])

        # copy to a nplike.ndarray
        vert = nplike.array(dem[topoconfig.key][:])

        # see if we need to do interpolation
        try:
            interp = not (nplike.allclose(grid.x.vert, nplike.array(dem["x"]))
                          and nplike.allclose(grid.y.vert,
                                              nplike.array(dem["y"])))
        except ValueError:  # assume thie excpetion means a shape mismatch
            interp = True

        # unfortunately, we need to do interpolation in such a situation
        if interp:
            interpolator = RectBivariateSpline(dem["x"], dem["y"], vert.T)
            vert = nplike.array(interpolator(
                grid.x.vert, grid.y.vert).T)  # it uses vanilla numpy

        # cast to desired float type
        vert = vert.astype(dtype)

        # topography elevation at cell centers through linear interpolation
        cntr = vert[:-1, :-1] + vert[:-1, 1:] + vert[1:, :-1] + vert[1:, 1:]
        cntr /= 4

        # topography elevation at cell faces' midpoints through linear interpolation
        xface = (vert[:-1, :] + vert[1:, :]) / 2.
        yface = (vert[:, :-1] + vert[:, 1:]) / 2.

        # gradient at cell centers through central difference; here allows nonuniform grids
        # this function does not assume constant cell sizes, so we re-calculate dx, dy
        # the `delta`s in grid.x and y are constants (current solver only supports uniform grid)
        xgrad = (xface[:, 1:] - xface[:, :-1]) / (grid.x.vert[1:] -
                                                  grid.x.vert[:-1])[None, :]
        ygrad = (yface[1:, :] - yface[:-1, :]) / (grid.y.vert[1:] -
                                                  grid.y.vert[:-1])[:, None]

        # initialize DataModel and let pydantic validates data
        super().__init__(nx=grid.x.n,
                         ny=grid.y.n,
                         dtype=dtype,
                         vert=vert,
                         cntr=cntr,
                         xface=xface,
                         yface=yface,
                         xgrad=xgrad,
                         ygrad=ygrad)
Beispiel #2
0
pyplot.style.use(case_dir.joinpath("paper.mplstyle"))

# import the "exact_soln" functions from cases
sys.path.insert(0, str(case_dir))
topo_fun = importlib.import_module("create_data").topo
exact_soln = importlib.import_module("create_data").exact_soln

# read data in
# -------------
if case_dir.joinpath("solutions.npz").is_file():
    sim_data = {}
    with numpy.load(case_dir.joinpath("solutions.npz")) as data:
        for k, v in data.items():
            sim_data[k] = v[:]
else:
    sim_data, _ = read_cf(case_dir.joinpath("solutions.nc"), ["w", "hu", "hv"])
    numpy.savez_compressed(case_dir.joinpath("solutions"), **sim_data)

# some parameters
# ----------------
L = 4.
h0 = 0.1
a = 1.
g = 9.81
eta = 0.5
omega = numpy.sqrt(2. * g * h0)

# topo
# -----
topo = topo_fun(*numpy.meshgrid(sim_data["x"], sim_data["y"]), h0, L, a)
def main():
    """Plot and compare to analytical solutions."""

    # read simulation data
    filename = pathlib.Path(__file__).expanduser().resolve().parent.joinpath(
        "solutions.nc")
    sim_data, _ = read_cf(filename, ["w", "hu"])
    x = sim_data["x"]
    w = sim_data["w"][-1, :, :]  # only keep the soln at the last time
    w = numpy.mean(w, 0)  # use the average in y direction
    hu = sim_data["hu"][-1, :, :]
    hu = numpy.mean(hu, 0)

    # get a set of analytical solution for error
    b_ana = topo(x)
    h_ana = numpy.zeros_like(x)
    C0, C1 = get_coeffs(b_ana, 4.42, 2.0, 9.81)
    for i, c1 in enumerate(C1):
        h_ana[i] = numpy.roots([1.0, c1, 0., C0])[0]
    w_ana = h_ana + b_ana

    # get another set of solution for plotting
    x_plot = numpy.linspace(0., 25., 1000, dtype=numpy.float64)
    b_plot = topo(x_plot)
    h_plot = numpy.zeros_like(x_plot)
    C0, C1 = get_coeffs(b_plot, 4.42, 2.0, 9.81)
    for i, c1 in enumerate(C1):
        h_plot[i] = numpy.roots([1.0, c1, 0., C0])[0]
    w_plot = h_plot + b_plot

    # relative L1 error
    w_err = numpy.abs((w - w_ana) / w_ana)

    # total volume per unit y
    vol = w.sum() * (x[1] - x[0])
    vol_ana = w_ana.sum() * (x[1] - x[0])
    print("Total volume per y: analytical -- {} m^2; ".format(vol_ana) +
          "simulation -- {} m^2".format(vol))

    # plot
    pyplot.figure()
    pyplot.plot(x_plot, b_plot, "k-", lw=4, label="Topography elevation (m)")
    pyplot.plot(x_plot, w_plot, "k-", lw=2, label="Analytical solution")
    pyplot.plot(x,
                w,
                ls='',
                marker='x',
                ms=5,
                alpha=0.6,
                label="Simulation solution")
    pyplot.title("Subcritical flow: water level")
    pyplot.xlabel("x (m)")
    pyplot.ylabel("Water level (m)")
    pyplot.grid()
    pyplot.legend()
    pyplot.savefig("simulation_vs_analytical_w.png", dpi=166)

    pyplot.figure()
    pyplot.plot(x_plot, h_plot, "k-", lw=2, label="Analytical solution")
    pyplot.plot(x,
                w - b_ana,
                ls='',
                marker='x',
                ms=5,
                alpha=0.6,
                label="Simulation solution")
    pyplot.title("Subcritical flow: water depth")
    pyplot.xlabel("x (m)")
    pyplot.ylabel("Water depth (m)")
    pyplot.grid()
    pyplot.legend()
    pyplot.savefig("simulation_vs_analytical_h.png", dpi=166)

    pyplot.figure()
    pyplot.plot(x_plot,
                numpy.ones_like(x_plot) * 4.42,
                "k-",
                lw=2,
                label="Analytical solution")
    pyplot.plot(x,
                hu,
                ls='',
                marker='x',
                ms=5,
                alpha=0.6,
                label="Simulation solution")
    pyplot.title("Subcritical flow: discharge")
    pyplot.xlabel("x (m)")
    pyplot.ylabel("Discharge " r"($q=hu$)" " (m)")
    pyplot.grid()
    pyplot.legend()
    pyplot.savefig("simulation_vs_analytical_hu.png", dpi=166)

    pyplot.figure()
    pyplot.semilogy(x, w_err, "k-", lw=2)
    pyplot.title("Subcritical flow: relative L1 error of w")
    pyplot.xlabel("x (m)")
    pyplot.ylabel(
        r"$\left|\left(w_{simulation}-w_{analytical}\right)/w_{analytical}\right|$"
    )
    pyplot.grid()
    pyplot.savefig("simulation_vs_analytical_w_L1.png", dpi=166)

    return 0
def main():
    """Plot and compare to analytical solutions."""

    # get the critical depth; also represents h at b = 0.2 (& x = 10)
    hcr = solve_hcr(0.18, 9.81)
    xsh = solve_shock_loc(0.2, hcr, 0.18, 0.33, 9.81)

    # read simulation data
    filename = pathlib.Path(__file__).expanduser().resolve().parent.joinpath(
        "solutions.nc")
    sim_data, _ = read_cf(filename, ["w", "hu"])
    x = sim_data["x"]
    w = sim_data["w"][-1, :, :]  # only keep the soln at the last time
    w = numpy.mean(w, 0)  # use the average in y direction
    hu = sim_data["hu"][-1, :, :]
    hu = numpy.mean(hu, 0)

    # get a set of analytical solution for error
    b_ana, _, w_ana = get_analytical(x, 0.2, hcr, xsh, 0.18, 0.33, 9.81)

    # get another set of solution for plotting
    x_plot = numpy.linspace(0., 25., 2500)
    b_plot, h_plot, w_plot = get_analytical(x_plot, 0.2, hcr, xsh, 0.18, 0.33,
                                            9.81)

    # relative L1 error
    w_err = numpy.abs((w - w_ana) / w_ana)

    # total volume of w per unit y
    vol = w.sum() * (x[1] - x[0])
    vol_ana = w_ana.sum() * (x[1] - x[0])
    print("Total volume per y: analytical -- {} m^2; ".format(vol_ana) +
          "simulation -- {} m^2".format(vol))

    # plot
    pyplot.figure()
    pyplot.plot(x_plot, b_plot, "k-", lw=4, label="Topography elevation (m)")
    pyplot.plot(x_plot, w_plot, "k-", lw=2, label="Analytical solution")
    pyplot.plot(x,
                w,
                ls='',
                marker='x',
                ms=5,
                alpha=0.6,
                label="Simulation solution")
    pyplot.title("Transcritical flow w/ shock: water level")
    pyplot.xlabel("x (m)")
    pyplot.ylabel("Water level (m)")
    pyplot.grid()
    pyplot.legend()
    pyplot.savefig("simulation_vs_analytical_w.png", dpi=166)

    pyplot.figure()
    pyplot.plot(x_plot, h_plot, "k-", lw=2, label="Analytical solution")
    pyplot.plot(x,
                w - b_ana,
                ls='',
                marker='x',
                ms=5,
                alpha=0.6,
                label="Simulation solution")
    pyplot.title("Transcritical flow w/ shock: water depth")
    pyplot.xlabel("x (m)")
    pyplot.ylabel("Water depth (m)")
    pyplot.grid()
    pyplot.legend()
    pyplot.savefig("simulation_vs_analytical_h.png", dpi=166)

    pyplot.figure()
    pyplot.plot(x_plot,
                numpy.ones_like(x_plot) * 0.18,
                "k-",
                lw=2,
                label="Analytical solution")
    pyplot.plot(x,
                hu,
                ls='',
                marker='x',
                ms=5,
                alpha=0.6,
                label="Simulation solution")
    pyplot.title("Transcritical flow w/ shock: discharge")
    pyplot.xlabel("x (m)")
    pyplot.ylabel("Discharge " r"($q=hu$)" " (m)")
    pyplot.grid()
    pyplot.legend()
    pyplot.savefig("simulation_vs_analytical_hu.png", dpi=166)

    pyplot.figure()
    pyplot.semilogy(x, w_err, "k-", lw=2)
    pyplot.title("Transcritical flow w/ shock: relative L1 error of w")
    pyplot.xlabel("x (m)")
    pyplot.ylabel(
        r"$\left|\left(w_{simulation}-w_{analytical}\right)/w_{analytical}\right|$"
    )
    pyplot.grid()
    pyplot.savefig("simulation_vs_analytical_w_L1.png", dpi=166)
Beispiel #5
0
def main():
    """Plot and compare to analytical solutions."""
    # pylint: disable=invalid-name

    # read simulation data
    filename = pathlib.Path(__file__).expanduser().resolve().parent.joinpath(
        "solutions.nc")
    sim_data, _ = read_cf(filename, ["w"])

    # 2D coordinates
    x = sim_data["x"]
    y = sim_data["y"]
    X, Y = numpy.meshgrid(x, y)

    # get solutions except the one at T=0
    W = sim_data["w"][1:, :, :]

    # time labels
    t = [0.12, 0.24, 0.36, 0.48, 0.6]

    # contour line range
    n = 32
    r = [
        numpy.linspace(0.999703, 1.00629, n),
        numpy.linspace(0.994836, 1.01604, n),
        numpy.linspace(0.988582, 1.0117, n),
        numpy.linspace(0.990344, 1.00497, n),
        numpy.linspace(0.995065, 1.0056, n)
    ]

    # contour lines: to compare with Xing & Shu
    for i in range(5):
        pyplot.figure(figsize=(10, 4), dpi=166)
        pyplot.contour(X, Y, W[i], r[i], linewidths=1)
        pyplot.title(
            "Xing & Shu (2005) case 5.3: water level @ T={} sec".format(t[i]))
        pyplot.xlabel("x (m)")
        pyplot.ylabel("y (m)")
        pyplot.xlim(0., 2.)
        pyplot.ylim(0., 1.)
        pyplot.colorbar()
        pyplot.tight_layout()
        pyplot.savefig("water_level_contourline_t={}.png".format(t[i]),
                       dpi=166,
                       bbox_inches="tight")

    # contourf
    for i in range(5):
        pyplot.figure(figsize=(10, 4), dpi=166)
        pyplot.contourf(X, Y, W[i], 128)
        pyplot.title(
            "Xing & Shu (2005) case 5.3: water level @ T={} sec".format(t[i]))
        pyplot.xlabel("x (m)")
        pyplot.ylabel("y (m)")
        pyplot.xlim(0., 2.)
        pyplot.ylim(0., 1.)
        pyplot.colorbar()
        pyplot.tight_layout()
        pyplot.savefig("water_level_contour_t={}.png".format(t[i]),
                       dpi=166,
                       bbox_inches="tight")

    return 0
Beispiel #6
0
def create_ic(ic_config, gridlines, topo, dtype):
    """Create initial conditions.

    When the x_cntr and y_cntr have different resolutions from the x and y in the NetCDF file, an
    bi-cubic spline interpolation will take place.

    Arguments
    ---------
    ic_config : torchswe.utils.config.ICConfig
    gridlines : torchswe.utils.data.Gridlines
    topo : torchswe.utils.data.Topography
    dtype : str; either "float32" or "float64"

    Returns
    -------
    torchswe.utils.data.WHUHVModel
    """

    # special case: constant I.C.
    if ic_config.values is not None:
        return WHUHVModel(gridlines.x.n,
                          gridlines.y.n,
                          dtype,
                          w=nplike.maximum(topo.cntr,
                                           nplike.array(ic_config.values[0])),
                          hu=nplike.full(topo.cntr.shape,
                                         ic_config.values[1],
                                         dtype=topo.dtype),
                          hv=nplike.full(topo.cntr.shape,
                                         ic_config.values[2],
                                         dtype=topo.dtype))

    # otherwise, read data from a NetCDF file
    icdata, _ = read_cf(ic_config.file, ic_config.keys)

    # see if we need to do interpolation
    try:
        interp = not (
            nplike.allclose(gridlines.x.cntr, nplike.array(icdata["x"]))
            and nplike.allclose(gridlines.y.cntr, nplike.array(icdata["y"])))
    except ValueError:  # assume thie excpetion means a shape mismatch
        interp = True

    # unfortunately, we need to do interpolation in such a situation
    if interp:
        interpolator = RectBivariateSpline(icdata["x"], icdata["y"],
                                           icdata[ic_config.keys[0]][:].T)
        w = interpolator(gridlines.x.cntr, gridlines.y.cntr).T

        # get an interpolator for conserv_q_ic[1], use the default 3rd order spline
        interpolator = RectBivariateSpline(icdata["x"], icdata["y"],
                                           icdata[ic_config.keys[1]][:].T)
        hu = interpolator(gridlines.x.cntr, gridlines.y.cntr).T

        # get an interpolator for conserv_q_ic[2], use the default 3rd order spline
        interpolator = RectBivariateSpline(icdata["x"], icdata["y"],
                                           icdata[ic_config.keys[2]][:].T)
        hv = interpolator(gridlines.x.cntr, gridlines.y.cntr).T
    else:
        w = nplike.array(icdata[ic_config.keys[0]][:].copy())
        hu = nplike.array(icdata[ic_config.keys[1]][:].copy())
        hv = nplike.array(icdata[ic_config.keys[2]][:].copy())

    # make sure the w can not be smaller than topopgraphy elevation
    w = nplike.maximum(w, topo.cntr)

    return WHUHVModel(gridlines.x.n, gridlines.y.n, dtype, w=w, hu=hu, hv=hv)