Ejemplo n.º 1
0
def create_Efield(cfg, xg, params):

    cfg["E0dir"].mkdir(parents=True, exist_ok=True)

    # %% CREATE ELECTRIC FIELD DATASET
    llon = 100
    llat = 100
    # NOTE: cartesian-specific code
    if xg["lx"][1] == 1:
        llon = 1
    elif xg["lx"][2] == 1:
        llat = 1

    thetamin = xg["theta"].min()
    thetamax = xg["theta"].max()
    mlatmin = 90 - np.degrees(thetamax)
    mlatmax = 90 - np.degrees(thetamin)
    mlonmin = np.degrees(xg["phi"].min())
    mlonmax = np.degrees(xg["phi"].max())

    # add a 1% buff
    latbuf = 0.01 * (mlatmax - mlatmin)
    lonbuf = 0.01 * (mlonmax - mlonmin)

    E = xarray.Dataset(
        coords={
            "time":
            datetime_range(cfg["time"][0], cfg["time"][0] +
                           cfg["tdur"], cfg["dtE0"]),
            "mlat":
            np.linspace(mlatmin - latbuf, mlatmax + latbuf, llat),
            "mlon":
            np.linspace(mlonmin - lonbuf, mlonmax + lonbuf, llon),
        })
    Nt = E.time.size

    # %% INTERPOLATE X2 COORDINATE ONTO PROPOSED MLON GRID
    xgmlon = np.degrees(xg["phi"][0, :, 0])
    # xgmlat = 90 - np.degrees(xg["theta"][0, 0, :])

    f = interp1d(xgmlon,
                 xg["x2"][2:xg["lx"][1] + 2],
                 kind="linear",
                 fill_value="extrapolate")
    x2i = f(E["mlon"])
    # f = interp1d(xgmlat, xg["x3"][2:lx3 + 2], kind='linear', fill_value="extrapolate")
    # x3i = f(E["mlat"])

    # %% CREATE DATA FOR BACKGROUND ELECTRIC FIELDS
    if "Exit" in cfg:
        E["Exit"] = (("time", "mlon", "mlat"), cfg["Exit"] * np.ones(
            (Nt, llon, llat)))
    else:
        E["Exit"] = (("time", "mlon", "mlat"), np.zeros((Nt, llon, llat)))
    if "Eyit" in cfg:
        E["Eyit"] = (("time", "mlon", "mlat"), cfg["Eyit"] * np.ones(
            (Nt, llon, llat)))
    else:
        E["Eyit"] = (("time", "mlon", "mlat"), np.zeros((Nt, llon, llat)))

    # %% CREATE DATA FOR BOUNDARY CONDITIONS FOR POTENTIAL SOLUTION

    # if 0 data is interpreted as FAC, else we interpret it as potential
    E["flagdirich"] = (("time", ), np.zeros(Nt, dtype=np.int32))
    E["Vminx1it"] = (("time", "mlon", "mlat"), np.zeros((Nt, llon, llat)))
    E["Vmaxx1it"] = (("time", "mlon", "mlat"), np.zeros((Nt, llon, llat)))
    # these are just slices
    E["Vminx2ist"] = (("time", "mlat"), np.zeros((Nt, llat)))
    E["Vmaxx2ist"] = (("time", "mlat"), np.zeros((Nt, llat)))
    E["Vminx3ist"] = (("time", "mlon"), np.zeros((Nt, llon)))
    E["Vmaxx3ist"] = (("time", "mlon"), np.zeros((Nt, llon)))

    for i in range(Nt):
        # ZEROS TOP CURRENT AND X3 BOUNDARIES DON'T MATTER SINCE PERIODIC

        # COMPUTE KHI DRIFT FROM APPLIED POTENTIAL
        vel3 = np.empty((llon, llat))
        for j in range(llat):
            vel3[:, j] = params["v0"] * np.tanh(
                x2i / params["ell"]) - params["vn"]

        vel3 = np.flipud(vel3)

        # CONVERT TO ELECTRIC FIELD (actually -1* electric field...)
        E2slab = vel3 * params["B1val"]

        # INTEGRATE TO PRODUCE A POTENTIAL OVER GRID - then save the edge boundary conditions
        DX2 = np.diff(x2i)
        DX2 = np.append(DX2, DX2[-1])
        Phislab = np.cumsum(E2slab * DX2, axis=0)
        # use a forward difference

        E["Vmaxx2ist"][i, :] = Phislab[-1, :]
        E["Vminx2ist"][i, :] = Phislab[0, :]

    # %% Write electric field data to file
    gemini3d.write.Efield(E, cfg["E0dir"], cfg["file_format"])
