def heatDiff(self,iii): ''' Heat diffusion function :param z: :param dz: :param Ts: :param rho: :returns self.Tz: :returns self.T10m: thermal diffusivity: alpha = K_firn / (rho*c_firn) ''' nz_P = len(self.z) nz_fv = nz_P - 2 nt = 1 z_edges_vec1 = self.z[0:-1] + np.diff(self.z) / 2 z_edges_vec = np.concatenate(([self.z[0]], z_edges_vec1, [self.z[-1]])) z_P_vec = self.z phi_s = self.Tz[0] phi_0 = self.Tz K_ice = 9.828 * np.exp(-0.0057 * phi_0) # thermal conductivity, Cuffey and Paterson, eq. 9.2 (Yen 1981) c_firn = 152.5 + 7.122 * phi_0 # specific heat, Cuffey and Paterson, eq. 9.1 (page 400) # c_firn = CP_I # If you prefer a constant specific heat. K_firn = firnConductivity(self,iii,K_ice) # thermal conductivity if self.c['MELT']: try: if self.c['LWCheat']=='lowK': K_firn[self.LWC>0]=K_firn[self.LWC>0]/1.e4 except: pass Gamma_P = K_firn tot_rho = self.rho c_vol = self.rho * c_firn self.Tz = transient_solve_TR(z_edges_vec, z_P_vec, nt, self.dt[iii], Gamma_P, phi_0, nz_P, nz_fv, phi_s, tot_rho, c_vol) self.T10m = self.Tz[np.where(self.z>=10.0)[0][0]] if self.c['MELT']: if self.c['LWCheat']=='effectiveT': pass elif np.any(self.Tz>273.15): print('WARNING: TEMPERATURE EXCEEDS MELTING TEMPERATURE') print('Maximum temperature was:',np.max(self.Tz),' at layers:',np.where(self.Tz == np.max(self.Tz))) print('WARM TEMPERATURES HAVE BEEN SET TO 273.15; MODEL RUN IS CONTINUING') self.Tz[self.Tz>=273.15]=273.15 return self.Tz, self.T10m
def heatDiff(self, iii): ''' Heat diffusion function :param z: :param dz: :param Ts: :param rho: :returns self.Tz: :returns self.T10m: ''' nz_P = len(self.z) nz_fv = nz_P - 2 nt = 1 z_edges_vec = self.z[1:-2] + self.dz[2:-1] / 2 z_edges_vec = np.concatenate(([self.z[0]], z_edges_vec, [self.z[-1]])) z_P_vec = self.z # phi_s = self.Ts[iii] phi_s = self.Tz[0] phi_0 = self.Tz # K_ice = 9.828 * np.exp(-0.0057 * phi_0) # K_firn = K_ice * (self.rho / 1000) ** (2 - 0.5 * (self.rho / 1000)) K_firn = 0.021 + 2.5 * (self.rho / 1000.)**2 c_firn = 152.5 + 7.122 * phi_0 Gamma_P = K_firn / (c_firn * self.rho) self.Tz = transient_solve_TR(z_edges_vec, z_P_vec, nt, self.dt, Gamma_P, phi_0, nz_P, nz_fv, phi_s) self.Tz = np.concatenate(([self.Ts[iii]], self.Tz[:-1])) fT10m = interpolate.interp1d(self.z, self.Tz) # temp at 10m depth self.T10m = fT10m(10) return self.Tz, self.T10m
def isoDiff(self,iii): ''' Isotope diffusion function :param iter: :param z: :param dz: :param rho: :param iso: :returns self.phi_t: ''' nz_P = len(self.z) # number of nodes in z nz_fv = nz_P - 2 # number of finite volumes in z nt = 1 # number of time steps # z_edges_vec = self.z[1:-2] + self.dz[2:-1] / 2 # uniform edge spacing of volume edges # z_edges_vec = np.concatenate(([self.z[0]], z_edges_vec, [self.z[-1]])) # z_P_vec = self.z z_edges_vec1 = self.z[0:-1] + np.diff(self.z) / 2 z_edges_vec = np.concatenate(([self.z[0]], z_edges_vec1, [self.z[-1]])) z_P_vec = self.z ### Node positions phi_s = self.del_z[0] # isotope value at surface phi_0 = self.del_z # initial isotope profile ### Define diffusivity for each isotopic species ### Establish values needed for diffusivity calculation m = 0.018 # kg/mol; molar mass of water pz = 3.454 * np.power(10, 12) * np.exp(-6133 / self.Tz) # Pa; saturation vapor pressure over ice alpha_18_z = 0.9722 * np.exp(11.839 / self.Tz) # fractionation factor for 18_O # alpha_18_z = np.exp(11.839/Tz-28.224*np.power(10,-3)) # alternate formulation from Eric's python code alpha_D_z = 0.9098 * np.exp(16288 / np.power(self.Tz, 2)) # fractionation factor for D Po = 1.0 # reference pressure in atm P = 1.0 ### Set diffusivity in air (units of m^2/s) # Da = 2.1 * np.power(10.0, -5.) * np.power(self.Tz / 273.15, 1.94) * (Po / P) Da = 2.1 * 1.0e-5 * (self.Tz / 273.15)**1.94 * (Po / P) Da_18 = Da / 1.0285 # account for fractionation factor for 18_O, fixed Johnsen typo Da_D = Da / 1.0251 # account for fractionation factor for D, fixed Johnsen typo ### Calculate tortuosity invtau = np.zeros(int(len(self.dz))) b = 0.25 # Tortuosity parameter invtau[self.rho < RHO_I / np.sqrt(b)] = 1.0 - (b * (self.rho[self.rho < RHO_I / np.sqrt(b)] / RHO_I)) ** 2 invtau[self.rho >= RHO_I / np.sqrt(b)] = 0.0 ### Set diffusivity for each isotope if self.c['iso'] == '18': D = m * pz * invtau * Da_18 * (1 / self.rho - 1 / RHO_I) / (R * self.Tz * alpha_18_z) D = D + 1.5e-15 self.del_z = transient_solve_TR(z_edges_vec, z_P_vec, nt, self.dt, D, phi_0, nz_P, nz_fv, phi_s, self.rho) elif self.c['iso'] == 'D': D = m * pz * invtau * Da_D * (1 / self.rho - 1 / RHO_I) / (R * self.Tz * alpha_D_z) D[D<=0.0] = 1.0e-20 self.del_z = transient_solve_TR(z_edges_vec, z_P_vec, nt, self.dt, D, phi_0, nz_P, nz_fv, phi_s, self.rho) elif self.c['iso'] == 'NoDiffusion': pass ### Solve for vertical isotope profile at this time step i self.del_z = np.concatenate(([self.del_s[iii]], self.del_z[:-1])) return self.del_z
def heatDiff(self,iii): ''' Heat diffusion function :param z: :param dz: :param Ts: :param rho: :returns self.Tz: :returns self.T10m: # thermal diffusivity: alpha = K_firn / (rho*c_firn) ''' nz_P = len(self.z) nz_fv = nz_P - 2 nt = 1 # z_edges_vec = self.z[1:-2] + self.dz[2:-1] / 2 # z_edges_vec = np.concatenate(([self.z[0]], z_edges_vec, [self.z[-1]])) # z_P_vec = self.z z_edges_vec1 = self.z[0:-1] + np.diff(self.z) / 2 z_edges_vec = np.concatenate(([self.z[0]], z_edges_vec1, [self.z[-1]])) z_P_vec = self.z phi_s = self.Tz[0] phi_0 = self.Tz K_ice = 9.828 * np.exp(-0.0057 * phi_0) # thermal conductivity, Cuffey and Paterson, eq. 9.2 (Yen 1981) # c_firn = 152.5 + 7.122 * phi_0 # specific heat, Cuffey and Paterson, eq. 9.1 (page 400) c_firn = CP_I # If you prefer a constant specific heat. ### Conductivity. Choose your favorite! ### # References are provided at the end of this script. # alpha_DAVIDCS_m2s = 18.3 / S_PER_YEAR # special for work Max was doing for David Clemens-Sewell # K_firn = alpha_DAVIDCS_m2s * self.rho * c_firn # K_firn[self.z>=20.0] = K_ice[self.z>=20.0] * (self.rho[self.z>=20.0]/RHO_I) ** (2 - 0.5 * (self.rho[self.z>=20.0]/RHO_I)) # Schwander 1997, eq. A11 # K_firn = K_ice * (self.rho/RHO_I) ** (2 - 0.5 * (self.rho/RHO_I)) # Schwander 1997, eq. A11 # K_firn = 2.22362 * (self.rho / 1000)**1.885 # Yen 1981, eq 34 w/ fixed K_ice (original) # K_firn = K_ice * (self.rho / 1000)**1.885 # Yen 1981, modified for variable K_ice # K_firn = 0.021 + 2.5 * (self.rho/1000.)**2 # Anderson (1976) # K_firn = 0.0688 * np.exp(0.0088*phi_0 + 4.6682*self.rho) # Yen 1981, eq. 35. # K_firn = 0.138 - 1.01*(self.rho/1000) + 3.233*(self.rho/1000)**2 # Sturm, 1997.; rho < 0.6 # K_firn = 2.1e-2 + 4.2e-4 * self.rho + 2.2e-9 * (self.rho)**3 # Van Dusen 1929 (via C&P) K_firn = (2 * K_ice * self.rho) / (3*RHO_I - self.rho) # Schwerdtfeger (via C&P) # K_firn = 3.e-6 * self.rho**2 - 1.06e-5 * self.rho + 0.024 # Riche and Schneebeli 2013 eq. 10 # k_firn = 0.0784 + 2.697 * (self.rho/1000.)**2 # Jiawen 1991 eq. 3 Gamma_P = K_firn # (new) # Gamma_P = K_firn / (c_firn) # old) tot_rho = self.rho c_vol = self.rho * c_firn # print('c_vol',c_vol) self.Tz = transient_solve_TR(z_edges_vec, z_P_vec, nt, self.dt, Gamma_P, phi_0, nz_P, nz_fv, phi_s, tot_rho, c_vol) fT10m = interpolate.interp1d(self.z, self.Tz) # temp at 10m depth self.T10m = fT10m(10) if np.any(self.Tz>273.17): print('WARNING: TEMPERATURE EXCEEDS MELTING TEMPERATURE') print('Maximal temperature was:',np.max(self.Tz),' at layers:',np.where(self.Tz == np.max(self.Tz))) print('WARM TEMPERATURES HAVE BEEN SET TO 273.15; MODEL RUN IS CONTINUING') self.Tz[self.Tz>=273.15]=273.15 return self.Tz, self.T10m
def isoDiff(self, IsoParams, iii): ''' Isotope diffusion function :param iter: :param z: :param dz: :param rho: :param iso: :returns self.phi_t: ''' for k, v in list(IsoParams.items()): setattr(self, k, v) nz_P = len(self.z) # number of nodes in z nz_fv = nz_P - 2 # number of finite volumes in z nt = 1 # number of time steps # z_edges_vec = self.z[1:-2] + self.dz[2:-1] / 2 # uniform edge spacing of volume edges # z_edges_vec = np.concatenate(([self.z[0]], z_edges_vec, [self.z[-1]])) # z_P_vec = self.z z_edges_vec1 = self.z[0:-1] + np.diff(self.z) / 2 z_edges_vec = np.concatenate(([self.z[0]], z_edges_vec1, [self.z[-1]])) z_P_vec = self.z ### Node positions phi_s = self.del_z[0] # isotope value at surface # phi_s = self.del_z[1] # isotope value at surface # if iii==0: # print('Caution! line 121, isotopeDiffusion.py') phi_0 = self.del_z # initial isotope profile ### Define diffusivity for each isotopic species ### Establish values needed for diffusivity calculation m = 0.018 # kg/mol; molar mass of water pz = 3.454e12 * np.exp( -6133 / self.Tz) # Pa; saturation vapor pressure over ice alpha_18_z = 0.9722 * np.exp( 11.839 / self.Tz) # fractionation factor for 18_O # alpha_18_z = np.exp(11.839/Tz-28.224*np.power(10,-3)) # alternate formulation from Eric's python code alpha_D_z = 0.9098 * np.exp(16288 / (self.Tz**2)) # fractionation factor for D Po = 1.0 # reference pressure in atm # P = 1.0 P = self.c[ 'site_pressure'] / 1013.25 # Pressure at WAIS from Christo's thesis. ### Set diffusivity in air (units of m^2/s) Da = 2.11e-5 * (self.Tz / 273.15)**1.94 * (Po / P) ### Calculate tortuosity invtau = np.zeros(int(len(self.dz))) b = 1.3 # Tortuosity parameter (Johnsen 2000) invtau[self.rho < RHO_I / np.sqrt(b)] = 1.0 - ( b * (self.rho[self.rho < RHO_I / np.sqrt(b)] / RHO_I)**2) # b = 0.25 # Tortuosity parameter (Emma's value), effective b = 0.0625 (taken outside of squared term) # invtau[self.rho < RHO_I / np.sqrt(b)] = 1.0 - (b * (self.rho[self.rho < RHO_I / np.sqrt(b)] / RHO_I))**2 #Emma invtau[self.rho >= RHO_I / np.sqrt(b)] = 0.0 ### Set diffusivity for each isotope c_vol = np.ones_like( self.rho) # Just a filler here to make the diffusion work. if ((self.isotope == '18') or (self.isotope == 'd18O')): Da_18 = Da / 1.0285 # account for fractionation factor for 18_O, fixed Johnsen typo D = m * pz * invtau * Da_18 * (1 / self.rho - 1 / RHO_I) / ( R * self.Tz * alpha_18_z) D = D + 1.5e-15 # Emma added - not sure why? prevent negative? self.del_z = transient_solve_TR(z_edges_vec, z_P_vec, nt, self.dt, D, phi_0, nz_P, nz_fv, phi_s, self.rho, c_vol) elif ((self.isotope == 'D') or (self.isotope == 'dD')): Da_D = Da / 1.0251 # account for fractionation factor for D, fixed Johnsen typo D = m * pz * invtau * Da_D * (1 / self.rho - 1 / RHO_I) / ( R * self.Tz * alpha_D_z) D[D <= 0.0] = 1.0e-20 self.del_z = transient_solve_TR(z_edges_vec, z_P_vec, nt, self.dt, D, phi_0, nz_P, nz_fv, phi_s, self.rho, c_vol) elif ((self.isotope == 'NoDiffusion') or (self.isotope == 'ND')): D = np.zeros_like(self.z) dsig2_dt = 2 * (-1 * self.drho_dt / self.rho) * self.iso_sig2_z + 2 * D self.iso_sig2_z = self.iso_sig2_z + dsig2_dt * self.dt # Advect profile down if self.bdot > 0.0: self.del_z = np.concatenate(([self.del_s[iii]], self.del_z[:-1])) self.iso_sig2_z = np.concatenate( ([self.iso_sig2_s[iii]], self.iso_sig2_z[:-1])) else: pass # self.del_z[0] = self.del_z[1] # print('Caution!!! You are altering the upper isotope value! Line 173, isotopeDiffusion.py') return self.del_z, self.iso_sig2_z
def firn_air_diffusion(self, AirParams, iii): ''' Solve the diffusion equation. Calls solver.py ''' for k, v in list(AirParams.items()): setattr(self, k, v) nz_P = len(self.z) nz_fv = nz_P - 2 nt = 1 z_edges1 = self.z[0:-1] + np.diff(self.z) / 2 z_edges = np.concatenate(([self.z[0]], z_edges1, [self.z[-1]])) z_P_vec = self.z # if (iii>100 and iii<110): # print('z_P',z_P_vec[0:5]) # print('len p', len(z_P_vec)) # print('edges',z_edges[0:5]) # print('len edges',len(z_edges)) # input('enter') # phi_s = self.Ts[iii] phi_s = self.Gz[0] phi_0 = self.Gz # K_ice = 9.828 * np.exp(-0.0057 * phi_0) # K_firn = K_ice * (self.rho / 1000) ** (2 - 0.5 * (self.rho / 1000)) self.rho_co, self.por_co, self.por_tot, self.por_cl, self.por_op, self.bcoRho, self.LIDRho = self.porosity( ) # self.air_pressure_old = np.copy(self.air_pressure) porosity_old = (RHO_I - self.rho_old) / RHO_I por_co1 = 1 - self.rho_co / RHO_I # Porosity at close-off alpha = 0.37 # constant determined in Goujon por_cl1 = np.zeros_like(porosity_old) por_cl1[porosity_old > 0] = alpha * porosity_old[porosity_old > 0] * ( porosity_old[porosity_old > 0] / por_co1)**(-7.6) ind = por_cl1 > porosity_old por_cl1[ind] = porosity_old[ind] por_op_old = porosity_old - por_cl1 # Open Porosity self.air_volume_old = por_op_old * self.dz_old # self.air_volume_old = np.copy(self.air_volume) self.air_volume = self.por_op * self.dz volfrac = self.air_volume_old / self.air_volume # volfrac = np.concatenate(([volfrac[0]],volfrac)) self.air_pressure = (self.p_a * np.exp( M_AIR * GRAVITY * self.z / (R * self.Tz))) * volfrac - ( self.p_a * np.exp(M_AIR * GRAVITY * self.z / (R * self.Tz)) ) # assume air pressure is atmos in entire column self.pressure_grad = np.gradient(self.air_pressure, self.z) self.z_co = min(self.z[self.rho >= ( self.bcoRho)]) #close-off depth; bcoRho is mean close off density # self.z_co = min(self.z[self.rho>=(self.rho_co)]) #close-off depth; bcoRho is close off density # self.z_co = self.z[np.where(self.rho>=self.rho_co)[0][0]] #close-off depth; bcoRho is close off density self.LID = min(self.z[self.rho >= ( self.LIDRho)]) #lock in depth; LIDRho is lock-in density # print(self.LID) self.bdot_t = self.bdot[iii] self.diffu, self.d_eddy = self.diffusivity() # ij = np.where(self.diffu<=1e-20)[0][0] # print('Diffu zero',self.z[ij]) airdict = { 'd_eddy': self.d_eddy, 'por_op': self.por_op, 'Tz': self.Tz, 'deltaM': self.deltaM, 'omega': self.omega, 'dz': self.dz, 'rho': self.rho, 'gravity': self.cg['gravity'], 'thermal': self.cg['thermal'], 'air_pressure': self.air_pressure, 'pressure_grad': self.pressure_grad, 'z': self.z, 'dt': self.dt, 'z_co': self.z_co, 'p_a': self.p_a, 'por_tot': self.por_tot, 'por_cl': self.por_cl, 'w_firn': self.w_firn, 'advection_type': self.cg['advection_type'], 'iii': iii, 'gaschoice': self.gaschoice } msk = np.where(self.z > self.z_co)[0][0] c_vol = np.ones_like( self.rho) # Just a filler here to make the diffusion work. self.Gz, w_p = transient_solve_TR(z_edges, z_P_vec, nt, self.dt, self.diffu, phi_0, nz_P, nz_fv, phi_s, self.rho, c_vol, airdict) self.Gz = np.concatenate(([self.Gs[iii]], self.Gz[:-1])) ind_LID = np.where(self.z >= self.LID)[0] self.gas_age[self.gas_age > 0] = self.gas_age[self.gas_age > 0] + self.dt / S_PER_YEAR self.gas_age = np.concatenate(([0], self.gas_age[:-1])) self.gas_age[ind_LID[0]] = 15.0 ii2 = np.where((self.z > self.LID) & (self.gas_age == 0))[0] self.gas_age[ii2] = 15 # print('diffu',self.diffu[0:10]) return self.Gz, self.diffu, w_p, self.gas_age
def isoDiff(self, iii): ''' Isotope diffusion function :param iter: :param z: :param dz: :param rho: :param iso: :returns self.phi_t: ''' nz_P = len(self.z) # number of nodes in z nz_fv = nz_P - 2 # number of finite volumes in z nt = 1 # number of time steps # z_edges_vec = self.z[1:-2] + self.dz[2:-1] / 2 # uniform edge spacing of volume edges # z_edges_vec = np.concatenate(([self.z[0]], z_edges_vec, [self.z[-1]])) # z_P_vec = self.z z_edges_vec1 = self.z[0:-1] + np.diff(self.z) / 2 z_edges_vec = np.concatenate(([self.z[0]], z_edges_vec1, [self.z[-1]])) z_P_vec = self.z ### Node positions phi_s = self.del_z[0] # isotope value at surface phi_0 = self.del_z # initial isotope profile ### Define diffusivity for each isotopic species ### Establish values needed for diffusivity calculation m = 0.018 # kg/mol; molar mass of water pz = 3.454 * np.power(10, 12) * np.exp( -6133 / self.Tz) # Pa; saturation vapor pressure over ice alpha_18_z = 0.9722 * np.exp( 11.839 / self.Tz) # fractionation factor for 18_O # alpha_18_z = np.exp(11.839/Tz-28.224*np.power(10,-3)) # alternate formulation from Eric's python code alpha_D_z = 0.9098 * np.exp( 16288 / np.power(self.Tz, 2)) # fractionation factor for D Po = 1.0 # reference pressure in atm P = 1.0 ### Set diffusivity in air (units of m^2/s) # Da = 2.1 * np.power(10.0, -5.) * np.power(self.Tz / 273.15, 1.94) * (Po / P) Da = 2.1 * 1.0e-5 * (self.Tz / 273.15)**1.94 * (Po / P) Da_18 = Da / 1.0285 # account for fractionation factor for 18_O, fixed Johnsen typo Da_D = Da / 1.0251 # account for fractionation factor for D, fixed Johnsen typo ### Calculate tortuosity invtau = np.zeros(int(len(self.dz))) b = 0.25 # Tortuosity parameter invtau[self.rho < RHO_I / np.sqrt(b)] = 1.0 - ( b * (self.rho[self.rho < RHO_I / np.sqrt(b)] / RHO_I))**2 invtau[self.rho >= RHO_I / np.sqrt(b)] = 0.0 ### Set diffusivity for each isotope if self.c['iso'] == '18': D = m * pz * invtau * Da_18 * (1 / self.rho - 1 / RHO_I) / (R * self.Tz * alpha_18_z) D = D + 1.5e-15 self.del_z = transient_solve_TR(z_edges_vec, z_P_vec, nt, self.dt, D, phi_0, nz_P, nz_fv, phi_s, self.rho) elif self.c['iso'] == 'D': D = m * pz * invtau * Da_D * (1 / self.rho - 1 / RHO_I) / (R * self.Tz * alpha_D_z) D[D <= 0.0] = 1.0e-20 self.del_z = transient_solve_TR(z_edges_vec, z_P_vec, nt, self.dt, D, phi_0, nz_P, nz_fv, phi_s, self.rho) elif self.c['iso'] == 'NoDiffusion': pass ### Solve for vertical isotope profile at this time step i self.del_z = np.concatenate(([self.del_s[iii]], self.del_z[:-1])) return self.del_z
def heatDiff(self, iii): ''' Heat diffusion function :param z: :param dz: :param Ts: :param rho: :returns self.Tz: :returns self.T10m: # thermal diffusivity: alpha = K_firn / (rho*c_firn) ''' nz_P = len(self.z) nz_fv = nz_P - 2 nt = 1 # z_edges_vec = self.z[1:-2] + self.dz[2:-1] / 2 # z_edges_vec = np.concatenate(([self.z[0]], z_edges_vec, [self.z[-1]])) # z_P_vec = self.z z_edges_vec1 = self.z[0:-1] + np.diff(self.z) / 2 z_edges_vec = np.concatenate(([self.z[0]], z_edges_vec1, [self.z[-1]])) z_P_vec = self.z phi_s = self.Tz[0] phi_0 = self.Tz K_ice = 9.828 * np.exp( -0.0057 * phi_0) # thermal conductivity, Cuffey and Paterson, eq. 9.2 (Yen 1981) # c_firn = 152.5 + 7.122 * phi_0 # specific heat, Cuffey and Paterson, eq. 9.1 (page 400) c_firn = CP_I # If you prefer a constant specific heat. ### Conductivity. Choose your favorite! ### # References are provided at the end of this script. # alpha_DAVIDCS_m2s = 18.3 / S_PER_YEAR # K_firn = alpha_DAVIDCS_m2s * self.rho * c_firn # K_firn[self.z>=20.0] = K_ice[self.z>=20.0] * (self.rho[self.z>=20.0]/RHO_I) ** (2 - 0.5 * (self.rho[self.z>=20.0]/RHO_I)) # Schwander 1997, eq. A11 # K_firn = K_ice * (self.rho/RHO_I) ** (2 - 0.5 * (self.rho/RHO_I)) # Schwander 1997, eq. A11 # K_firn = 2.22362 * (self.rho / 1000)**1.885 # Yen 1981, eq 34 w/ fixed K_ice (original) K_firn = K_ice * (self.rho / 1000)**1.885 # Yen 1981, modified for variable K_ice # K_firn = 0.021 + 2.5 * (self.rho/1000.)**2 # Anderson (1976) # K_firn = 0.0688 * np.exp(0.0088*phi_0 + 4.6682*self.rho) # Yen 1981, eq. 35. # K_firn = 0.138 - 1.01*(self.rho/1000) + 3.233*(self.rho/1000)**2 # Sturm, 1997.; rho < 0.6 # K_firn = 2.1e-2 + 4.2e-4 * self.rho + 2.2e-9 * (self.rho)**3 # Van Dusen 1929 (via C&P) # K_firn = (2 * K_ice * self.rho) / (3*RHO_I - self.rho) # Schwerdtfeger (via C&P) # K_firn = 3.e-6 * self.rho**2 - 1.06e-5 * self.rho + 0.024 # Riche and Schneebeli 2013 eq. 10 # k_firn = 0.0784 + 2.697 * (self.rho/1000.)**2 # Jiawen 1991 eq. 3 Gamma_P = K_firn # (new) # print('K_firn',K_firn) # Gamma_P = K_firn / (c_firn) # old) tot_rho = self.rho c_vol = self.rho * c_firn # print('c_vol',c_vol) self.Tz = transient_solve_TR(z_edges_vec, z_P_vec, nt, self.dt, Gamma_P, phi_0, nz_P, nz_fv, phi_s, tot_rho, c_vol) fT10m = interpolate.interp1d(self.z, self.Tz) # temp at 10m depth self.T10m = fT10m(10) if np.any(self.Tz > 273.17): print('WARNING: TEMPERATURE EXCEEDS MELTING TEMPERATURE') print('Maximal temperature was:', np.max(self.Tz), ' at layers:', np.where(self.Tz == np.max(self.Tz))) print( 'WARM TEMPERATURES HAVE BEEN SET TO 273.15; MODEL RUN IS CONTINUING' ) self.Tz[self.Tz >= 273.15] = 273.15 return self.Tz, self.T10m
def firn_air_diffusion(self,AirParams,iii): for k,v in list(AirParams.items()): setattr(self,k,v) nz_P = len(self.z) nz_fv = nz_P - 2 nt = 1 z_edges1 = self.z[0:-1] + np.diff(self.z) / 2 z_edges = np.concatenate(([self.z[0]], z_edges1, [self.z[-1]])) z_P_vec = self.z # if (iii>100 and iii<110): # print('z_P',z_P_vec[0:5]) # print('len p', len(z_P_vec)) # print('edges',z_edges[0:5]) # print('len edges',len(z_edges)) # input('enter') # phi_s = self.Ts[iii] phi_s = self.Gz[0] phi_0 = self.Gz # K_ice = 9.828 * np.exp(-0.0057 * phi_0) # K_firn = K_ice * (self.rho / 1000) ** (2 - 0.5 * (self.rho / 1000)) self.rho_co, self.por_co, self.por_tot, self.por_cl, self.por_op, self.bcoRho, self.LIDRho = self.porosity() # self.air_pressure_old = np.copy(self.air_pressure) porosity_old = (RHO_I-self.rho_old)/RHO_I por_co1 = 1 - self.rho_co/RHO_I # Porosity at close-off alpha = 0.37 # constant determined in Goujon por_cl1 = np.zeros_like(porosity_old) por_cl1[porosity_old>0] = alpha*porosity_old[porosity_old>0]*(porosity_old[porosity_old>0]/por_co1)**(-7.6) ind = por_cl1>porosity_old por_cl1[ind] = porosity_old[ind] por_op_old = porosity_old - por_cl1 # Open Porosity self.air_volume_old = por_op_old * self.dz_old # self.air_volume_old = np.copy(self.air_volume) self.air_volume = self.por_op * self.dz volfrac = self.air_volume_old / self.air_volume # volfrac = np.concatenate(([volfrac[0]],volfrac)) self.air_pressure = (self.p_a*np.exp(M_AIR*GRAVITY*self.z/(R*self.Tz))) * volfrac - (self.p_a*np.exp(M_AIR*GRAVITY*self.z/(R*self.Tz))) # assume air pressure is atmos in entire column self.pressure_grad = np.gradient(self.air_pressure,self.z) self.z_co = min(self.z[self.rho>=(self.bcoRho)]) #close-off depth; bcoRho is mean close off density # self.z_co = min(self.z[self.rho>=(self.rho_co)]) #close-off depth; bcoRho is close off density # self.z_co = self.z[np.where(self.rho>=self.rho_co)[0][0]] #close-off depth; bcoRho is close off density self.LID = min(self.z[self.rho>=(self.LIDRho)]) #lock in depth; LIDRho is lock-in density print(self.LID) self.bdot_t = self.bdot[iii] self.diffu, self.d_eddy = self.diffusivity() # ij = np.where(self.diffu<=1e-20)[0][0] # print('Diffu zero',self.z[ij]) airdict = { 'd_eddy': self.d_eddy, 'por_op': self.por_op, 'Tz': self.Tz, 'deltaM': self.deltaM, 'omega': self.omega, 'dz': self.dz, 'rho': self.rho, 'gravity': self.cg['gravity'], 'thermal': self.cg['thermal'], 'air_pressure': self.air_pressure, 'pressure_grad': self.pressure_grad, 'z': self.z, 'dt': self.dt, 'z_co': self.z_co, 'p_a': self.p_a, 'por_tot': self.por_tot, 'por_cl': self.por_cl, 'w_firn': self.w_firn, 'advection_type': self.cg['advection_type'], 'iii': iii, 'gaschoice': self.gaschoice } msk = np.where(self.z>self.z_co)[0][0] self.Gz, w_p = transient_solve_TR(z_edges, z_P_vec, nt, self.dt, self.diffu, phi_0, nz_P, nz_fv, phi_s, self.rho, airdict) self.Gz = np.concatenate(([self.Gs[iii]], self.Gz[:-1])) ind_LID = np.where(self.z>=self.LID)[0] self.gas_age[self.gas_age>0] = self.gas_age[self.gas_age>0] + self.dt/S_PER_YEAR self.gas_age = np.concatenate(([0], self.gas_age[:-1])) self.gas_age[ind_LID[0]] = 15.0 ii2 = np.where((self.z>self.LID) & (self.gas_age==0))[0] self.gas_age[ii2] = 15 # print('diffu',self.diffu[0:10]) return self.Gz, self.diffu, w_p, self.gas_age