Exemple #1
0
def update_solute_transport_pde(mesh,
                                solute_pde,
                                concentration_old,
                                v,
                                dt,
                                solute_source,
                                dispersion_tensor,
                                diffusivity,
                                l_disp,
                                t_disp,
                                rho_f,
                                verbose=False):
    """
    Solve the solute transport equation.
    """

    # calculate hydrodynamic dispersivity tensor from molecular diffusivity
    # and longitudinal and transverse dispersivity

    # calculate absolute velocity
    v_abs = (v[0]**2 + v[1]**2)**0.5

    # get rid of 0 values of velocity
    v_abs_1 = es.whereZero(v_abs) * 1e-20 + es.whereNonZero(v_abs) * v_abs

    Dxx = l_disp * (v[0]**2) / v_abs_1 + diffusivity
    Dyy = t_disp * (v[1]**2) / v_abs_1 + diffusivity

    # and set dispersion tensor to 0 where 0 absolute velocity
    Dxx = (Dxx * es.whereNonZero(v_abs) + es.whereZero(v_abs) * diffusivity)
    Dyy = (Dyy * es.whereNonZero(v_abs) + es.whereZero(v_abs) * diffusivity)

    # horizontal and vertical values of dispersion (Dxx and Dyy)
    dispersion_tensor[0, 0] = Dxx
    dispersion_tensor[1, 1] = Dyy

    # off-diagonal terms in tensor (Dxy and Dyx)
    # set to 0 for now, model becomes numerically unstable
    # testing with fixed values did not result in significant cahnges in solute conc...
    # todo, figure out why this is unstable or check the potential error
    dispersion_tensor[0, 1] = (l_disp - t_disp) * (v[0] * v[1]) / v_abs_1
    dispersion_tensor[1, 0] = (l_disp - t_disp) * (v[0] * v[1]) / v_abs_1

    u_old = concentration_old

    a_coeff = dt * dispersion_tensor * es.kronecker(mesh)
    c_coeff = dt * v
    d_coeff = 1
    y_coeff = u_old + solute_source * dt

    if verbose is True:
        print('solute transport coefficients')
        print('A: ', a_coeff.getShape(), a_coeff)
        print('C: ', c_coeff.getShape(), c_coeff)
        print('D: ', d_coeff)
        print('Y: ', y_coeff.getShape(), y_coeff)

    solute_pde.setValue(A=a_coeff, C=c_coeff, D=d_coeff, Y=y_coeff)

    return solute_pde