Ejemplo n.º 2
0
def fast2GEMINI(cfg, xg):
    # output dict.
    pg = {}

    # read in the data
    [invlat, eflux, chare] = readfast(filename)

    # smooth data a bit prior to insertion into model
    lsmooth = 0
    [efluxsmooth, charesmooth] = smoothfast(lsmooth, eflux, chare)

    # basic grid info
    gridmlat = 90 - xg["theta"] * 180 / pi
    gridmlon = xg["phi"] * 180 / pi
    mlatmin = np.min(gridmlat)
    mlatmax = np.max(gridmlat)
    mlonmin = np.min(gridmlon)
    mlonmax = np.max(gridmlon)

    # precipitation input grids
    llon = 128
    llat = invlat.size
    mlon = np.linspace(mlonmin, mlonmax, llon)
    mlat = invlat
    mlonctr = np.average(mlon)
    mlatctr = np.average(mlat)

    # fast data may need to be sorted along the latitude axis
    isort = np.argsort(mlat)
    mlat = mlat[isort]
    efluxsmooth = efluxsmooth[isort]
    charesmooth = charesmooth[isort]

    # for convenience recenter grid on what the user has made
    #dmlat=np.average(gridmlat)-mlatctr
    dmlat = 0
    mlat = mlat + dmlat

    # time grid for precipitation
    time = datetime_range(cfg["time"][0], cfg["time"][0] + cfg["tdur"],
                          cfg["dtprec"])
    lt = len(time)
    t = np.empty((lt))
    for k in range(0, lt):
        t[k] = time[k].timestamp()
    meant = np.average(t)

    # longitude shape
    Q = np.empty((lt, llon, llat))
    E0 = np.empty((lt, llon, llat))
    siglon = 15
    sigt = 100
    for k in range(0, lt):
        tshape = np.exp(-(t[k] - meant)**2 / 2 / sigt**2)
        for ilon in range(0, llon):
            lonshape = np.exp(-(mlon[ilon] - mlonctr)**2 / 2 / siglon**2)
            Q[k, ilon, :] = tshape * lonshape * efluxsmooth[:]
            E0[k, ilon, :] = charesmooth[:]

    # fill values
    Q[Q < 0] = 0
    E0[E0 < 101] = 101

    # create xarray dataset
    pg = xarray.Dataset(
        {
            "Q": (("time", "mlon", "mlat"), Q),
            "E0": (("time", "mlon", "mlat"), E0),
        },
        coords={
            "time": time,
            "mlat": mlat,
            "mlon": mlon,
        },
    )

    # make a representative plot if required
    if debug:
        plt.subplots(1, 2, dpi=100)
        plt.subplot(1, 2, 1)
        plt.pcolormesh(mlon, mlat, Q[lt // 2, :, :].transpose())
        plt.colorbar()
        plt.title("energy flux")
        plt.xlabel("mlon")
        plt.ylabel("mlat")
        plt.subplot(1, 2, 2)
        plt.pcolormesh(mlon, mlat, E0[lt // 2, :, :].transpose())
        plt.colorbar()
        plt.title("char. en.")
        plt.xlabel("mlon")
        plt.ylabel("mlat")
        plt.show(block=False)

    # write these to the simulation input directory
    write.precip(pg, cfg["precdir"], cfg["file_format"])
    return
Ejemplo n.º 3
0
def create_precip(cfg, xg, params):
    """write particle precipitation to disk"""

    # %% CREATE PRECIPITATION INPUT DATA
    # Q: energy flux [mW m^-2]
    # E0: characteristic energy [eV]

    pg = precip_grid(cfg, xg)

    # did user specify on/off time? if not, assume always on.
    t0 = pg.time[0].data

    if "precip_startsec" in cfg:
        t = t0 + np.timedelta64(cfg["precip_startsec"])
        i_on = abs(pg.time - t).argmin().item()
    else:
        i_on = 0

    if "precip_endsec" in cfg:
        t = t0 + np.timedelta64(cfg["precip_endsec"])
        i_off = abs(pg.time - t).argmin().item()
    else:
        i_off = pg.time.size

    assert np.isfinite(cfg["E0precip"]), "E0 precipitation must be finite"
    assert cfg["E0precip"] > 0, "E0 precip must be positive"
    assert cfg["E0precip"] < 100e6, "E0 precip must not be relativistic 100 MeV"

    llon = 512
    llat = 512
    # NOTE: cartesian-specific code
    if xg["lx"][1] == 1:
        llon = 1
    elif xg["lx"][2] == 1:
        llat = 1

    thetamin = xg["theta"].min()
    thetamax = xg["theta"].max()
    mlatmin = 90 - np.degrees(thetamax)
    mlatmax = 90 - np.degrees(thetamin)
    mlonmin = np.degrees(xg["phi"].min())
    mlonmax = np.degrees(xg["phi"].max())

    # add a 1% buff
    latbuf = 0.01 * (mlatmax - mlatmin)
    lonbuf = 0.01 * (mlonmax - mlonmin)

    time = datetime_range(cfg["time"][0], cfg["time"][0] + cfg["tdur"],
                          cfg["dtprec"])

    pg = xarray.Dataset(
        {
            "Q": (("time", "mlon", "mlat"), np.zeros((len(time), llon, llat))),
            "E0": (("time", "mlon", "mlat"), np.zeros(
                (len(time), llon, llat))),
        },
        coords={
            "time": time,
            "mlat": np.linspace(mlatmin - latbuf, mlatmax + latbuf, llat),
            "mlon": np.linspace(mlonmin - lonbuf, mlonmax + lonbuf, llon),
        },
    )
    Nt = pg.time.size

    # %% INTERPOLATE X2 COORDINATE ONTO PROPOSED MLON GRID
    xgmlon = np.degrees(xg["phi"][0, :, 0])
    # xgmlat = 90 - np.degrees(xg["theta"][0, 0, :])

    f = interp1d(xgmlon,
                 xg["x2"][2:xg["lx"][1] + 2],
                 kind="linear",
                 fill_value="extrapolate")
    x2i = f(pg["mlon"])
    # f = interp1d(xgmlat, xg["x3"][2:lx3 + 2], kind='linear', fill_value="extrapolate")
    # x3i = f(E["mlat"])

    # NOTE: in future, E0 could be made time-dependent in config.nml as 1D array
    for i in range(i_on, i_off):
        pg["Q"][i, :, :] = precip_SAID(pg, params, x2i, cfg["Qprecip"],
                                       cfg["Qprecip_background"])
        pg["E0"][i, :, :] = cfg["E0precip"]

    assert np.isfinite(pg["Q"]).all(), "Q flux must be finite"
    assert (pg["Q"] >= 0).all(), "Q flux must be non-negative"

    gemini3d.write.precip(pg, cfg["precdir"], cfg["file_format"])