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')