def RegionalCalculation(reg_mask):
    """
    Calculates the "regional" from the entire FEILDS model excluding the
    selected region and outputs gravity at the specified altitude...
    see above for the "residual"
    """

    # read in a gravity data grid to define data computation space
    G_DATA = os.path.join(DATADIR,'Final_BouguerTC_UC15K_qrtdeg.nc')
    FS=ReducedFunction(dom)
    nValues=[NX, NY, 1]
    first = [0, 0, cell_at_altitude]
    multiplier = [1, 1, 1]
    reverse = [0, 0, 0]
    byteorder = BYTEORDER_NATIVE
    gdata = readBinaryGrid(G_DATA, FS, shape=(),
                fill=-999999, byteOrder=byteorder,
                dataType=DATATYPE_FLOAT32, first=first, numValues=nValues,
                multiplier=multiplier, reverse=reverse)
    print("Grid successfully read")

    # get the masking and units sorted out for the data-space
    g_mask = whereNonZero(gdata+999999)

    gdata=gdata*g_mask * GRAV_UNITS

    # if people choose to have air in their region we exclude it from the
    # specified gravity calculation region
    if h_top < 0.:
        reg_mask = reg_mask+mask_air

    live_model = initial_model* whereNonPositive(reg_mask)
    dead_model = initial_model* wherePositive(reg_mask)

    if UseMean is True:
        # calculate the mean density within the selected region
        BackgroundDensity = integrate(dead_model)/integrate(wherePositive(reg_mask))
        print("Density mean for selected region equals = %s"%BackgroundDensity)

        live_model = live_model + BackgroundDensity * wherePositive(reg_mask)

    # create mapping
    rho_mapping = DensityMapping(dom, rho0=live_model)

    # invert sign of gravity field to account for escript's coordinate system
    gdata = -GRAV_UNITS * gdata

    # turn the scalars into vectors (vertical direction)
    d=kronecker(DIM)[DIM-1]
    w=safeDiv(1., g_mask)
    gravity_model=GravityModel(dom, w*d, gdata*d, fixPotentialAtBottom=False, coordinates=COORDINATES)
    gravity_model.rescaleWeights(rho_scale=rho_mapping.getTypicalDerivative())
    phi,_ = gravity_model.getArguments(live_model)
    g_init = -gravity_model.getCoordinateTransformation().getGradient(phi)
    g_init = interpolate(g_init, gdata.getFunctionSpace())
    print("Computed gravity: %s"%(g_init[2]))

    fn=os.path.join(OUTPUTDIR,'regional-gravity')
    if SiloOutput is True:
        saveSilo(fn, density=live_model, gravity_init=g_init, g_initz=-g_init[2], gravitymask=g_mask, modelmask=reg_mask)
        print('SILO file written with the following fields: density (kg/m^3), gravity vector (m/s^2), gz (m/s^2), gravitymask, modelmask')

    # to compare calculated data against input dataset.
    # Not used by default but should work if the input dataset is correct
    #gslice = g_init[2]*wherePositive(g_mask)
    #g_dash = integrate(gslice)/integrate(wherePositive(g_mask))
    #gdataslice = gdata*wherePositive(g_mask)
    #gdata_dash = integrate(gdataslice)/integrate(wherePositive(g_mask))
    #misfit=(gdataslice-gdata_dash)-(gslice-g_dash)
    saveDataCSV(fn+".csv", mask=g_mask, gz=-g_init[2], Long=datacoords[0], Lat=datacoords[1], h=datacoords[2])
    print('CSV file written with the following fields: Longitude (degrees) Latitude (degrees), h (100km), gz (m/s^2)')
    pass

# read in the FEILDS Voxet
initial_model = readVoxet(dom, MODEL_DATASET, MODEL_PROPERTY, MODEL_ORIGIN,
                          0., COORDINATES)

# set the extents of the desired "region" for clipping and computation,
# mask is = 1 OUTSIDE area of interest

mask_air = whereNonNegative(dom.getX()[2]+spacing[2]/2) #reg_mask for air layer
mask_LONG = wherePositive(Longitude_W-datacoords[0]) + whereNegative(Longitude_E-datacoords[0]) #reg_mask for longitude
mask_LAT = whereNegative(Latitude_N-datacoords[1]) + wherePositive(Latitude_S-datacoords[1])    #reg_mask for latitude
mask_h = wherePositive(datacoords[2]+(h_top/100)) + whereNegative(datacoords[2]+(h_base/100))   #reg_mask for depth

if ReverseSelection:
    reg_mask = whereNonZero(mask_LONG+mask_LAT+mask_h)
else:
    reg_mask = whereZero(mask_LONG+mask_LAT+mask_h)

# prior to any computation, write out the selected region model as CSV
# and Silo if requested
fn = os.path.join(OUTPUTDIR, "region_%s")%(MODEL_PROPERTY)
saveDataCSV(fn+".csv", Long=datacoords[0], Lat=datacoords[1], h=datacoords[2],
            PROPERTY=initial_model, mask=reg_mask)
print("CSV file written with the following fields: Longitude (degrees)"
     +" Latitude (degrees), h (100km), Property (kg/m^3 or Pa)")

if SiloOutput:
    saveSilo(fn, PROPERTY=initial_model, mask=reg_mask)
    print('SILO file written with the following fields: Property (kg/m^3 or Pa), mask')