def heatcap(depth, latitude, temperature, salinity) -> np.ndarray: """ Calculates the heat capacity of sea water. Parameters: depth: The depth(s) in meters latitude: The latitude(s) in degrees North temperature: The temperatures(s) in Celsius salinity: The salinity (unitless) """ press = __calc_pressure(depth, latitude) heatcap = seawater.cp(salinity, temperature, press) return np.array(heatcap)
# empta = empt * 1. emptp = empt * 1. empti = empt * 1. # # Compute density rhon[t, ...] = eosNeutral(tost.data, sost.data) - 1000. rhon[t, ...].mask = maski rhon[t, ...] = maskVal(rhon[t, ...], valmask) rhonl = rhon.data[t, ...] # Compute buoyancy/density flux as mass fluxes in kg/m2/s (SI units) # convwf : kg/m2/s = mm/s -> m/s convwf = 1.e-3 pres = tost.data * 0. denflxh[t, ...] = (-sw.alpha(sost.data, tost.data, pres) / sw.cp(sost.data, tost.data, pres)) * heft.data if empsw == 0: denflxw[t, ...] = (rhonl + 1000.) * sw.beta( sost.data, tost.data, pres) * sost.data * empt.data * convwf else: denflxw[t, ...] = (rhonl + 1000.) * sw.beta( sost.data, tost.data, pres) * empt.data * convwf denflx[t, ...] = denflxh[t, ...] + denflxw[t, ...] denflx[t, ...].mask = maski denflxh[t, ...].mask = maski denflxw[t, ...].mask = maski denflx[t, ...] = maskVal(denflx[t, ...], valmask) denflxh[t, ...] = maskVal(denflxh[t, ...], valmask) denflxw[t, ...] = maskVal(denflxw[t, ...], valmask) dflxh = denflxh.data[t, :, :] dflxw = denflxw.data[t, :, :]
def test(fileout='python-test.txt'): r"""Copy of the Matlab test. Modifications: Phil Morgan 03-12-12. Lindsay Pender, Converted to ITS-90. """ f = open(fileout, 'w') asterisks = '*' * 76 f.write(asterisks) f.write('\n TEST REPORT ') f.write('\n') f.write('\n SEA WATER LIBRARY %s' % sw.__version__) f.write('\n') # Show some info about this Python. f.write('\npython version: %s' % sys.version) f.write('\n on %s computer %s' % (uname()[0], uname()[-1])) f.write('\n') f.write('\n') f.write(asctime(localtime())) f.write('\n') f.write('\n') # Test main module ptmp. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: ptmp') f.write('\n** and SUB-MODULE: adtg') f.write('\n%s' % asterisks) f.write('\n') f.write('\n') # Test 1 - data from Unesco 1983 p45. T = np.array([[0, 0, 0, 0, 0, 0], [10, 10, 10, 10, 10, 10], [20, 20, 20, 20, 20, 20], [30, 30, 30, 30, 30, 30], [40, 40, 40, 40, 40, 40]]) T = T / 1.00024 S = np.array([[25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35]]) P = np.array([[0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000]]) Pr = np.array([0, 0, 0, 0, 0, 0]) UN_ptmp = np.array([[0, -0.3061, -0.9667, 0, -0.3856, -1.0974], [10, 9.3531, 8.4684, 10, 9.2906, 8.3643], [20, 19.0438, 17.9426, 20, 18.9985, 17.8654], [30, 28.7512, 27.4353, 30, 28.7231, 27.3851], [40, 38.4607, 36.9254, 40, 38.4498, 36.9023]]) PT = sw.ptmp(S, T, P, Pr) * 1.00024 # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from UNESCO 1983 ') f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p45)') f.write('\n%s' % asterisks) f.write('\n') m, n = S.shape # TODO: so many loops there must be a better way. for icol in range(0, n): f.write('\n Sal Temp Press PTMP ptmp') f.write('\n (psu) (C) (db) (C) (C)\n') result = np.vstack( (S[:, icol], T[:, icol], P[:, icol], UN_ptmp[:, icol], PT[:, icol])) for iline in range(0, m): f.write(" %4.0f %4.0f %5.0f %8.4f %11.5f\n" % tuple(result[:, iline])) # Test main module svan. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: svan') f.write('\n** and SUB-MODULE: dens dens0 smow seck pden ptmp') f.write('\n%s' % asterisks) # Test data FROM: Unesco Tech. Paper in Marine Sci. No. 44, p22. s = np.array([0, 0, 0, 0, 35, 35, 35, 35]) p = np.array([0, 10000, 0, 10000, 0, 10000, 0, 10000]) t = np.array([0, 0, 30, 30, 0, 0, 30, 30]) / 1.00024 UN_svan = np.array( [2749.54, 2288.61, 3170.58, 3147.85, 0.0, 0.00, 607.14, 916.34]) SVAN = sw.svan(s, t, p) # DISPLAY RESULTS f.write('\n') f.write('\n%s' % asterisks) f.write('\n') f.write('\nComparison of accepted values from UNESCO 1983') f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p22)') f.write('\n%s' % asterisks) f.write('\n') f.write('\n Sal Temp Press SVAN svan') f.write('\n (psu) (C) (db) (1e-8*m3/kg) (1e-8*m3/kg)\n') result = np.vstack([s, t, p, UN_svan, 1e+8 * SVAN]) for iline in range(0, len(SVAN)): f.write(" %4.0f %4.0f %5.0f %11.2f %11.3f\n" % tuple(result[:, iline])) # Test main module salt. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: salt') f.write('\n** and SUB-MODULE: salrt salrp sals') f.write('\n%s' % asterisks) f.write('\n') # Test 1 - data from Unesco 1983 p9. R = np.array([1, 1.2, 0.65]) # cndr = R. T = np.array([15, 20, 5]) / 1.00024 P = np.array([0, 2000, 1500]) #Rt = np.array([ 1, 1.0568875, 0.81705885]) UN_S = np.array([35, 37.245628, 27.995347]) S = sw.salt(R, T, P) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from UNESCO 1983 ') f.write('\n(Unesco Tech. Paper in Marine Sci. No. 44, p9)') f.write('\n%s' % asterisks) f.write('\n') f.write('\n Temp Press R S salt') f.write('\n (C) (db) (no units) (psu) (psu)\n') table = np.vstack([T, P, R, UN_S, S]) m, n = table.shape for iline in range(0, n): f.write(" %4.0f %4.0f %8.2f %11.6f %14.7f\n" % tuple(table[:, iline])) # Test main module cndr. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: cndr') f.write('\n** and SUB-MODULE: salds') f.write('\n%s' % asterisks) # Test 1 - data from Unesco 1983 p9. T = np.array([0, 10, 0, 10, 10, 30]) / 1.00024 P = np.array([0, 0, 1000, 1000, 0, 0]) S = np.array([25, 25, 25, 25, 40, 40]) UN_R = np.array( [0.498088, 0.654990, 0.506244, 0.662975, 1.000073, 1.529967]) R = sw.cndr(S, T, P) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from UNESCO 1983 ') f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p14)') f.write('\n%s' % asterisks) f.write('\n') f.write('\n') f.write('\n Temp Press S cndr cndr') f.write('\n (C) (db) (psu) (no units) (no units)\n') table = np.vstack([T, P, S, UN_R, R]) m, n = table.shape for iline in range(0, n): f.write(" %4.0f %4.0f %8.6f %11.6f %14.8f\n" % tuple(table[:, iline])) # Test main module depth. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: depth') f.write('\n%s' % asterisks) # Test data - matrix "pressure", vector "lat" Unesco 1983 data p30. lat = np.array([0, 30, 45, 90]) P = np.array([[500, 500, 500, 500], [5000, 5000, 5000, 5000], [10000, 10000, 10000, 10000]]) UN_dpth = np.array([[496.65, 496.00, 495.34, 494.03], [4915.04, 4908.56, 4902.08, 4889.13], [9725.47, 9712.65, 9699.84, 9674.23]]) dpth = sw.dpth(P, lat) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from Unesco 1983 ') f.write('\n(Unesco Tech. Paper in Marine Sci. No. 44, p28)') f.write('\n%s' % asterisks) f.write('\n') f.write('\n') for irow in range(0, 3): f.write('\n Lat Press DPTH dpth') f.write('\n (degree) (db) (meter) (meter)\n') table = np.vstack([lat, P[irow, :], UN_dpth[irow, :], dpth[irow, :]]) m, n = table.shape for iline in range(0, n): f.write(" %6.3f %6.0f %8.2f %8.3f\n" % tuple(table[:, iline])) # Test main module fp. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: fp') f.write('\n%s' % asterisks) # Test 1 - UNESCO data p.30. S = np.array([[5, 10, 15, 20, 25, 30, 35, 40], [5, 10, 15, 20, 25, 30, 35, 40]]) P = np.array([[0, 0, 0, 0, 0, 0, 0, 0], [500, 500, 500, 500, 500, 500, 500, 500]]) UN_fp = np.array( [[-0.274, -0.542, -0.812, -1.083, -1.358, -1.638, -1.922, -2.212], [-0.650, -0.919, -1.188, -1.460, -1.735, -2.014, -2.299, -2.589]]) FP = sw.fp(S, P) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from UNESCO 1983 ') f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p30)') f.write('\n%s' % asterisks) f.write('\n') f.write('\n') for irow in range(0, 2): f.write('\n Sal Press fp fp') f.write('\n (psu) (db) (C) (C)\n') table = np.vstack( [S[irow, :], P[irow, :], UN_fp[irow, :], FP[irow, :]]) m, n = table.shape for iline in range(0, n): f.write(" %4.0f %5.0f %8.3f %11.4f\n" % tuple(table[:, iline])) # Test main module cp. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: cp') f.write('\n%s' % asterisks) # Test 1. # Data from Pond and Pickard Intro. Dynamical Oceanography 2nd ed. 1986 T = np.array([[0, 0, 0, 0, 0, 0], [10, 10, 10, 10, 10, 10], [20, 20, 20, 20, 20, 20], [30, 30, 30, 30, 30, 30], [40, 40, 40, 40, 40, 40]]) / 1.00024 S = np.array([[25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35]]) P = np.array([[0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000]]) UN_cp = np.array([[4048.4, 3896.3, 3807.7, 3986.5, 3849.3, 3769.1], [4041.8, 3919.6, 3842.3, 3986.3, 3874.7, 3804.4], [4044.8, 3938.6, 3866.7, 3993.9, 3895.0, 3828.3], [4049.1, 3952.0, 3883.0, 4000.7, 3909.2, 3844.3], [4051.2, 3966.1, 3905.9, 4003.5, 3923.9, 3868.3]]) CP = sw.cp(S, T, P) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from UNESCO 1983 ') f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p37)') f.write('\n%s' % asterisks) f.write('\n') m, n = S.shape f.write('\n') for icol in range(0, n): f.write('\n Sal Temp Press Cp cp') f.write('\n (psu) (C) (db) (J/kg.C) (J/kg.C)\n') result = np.vstack( [S[:, icol], T[:, icol], P[:, icol], UN_cp[:, icol], CP[:, icol]]) for iline in range(0, m): f.write(" %4.0f %4.0f %5.0f %8.1f %11.2f\n" % tuple(result[:, iline])) # Test main module svel. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: svel') f.write('\n%s' % asterisks) # Test 1. # Data from Pond and Pickard Intro. Dynamical Oceanography 2nd ed. 1986 T = np.array([[0, 0, 0, 0, 0, 0], [10, 10, 10, 10, 10, 10], [20, 20, 20, 20, 20, 20], [30, 30, 30, 30, 30, 30], [40, 40, 40, 40, 40, 40]]) / 1.00024 S = np.array([[25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35]]) P = np.array([[0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000]]) UN_svel = np.array([[1435.8, 1520.4, 1610.4, 1449.1, 1534.0, 1623.2], [1477.7, 1561.3, 1647.4, 1489.8, 1573.4, 1659.0], [1510.3, 1593.6, 1676.8, 1521.5, 1604.5, 1687.2], [1535.2, 1619.0, 1700.6, 1545.6, 1629.0, 1710.1], [1553.4, 1638.0, 1719.2, 1563.2, 1647.3, 1727.8]]) SVEL = sw.svel(S, T, P) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from UNESCO 1983 ') f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p50)') f.write('\n%s' % asterisks) f.write('\n') m, n = SVEL.shape f.write('\n') for icol in range(0, n): f.write('\n Sal Temp Press SVEL svel') f.write('\n (psu) (C) (db) (m/s) (m/s)\n') result = np.vstack([ S[:, icol], T[:, icol], P[:, icol], UN_svel[:, icol], SVEL[:, icol] ]) for iline in range(0, m): f.write(" %4.0f %4.0f %5.0f %8.1f %11.3f\n" % tuple(result[:, iline])) # Test submodules alpha beta aonb. f.write('\n%s' % asterisks) f.write('\n** and SUB-MODULE: alpha beta aonb') f.write('\n%s' % asterisks) # Data from McDouogall 1987. s = 40 PT = 10 p = 4000 beta_lit = 0.72088e-03 aonb_lit = 0.34763 alpha_lit = aonb_lit * beta_lit BETA = sw.beta(s, PT, p, pt=True) ALPHA = sw.alpha(s, PT, p, pt=True) AONB = sw.aonb(s, PT, p, pt=True) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from MCDOUGALL 1987 ') f.write('\n%s' % asterisks) f.write('\n') f.write('\n') f.write('\n Sal Temp Press BETA beta') f.write('\n (psu) (C) (db) (psu^-1) (psu^-1)\n') table = np.hstack([s, PT, p, beta_lit, BETA]) f.write(" %4.0f %4.0f %5.0f %11.4e %11.5e\n" % tuple(table)) f.write('\n Sal Temp Press AONB aonb') f.write('\n (psu) (C) (db) (psu C^-1) (psu C^-1)\n') table = np.hstack([s, PT, p, aonb_lit, AONB]) f.write(" %4.0f %4.0f %5.0f %8.5f %11.6f\n" % tuple(table)) f.write('\n Sal Temp Press ALPHA alpha') f.write('\n (psu) (C) (db) (psu^-1) (psu^-1)\n') table = np.hstack([s, PT, p, alpha_lit, ALPHA]) f.write(" %4.0f %4.0f %5.0f %11.4e %11.4e\n" % tuple(table)) # Test main moduleS satO2 satN2 satAr. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: satO2 satN2 satAr') f.write('\n%s' % asterisks) f.write('\n') # Data from Weiss 1970. T = np.array([[-1, -1], [10, 10], [20, 20], [40, 40]]) / 1.00024 S = np.array([[20, 40], [20, 40], [20, 40], [20, 40]]) lit_O2 = np.array([[9.162, 7.984], [6.950, 6.121], [5.644, 5.015], [4.050, 3.656]]) lit_N2 = np.array([[16.28, 14.01], [12.64, 11.01], [10.47, 9.21], [7.78, 6.95]]) lit_Ar = np.array([[0.4456, 0.3877], [0.3397, 0.2989], [0.2766, 0.2457], [0.1986, 0.1794]]) O2 = sw.satO2(S, T) N2 = sw.satN2(S, T) Ar = sw.satAr(S, T) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from Weiss, R.F. 1979 ') f.write('\n"The solubility of nitrogen, oxygen and argon in water') f.write('\n and seawater." Deep-Sea Research., 1970, Vol 17, pp721-735.') f.write('\n%s' % asterisks) f.write('\n') m, n = S.shape f.write('\n') for icol in range(0, n): f.write('\n Sal Temp O2 satO2') f.write('\n (psu) (C) (ml/l) (ml/l)\n') result = np.vstack( [S[:, icol], T[:, icol], lit_O2[:, icol], O2[:, icol]]) for iline in range(0, m): f.write(" %4.0f %4.0f %8.2f %9.3f\n" % tuple(result[:, iline])) for icol in range(0, n): f.write('\n Sal Temp N2 satN2') f.write('\n (psu) (C) (ml/l) (ml/l)\n') result = np.vstack( [S[:, icol], T[:, icol], lit_N2[:, icol], N2[:, icol]]) for iline in range(0, m): f.write(" %4.0f %4.0f %8.2f %9.3f\n" % tuple(result[:, iline])) for icol in range(0, n): f.write('\n Sal Temp Ar satAr') f.write('\n (psu) (C) (ml/l) (ml/l)\n') result = np.vstack( [S[:, icol], T[:, icol], lit_Ar[:, icol], Ar[:, icol]]) for iline in range(0, m): f.write(" %4.0f %4.0f %8.4f %9.4f\n" % tuple(result[:, iline]))
def makeHeatContent(salt,temp,destMask,thetao,pressure): """ The makeHeatContent() function takes 3D (not temporal) arguments and creates heat content which is then mapped to a destination grid and written to a specified variable Author: Paul J. Durack : [email protected] : @durack1. Created on Tue Nov 24 15:34:30 2015. Inputs: ------ - salt(lev,lat,lon) - 3D array. - temp(lev,lat,lon) - 3D array either in-situ or potential temperature. - destGridArray(str) - 2D array with valid grid and mask. - thetao(bool) - boolean value specifying either in-situ or potential temperature arrays provided. - pressure(bool) - boolean value specifying whether lev-coordinate is pressure (dbar) or depth (m). Usage: ------ >>> from oceanLib import makeHeatContent >>> makeHeatContent(salt,temp,destGridArray,thetao=True,pressure=False) Notes: ----- - PJD 24 Nov 2015 - Migrated into new oceanLib from heatContentLib - TODO: Better deal with insitu vs thetao variables - TODO: """ # Remap variables to short names #print salt.getAxisIds() s = salt(squeeze=1) ; # Trim off singleton time dimension #print s.getAxisIds() t = temp(squeeze=1) mask = destMask #print mask.getAxisIds() del(salt,temp,destMask) ; gc.collect() depthInd = 0 ; # Set depth coordinate index #print 's: ',s.min(),s.max() #print 't: ',t.min(),t.max() # Fix out of bounds values t = mv.where(t<-2.6,-2.6,t) ; # Fix for NaN values # Calculate pressure - inputs depth & lat # Create z-coordinate from salinity input if not pressure: zCoord = s.getAxis(depthInd) ; # Assume time,depth,latitude,longitude grid yCoord = s.getAxis(depthInd+1) yCoord = tile(yCoord,(s.shape[depthInd+2],1)).transpose() depthLevels = tile(zCoord.getValue(),(s.shape[depthInd+2],s.shape[depthInd+1],1)).transpose() pressureLevels = sw.pres(np.array(depthLevels),np.array(yCoord)) del(zCoord,yCoord,depthLevels) ; gc.collect() else: pressureLevels = s.getAxis(depthInd) #print pressureLevels.getValue() pressureLevels = transpose(tile(pressureLevels,(s.shape[depthInd+2],s.shape[depthInd+1],1))) pressureLevels = cdm.createVariable(pressureLevels,id='pressureLevels') pressureLevels.setAxis(0,s.getAxis(depthInd)) pressureLevels.setAxis(1,s.getAxis(depthInd+1)) pressureLevels.setAxis(2,s.getAxis(depthInd+2)) pressureLevels.units_long = 'decibar (pressure)' pressureLevels.positive = 'down' pressureLevels.long_name = 'sea_water_pressure' pressureLevels.standard_name = 'sea_water_pressure' pressureLevels.units = 'decibar' pressureLevels.axis = 'Z' #print 'pres: ',pressureLevels.min(),pressureLevels.max() #print pressureLevels.shape #print s.shape #print t.shape #print mask.shape # Calculate temp,rho,cp - inputs temp,salt,pressure if thetao: # Process potential temperature to in-situ temp = sw.temp(np.array(s),np.array(t),np.array(pressureLevels)); # units degrees C rho = sw.dens(np.array(s),np.array(temp),np.array(pressureLevels)) ; # units kg m-3 cp = sw.cp(np.array(s),np.array(temp),np.array(pressureLevels)) ; # units J kg-1 C-1 # Correct instances of NaN values and fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset temp = scrubNaNAndMask(temp,s) rho = scrubNaNAndMask(rho,s) cp = scrubNaNAndMask(cp,s) #print 'temp: ',temp.min(),temp.max() #print 'rho: ',rho.min(),rho.max() #print 'cp: ',cp.min(),cp.max() # Calculate heatContent - inputs temp,rho,cp heatContent = np.array(temp)*np.array(rho)*np.array(cp) ; # units J # Correct instances of NaN values and fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset heatContent = scrubNaNAndMask(heatContent,s) #print 'hc: ',heatContent.min(),heatContent.max() # Interpolate to standard levels - inputs heatContent,levels newDepth = np.array([5,10,20,30,40,50,75,100,125,150,200,300,500,700,1000,1500,1800,2000]).astype('f'); newDepth_bounds = np.array([[0,5],[5,10],[10,20],[20,30],[30,40],[40,50],[50,75],[75,100],[100,125],[125,150], [150,200],[200,300],[300,500],[500,700],[700,1000],[1000,1500],[1500,1800],[1800,2000]]).astype('f') # Interpolate to standard levels #print heatContent.shape #print heatContent.getAxisIds() #print pressureLevels.shape #print pressureLevels.getAxisIds() # Reset variable axes heatContent.setAxis(0,s.getAxis(0)) #heatContent.setAxis(1,s.getAxis(1)) #heatContent.setAxis(2,s.getAxis(2)) pdb.set_trace() heatContent.setGrid(s.getGrid()) #print heatContent.shape #print heatContent.getAxisIds() #print pressureLevels.shape #print pressureLevels.getAxisIds() heatContent_depthInterp = cdu.linearInterpolation(heatContent,pressureLevels,levels=newDepth) # Fix bounds newDepth = heatContent_depthInterp.getAxis(0) newDepth.setBounds(newDepth_bounds) del(newDepth_bounds) newDepth.id = 'depth2' newDepth.units_long = 'decibar (pressure)' newDepth.positive = 'down' newDepth.long_name = 'sea_water_pressure' newDepth.standard_name = 'sea_water_pressure' newDepth.units = 'decibar' newDepth.axis = 'Z' #print 'hc_interp:',heatContent_depthInterp.min(),heatContent_depthInterp.max() # Integrate to 700 dbar - inputs heatContent heatContent_depthInteg = cdu.averager(heatContent_depthInterp[0:14,...],axis=0,weights='weighted',action='sum')(squeeze=1) # Calculate depth-weighted-integrated thetao # Assign all axis info #print heatContent_depthInteg.shape pdb.set_trace() # Interpolate in x,y - inputs heatContent #tmp1 = heatContent_depthInteg.regrid(mask.getGrid(),regridTool='esmf',regridMethod='linear') ; # Use defaults - ,coordSys='deg',diag = {},periodicity=1) tmp1 = heatContent_depthInteg.regrid(mask,regridTool='esmf',regridMethod='linear') ; # Use defaults - ,coordSys='deg',diag = {},periodicity=1) #print tmp1.shape tmp1 = mv.where(tmp1<0,0,tmp1) ; # Fix for negative values # Infill - inputs heatContent # Create inputs for interpolation points = np.zeros([(mask.shape[0]*mask.shape[1]),2]) ; # Create 25380 vectors of lon/lat latcounter = 0 ; loncounter = 0 for count,data in enumerate(points): if not np.mod(count,180) and not count == 0: latcounter = latcounter + 1 loncounter = 0 points[count,0] = mask.getLatitude().getValue()[latcounter] points[count,1] = mask.getLongitude().getValue()[loncounter] loncounter = loncounter + 1 del(count,data,latcounter,loncounter); gc.collect() valid = np.logical_not(tmp1.mask) ; # Get inverted-logic boolean mask from variable if valid.size == 1: print '** No valid mask found, skipping **' return valid = valid.flatten() ; # Flatten 2D to 1D #maskFilled = mask(tmp,points,valid) interpolant = interpolate.LinearNDInterpolator(points[valid,:],np.array(tmp1.flatten())[valid]) ; # Create interpolant maskFill = interpolant(points[:,0].squeeze(),points[:,1].squeeze()) ; # Use interpolant to create filled matrix maskFill = np.reshape(maskFill,mask.shape) ; # Resize to original dimensions # Fix issues with interpolant tmp2 = mv.where(np.isnan(maskFill),1e+20,maskFill) ; # Fix for NaN values tmp2 = mv.where(tmp2>tmp1.max(),0,tmp2) ; # Fix for max values tmp2 = mv.where(tmp2<tmp1.min(),0,tmp2) ; # Fix for min values tmp = mv.masked_where(mask.mask,tmp2) #print tmp.shape # Redress variable heatContent = cdm.createVariable([tmp],id='heatContent') depthInt = cdm.createAxis([350],id='depth') depthInt.setBounds(np.array([0,700])) depthInt.units_long = 'decibar (pressure)' depthInt.positive = 'down' depthInt.long_name = 'sea_water_pressure' depthInt.standard_name = 'sea_water_pressure' depthInt.units = 'decibar' depthInt.axis = 'Z' heatContent.setAxis(0,depthInt) heatContent.setAxis(1,mask.getAxis(0)) heatContent.setAxis(2,mask.getAxis(1)) heatContent.units_long = 'Joules' heatContent.long_name = 'sea_water_heat_content' heatContent.standard_name = 'sea_water_heat_content' heatContent.units = 'J' return heatContent ; #,tmp1 ; # 0-700 dbar standard masked variable
def makeSteric(salinity,salinityChg,temp,tempChg,outFileName,thetao,pressure): """ The makeSteric() function takes 3D (not temporal) arguments and creates heat content and steric fields which are written to a specified outfile Author: Paul J. Durack : [email protected] : @durack1. Created on Thu Jul 18 13:03:37 2013. Inputs: ------ - salinity(lev,lat,lon) - 3D array for the climatological period. - salinityChg(lev,lat,lon) - 3D array for the temporal change period. - temp(lev,lat,lon) - 3D array for the climatological period either in-situ or potential temperature. - tempChg(lev,lat,lon) - 3D array for the temporal change period as with temp, either in-situ or potential temperature. - outFileName(str) - output filename with full path specified. - thetao(bool) - boolean value specifying either in-situ or potential temperature arrays provided. - pressure(bool) - boolean value specifying whether lev-coordinate is pressure (dbar) or depth (m). Usage: ------ >>> from makeStericLib import makeSteric >>> makeSteric(salinity,salinityChg,thetao,thetaoChg,'outfile.nc',True,False) Notes: ----- - PJD 18 Jul 2013 - Validated Ishii v6.13 data against WOA94 - checks out ok. Units: dyn decimeter compared to http://www.nodc.noaa.gov/OC5/WOA94/dyn.html uses cm (not decimeter; x 10) - PJD 18 Jul 2013 - Added attribute scrub to incoming variables (so,so_chg,temp,temp_chg) to maintain output consistency - PJD 22 Jul 2013 - Added name attributes to so and temp variables, added units to so_chg - PJD 22 Jul 2013 - removed duplicated code by converting repetition to function scrubNaNAndMask - PJD 23 Jul 2013 - Further cleaned up so,so_chg,temp,temp_chg outputs specifying id/name attributes - PJD 5 Aug 2013 - Updated python-seawater library to version 3.3.1 from github repo, git clone http://github.com/ocefpaf/python-seawater, python setup.py install --user - PJD 7 Aug 2013 - FIXED: thetao rather than in-situ temperature propagating throughout calculations - PJD 7 Aug 2013 - Replaced looping with 3D gpan - PJD 7 Aug 2013 - Further code duplication cleanup - PJD 8 Aug 2013 - FIXED: scrubNanAndMask function type/mask/grid issue - encase sw arguments in np.array() (attempt to strip cdms fluff) - PJD 8 Aug 2013 - FIXED: removed depth variable unit edits - not all inputs are depth (m) - PJD 15 Aug 2013 - Increased interpolated field resolution [200,300,500,700,1000,1500,1800,2000] - [5,10,20,30,40,50,75,100,125,150,200, ...] - PJD 18 Aug 2013 - AR5 hard coded rho=1020,cp=4187 == 4.3e6 vs Ishii 1970 rho.mean=1024,cp.mean=3922 == 4.1e6 ~5% too high - PJD 13 Jan 2014 - Corrected steric_height_anom and steric_height_thermo_anom to true anomaly fields, needed to remove climatology - PJD 3 May 2014 - Turned off thetao conversion, although convert to numpy array rather than cdms2 transient variable - PJD 13 Oct 2014 - Added seawater_library_version as a global attribute - PJD 13 Oct 2014 - FIXED: bug with calculation of rho_halo variable was calculating gpan - PJD 13 Oct 2014 - Added alternate calculation of halosteric anomaly (direct salinity anomaly calculation, rather than total-thermosteric) - PJD 13 Oct 2014 - Added makeSteric_version as a global attribute - TODO: Better deal with insitu vs thetao variables - TODO: Query Charles on why *.name attributes are propagating - TODO: validate outputs and compare to matlab versions - 10e-7 errors. """ # Remap all variables to short names so = salinity so_chg = salinityChg temp = temp temp_chg = tempChg del(salinity,salinityChg,tempChg) ; gc.collect() # Strip attributes to maintain consistency between datasets for count,x in enumerate(so.attributes.keys()): delattr(so,x) #print so.listattributes() ; # Print remaining attributes for count,x in enumerate(so_chg.attributes.keys()): delattr(so_chg,x) for count,x in enumerate(temp.attributes.keys()): delattr(temp,x) for count,x in enumerate(temp_chg.attributes.keys()): delattr(temp_chg,x) del(count,x) # Create z-coordinate from salinity input if not pressure: z_coord = so.getAxis(0) y_coord = so.getAxis(1) y_coord = tile(y_coord,(so.shape[2],1)).transpose() depth_levels = tile(z_coord.getValue(),(so.shape[2],so.shape[1],1)).transpose() pressure_levels = sw.pres(np.array(depth_levels),np.array(y_coord)) del(z_coord,y_coord,depth_levels) ; gc.collect() else: pressure_levels = so.getAxis(0) pressure_levels = transpose(tile(pressure_levels,(so.shape[2],so.shape[1],1))) pressure_levels = cdm.createVariable(pressure_levels,id='pressure_levels') pressure_levels.setAxis(0,so.getAxis(0)) pressure_levels.setAxis(1,so.getAxis(1)) pressure_levels.setAxis(2,so.getAxis(2)) pressure_levels.id = 'pressure_levels' pressure_levels.units_long = 'decibar (pressure)' pressure_levels.positive = 'down' pressure_levels.long_name = 'sea_water_pressure' pressure_levels.standard_name = 'sea_water_pressure' pressure_levels.units = 'decibar' pressure_levels.axis = 'Z' # Cleanup depth axis attributes depth = so.getAxis(0) depth.id = 'depth' depth.name = 'depth' depth.long_name = 'depth' depth.standard_name = 'depth' depth.axis = 'Z' so.setAxis(0,depth) so_chg.setAxis(0,depth) temp.setAxis(0,depth) temp_chg.setAxis(0,depth) del(depth) # Convert using python-seawater library (v3.3.1 - 130807) if thetao: # Process potential temperature to in-situ - default conversion sets reference pressure to 0 (surface) #temp_chg = sw.temp(np.array(so),np.array(temp_chg),np.array(pressure_levels)); # units degrees C #temp = sw.temp(np.array(so),np.array(temp),np.array(pressure_levels)); # units degrees C #temp_chg = sw.ptmp(np.array(so),np.array(temp_chg),np.array(pressure_levels),np.array(pressure_levels)); # units degrees C #temp = sw.ptmp(np.array(so),np.array(temp),np.array(pressure_levels),np.array(pressure_levels)); # units degrees C temp_chg = np.array(temp_chg); # units degrees C temp = np.array(temp); # units degrees C # Climatologies - rho,cp,steric_height rho = sw.dens(np.array(so),np.array(temp),np.array(pressure_levels)) ; # units kg m-3 cp = sw.cp(np.array(so),np.array(temp),np.array(pressure_levels)) ; # units J kg-1 C-1 steric_height = sw.gpan(np.array(so),np.array(temp),np.array(pressure_levels)) ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) # Halosteric - rho,cp ss = map(array,(so+so_chg)) rho_halo = sw.dens(np.array(ss),np.array(temp),np.array(pressure_levels)) ; # units kg m-3 cp_halo = sw.cp(np.array(ss),np.array(temp),np.array(pressure_levels)) ; # units J kg-1 C-1 tmp = sw.gpan(np.array(ss),np.array(temp),np.array(pressure_levels)) ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) steric_height_halo_anom2 = tmp-steric_height ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) # Full steric - steric_height tt = map(array,(temp+temp_chg)) tmp = sw.gpan(np.array(ss),np.array(tt),np.array(pressure_levels)) ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) steric_height_anom = tmp-steric_height ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) del(ss,tmp) ; gc.collect() # Thermosteric - rho,cp,steric_height rho_thermo = sw.dens(np.array(so),np.array(tt),np.array(pressure_levels)) ; # units kg m-3 cp_thermo = sw.cp(np.array(so),np.array(tt),np.array(pressure_levels)) ; # units J kg-1 C-1 tmp = sw.gpan(np.array(so),np.array(tt),np.array(pressure_levels)) ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) steric_height_thermo_anom = tmp-steric_height ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) del(tt,tmp) ; gc.collect() # Halosteric - steric_height steric_height_halo_anom = steric_height_anom-steric_height_thermo_anom ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) # Create heat content heat_content = np.array(temp)*np.array(rho)*np.array(cp) ; # units J heat_content_sanom = np.array(temp)*np.array(rho_halo)*np.array(cp_halo) ; # units J heat_content_tanom = np.array(temp_chg)*np.array(rho)*np.array(cp) ; # units J #heat_content_tanom = np.array(temp_chg)*np.array(1020)*np.array(4187) ; # units J - try hard-coded - AR5 numbers heat_content_tsanom = np.array(temp_chg)*np.array(rho_halo)*np.array(cp_halo) ; # units J # Correct all instances of NaN values and fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset temp = scrubNaNAndMask(temp,so) temp_chg = scrubNaNAndMask(temp_chg,so) rho = scrubNaNAndMask(rho,so) cp = scrubNaNAndMask(cp,so) rho_halo = scrubNaNAndMask(rho_halo,so) cp_halo = scrubNaNAndMask(cp_halo,so) rho_thermo = scrubNaNAndMask(rho_thermo,so) cp_thermo = scrubNaNAndMask(cp_thermo,so) steric_height = scrubNaNAndMask(steric_height,so) steric_height_anom = scrubNaNAndMask(steric_height_anom,so) steric_height_thermo_anom = scrubNaNAndMask(steric_height_thermo_anom,so) steric_height_halo_anom = scrubNaNAndMask(steric_height_halo_anom,so) steric_height_halo_anom2 = scrubNaNAndMask(steric_height_halo_anom2,so) heat_content = scrubNaNAndMask(heat_content,so) heat_content_sanom = scrubNaNAndMask(heat_content_sanom,so) heat_content_tanom = scrubNaNAndMask(heat_content_tanom,so) heat_content_tsanom = scrubNaNAndMask(heat_content_tsanom,so) # Recreate and redress variables so.id = 'so_mean' so.units = '1e-3' so_chg.id = 'so_chg' so_chg.units = '1e-3' temp = cdm.createVariable(temp,id='temp_mean') temp.setAxis(0,so.getAxis(0)) temp.setAxis(1,so.getAxis(1)) temp.setAxis(2,so.getAxis(2)) temp.units = 'degrees_C' temp_chg = cdm.createVariable(temp_chg,id='temp_chg') temp_chg.setAxis(0,so.getAxis(0)) temp_chg.setAxis(1,so.getAxis(1)) temp_chg.setAxis(2,so.getAxis(2)) temp_chg.units = 'degrees_C' rho = cdm.createVariable(rho,id='rho') rho.setAxis(0,so.getAxis(0)) rho.setAxis(1,so.getAxis(1)) rho.setAxis(2,so.getAxis(2)) rho.name = 'density_mean' rho.units = 'kg m^-3' cp = cdm.createVariable(cp,id='cp') cp.setAxis(0,so.getAxis(0)) cp.setAxis(1,so.getAxis(1)) cp.setAxis(2,so.getAxis(2)) cp.name = 'heat_capacity_mean' cp.units = 'J kg^-1 C^-1' rho_halo = cdm.createVariable(rho_halo,id='rho_halo') rho_halo.setAxis(0,so.getAxis(0)) rho_halo.setAxis(1,so.getAxis(1)) rho_halo.setAxis(2,so.getAxis(2)) rho_halo.name = 'density_mean_halo' rho_halo.units = 'kg m^-3' cp_halo = cdm.createVariable(cp_halo,id='cp_halo') cp_halo.setAxis(0,so.getAxis(0)) cp_halo.setAxis(1,so.getAxis(1)) cp_halo.setAxis(2,so.getAxis(2)) cp_halo.name = 'heat_capacity_mean_halo' cp_halo.units = 'J kg^-1 C^-1' rho_thermo = cdm.createVariable(rho_thermo,id='rho_thermo') rho_thermo.setAxis(0,so.getAxis(0)) rho_thermo.setAxis(1,so.getAxis(1)) rho_thermo.setAxis(2,so.getAxis(2)) rho_thermo.name = 'density_mean_thermo' rho_thermo.units = 'kg m^-3' cp_thermo = cdm.createVariable(cp_thermo,id='cp_thermo') cp_thermo.setAxis(0,so.getAxis(0)) cp_thermo.setAxis(1,so.getAxis(1)) cp_thermo.setAxis(2,so.getAxis(2)) cp_thermo.name = 'heat_capacity_mean_thermo' cp_thermo.units = 'J kg^-1 C^-1' steric_height = cdm.createVariable(steric_height,id='steric_height') steric_height.setAxis(0,so.getAxis(0)) steric_height.setAxis(1,so.getAxis(1)) steric_height.setAxis(2,so.getAxis(2)) steric_height.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_anom = cdm.createVariable(steric_height_anom,id='steric_height_anom') steric_height_anom.setAxis(0,so.getAxis(0)) steric_height_anom.setAxis(1,so.getAxis(1)) steric_height_anom.setAxis(2,so.getAxis(2)) steric_height_anom.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_thermo_anom = cdm.createVariable(steric_height_thermo_anom,id='steric_height_thermo_anom') steric_height_thermo_anom.setAxis(0,so.getAxis(0)) steric_height_thermo_anom.setAxis(1,so.getAxis(1)) steric_height_thermo_anom.setAxis(2,so.getAxis(2)) steric_height_thermo_anom.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_halo_anom = cdm.createVariable(steric_height_halo_anom,id='steric_height_halo_anom') steric_height_halo_anom.setAxis(0,so.getAxis(0)) steric_height_halo_anom.setAxis(1,so.getAxis(1)) steric_height_halo_anom.setAxis(2,so.getAxis(2)) steric_height_halo_anom.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_halo_anom2 = cdm.createVariable(steric_height_halo_anom2,id='steric_height_halo_anom2') steric_height_halo_anom2.setAxis(0,so.getAxis(0)) steric_height_halo_anom2.setAxis(1,so.getAxis(1)) steric_height_halo_anom2.setAxis(2,so.getAxis(2)) steric_height_halo_anom2.units = 'm^3 kg^-1 Pa (dynamic decimeter)' heat_content = cdm.createVariable(heat_content,id='heat_content') heat_content.setAxis(0,so.getAxis(0)) heat_content.setAxis(1,so.getAxis(1)) heat_content.setAxis(2,so.getAxis(2)) heat_content.units = 'J' heat_content_sanom = cdm.createVariable(heat_content_sanom,id='heat_content_sanom') heat_content_sanom.setAxis(0,so.getAxis(0)) heat_content_sanom.setAxis(1,so.getAxis(1)) heat_content_sanom.setAxis(2,so.getAxis(2)) heat_content_sanom.units = 'J' heat_content_tanom = cdm.createVariable(heat_content_tanom,id='heat_content_tanom') heat_content_tanom.setAxis(0,so.getAxis(0)) heat_content_tanom.setAxis(1,so.getAxis(1)) heat_content_tanom.setAxis(2,so.getAxis(2)) heat_content_tanom.units = 'J' heat_content_tsanom = cdm.createVariable(heat_content_tsanom,id='heat_content_tsanom') heat_content_tsanom.setAxis(0,so.getAxis(0)) heat_content_tsanom.setAxis(1,so.getAxis(1)) heat_content_tsanom.setAxis(2,so.getAxis(2)) heat_content_tsanom.units = 'J' # Create model-based depth index for subset target levels newdepth = np.array([5,10,20,30,40,50,75,100,125,150,200,300,500,700,1000,1500,1800,2000]).astype('f'); newdepth_bounds = np.array([[0,5],[5,10],[10,20],[20,30],[30,40],[40,50],[50,75],[75,100],[100,125],[125,150], [150,200],[200,300],[300,500],[500,700],[700,1000],[1000,1500],[1500,1800],[1800,2000]]).astype('f') #newdepth = np.array([200,300,500,700,1000,1500,1800,2000]).astype('f'); #newdepth_bounds = np.array([[0,200],[200,300],[300,500],[500,700],[700,1000],[1000,1500],[1500,1800],[1800,2000]]).astype('f') # Interpolate to depths so_depthInterp = cdu.linearInterpolation(so,pressure_levels,levels=newdepth) temp_depthInterp = cdu.linearInterpolation(temp,pressure_levels,levels=newdepth) steric_height_depthInterp = cdu.linearInterpolation(steric_height,pressure_levels,levels=newdepth) steric_height_anom_depthInterp = cdu.linearInterpolation(steric_height_anom,pressure_levels,levels=newdepth) steric_height_thermo_anom_depthInterp = cdu.linearInterpolation(steric_height_thermo_anom,pressure_levels,levels=newdepth) steric_height_halo_anom_depthInterp = cdu.linearInterpolation(steric_height_halo_anom,pressure_levels,levels=newdepth) steric_height_halo_anom2_depthInterp = cdu.linearInterpolation(steric_height_halo_anom2,pressure_levels,levels=newdepth) heat_content_sanom_depthInterp = cdu.linearInterpolation(heat_content_sanom,pressure_levels,levels=newdepth) heat_content_tanom_depthInterp = cdu.linearInterpolation(heat_content_tanom,pressure_levels,levels=newdepth) heat_content_tsanom_depthInterp = cdu.linearInterpolation(heat_content_tanom,pressure_levels,levels=newdepth) # Fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset temp_depthInterp = scrubNaNAndMask(temp_depthInterp,so_depthInterp) steric_height_depthInterp = scrubNaNAndMask(steric_height_depthInterp,so_depthInterp) steric_height_anom_depthInterp = scrubNaNAndMask(steric_height_anom_depthInterp,so_depthInterp) steric_height_thermo_anom_depthInterp = scrubNaNAndMask(steric_height_thermo_anom_depthInterp,so_depthInterp) steric_height_halo_anom_depthInterp = scrubNaNAndMask(steric_height_halo_anom_depthInterp,so_depthInterp) steric_height_halo_anom2_depthInterp = scrubNaNAndMask(steric_height_halo_anom2_depthInterp,so_depthInterp) heat_content_sanom_depthInterp = scrubNaNAndMask(heat_content_sanom_depthInterp,so_depthInterp) heat_content_tanom_depthInterp = scrubNaNAndMask(heat_content_tanom_depthInterp,so_depthInterp) heat_content_tsanom_depthInterp = scrubNaNAndMask(heat_content_tsanom_depthInterp,so_depthInterp) # Fix bounds newdepth = so_depthInterp.getAxis(0) newdepth.setBounds(newdepth_bounds) del(newdepth_bounds) newdepth.id = 'depth2' newdepth.units_long = 'decibar (pressure)' newdepth.positive = 'down' newdepth.long_name = 'sea_water_pressure' newdepth.standard_name = 'sea_water_pressure' newdepth.units = 'decibar' newdepth.axis = 'Z' # Assign corrected bounds so_depthInterp.setAxis(0,newdepth) temp_depthInterp.setAxis(0,newdepth) steric_height_depthInterp.setAxis(0,newdepth) steric_height_anom_depthInterp.setAxis(0,newdepth) steric_height_thermo_anom_depthInterp.setAxis(0,newdepth) steric_height_halo_anom_depthInterp.setAxis(0,newdepth) steric_height_halo_anom2_depthInterp.setAxis(0,newdepth) heat_content_sanom_depthInterp.setAxis(0,newdepth) heat_content_tanom_depthInterp.setAxis(0,newdepth) heat_content_tsanom_depthInterp.setAxis(0,newdepth) # Average/integrate to surface - configure bounds # Preallocate arrays so_depthAve = np.ma.zeros([len(newdepth),shape(so)[1],shape(so)[2]]) temp_depthAve = so_depthAve.copy() heat_content_sanom_depthInteg = so_depthAve.copy() heat_content_tanom_depthInteg = so_depthAve.copy() heat_content_tsanom_depthInteg = so_depthAve.copy() for count,depth in enumerate(newdepth): tmp = cdu.averager(so_depthInterp[0:(count+1),...],axis=0,weights='weighted',action='average') so_depthAve[count,] = tmp; tmp = cdu.averager(temp_depthInterp[0:(count+1),...],axis=0,weights='weighted',action='average') temp_depthAve[count,] = tmp; tmp = cdu.averager(heat_content_sanom_depthInterp[0:(count+1),...],axis=0,weights='weighted',action='sum') heat_content_sanom_depthInteg[count,] = tmp tmp = cdu.averager(heat_content_tanom_depthInterp[0:(count+1),...],axis=0,weights='weighted',action='sum') heat_content_tanom_depthInteg[count,] = tmp tmp = cdu.averager(heat_content_tsanom_depthInterp[0:(count+1),...],axis=0,weights='weighted',action='sum') heat_content_tsanom_depthInteg[count,] = tmp del(heat_content_tanom_depthInterp,heat_content_tsanom_depthInterp); gc.collect() # Fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset so_depthAve = scrubNaNAndMask(so_depthAve,so_depthInterp) temp_depthAve = scrubNaNAndMask(temp_depthAve,so_depthInterp) heat_content_sanom_depthInteg = scrubNaNAndMask(heat_content_sanom_depthInteg,so_depthInterp) heat_content_tanom_depthInteg = scrubNaNAndMask(heat_content_tanom_depthInteg,so_depthInterp) heat_content_tsanom_depthInteg = scrubNaNAndMask(heat_content_tsanom_depthInteg,so_depthInterp) del(so_depthInterp) # Convert numpy arrays to cdms objects heat_content_sanom_depthInteg = cdm.createVariable(heat_content_sanom_depthInteg,id='heat_content_sanom_depthInteg') heat_content_sanom_depthInteg.id = 'heat_content_sanom_depthInteg' heat_content_sanom_depthInteg.setAxis(0,newdepth) heat_content_sanom_depthInteg.setAxis(1,so.getAxis(1)) heat_content_sanom_depthInteg.setAxis(2,so.getAxis(2)) heat_content_sanom_depthInteg.units = 'J' heat_content_tanom_depthInteg = cdm.createVariable(heat_content_tanom_depthInteg,id='heat_content_tanom_depthInteg') heat_content_tanom_depthInteg.id = 'heat_content_tanom_depthInteg' heat_content_tanom_depthInteg.setAxis(0,newdepth) heat_content_tanom_depthInteg.setAxis(1,so.getAxis(1)) heat_content_tanom_depthInteg.setAxis(2,so.getAxis(2)) heat_content_tanom_depthInteg.units = 'J' heat_content_tsanom_depthInteg = cdm.createVariable(heat_content_tsanom_depthInteg,id='heat_content_tsanom_depthInteg') heat_content_tsanom_depthInteg.id = 'heat_content_tsanom_depthInteg' heat_content_tsanom_depthInteg.setAxis(0,newdepth) heat_content_tsanom_depthInteg.setAxis(1,so.getAxis(1)) heat_content_tsanom_depthInteg.setAxis(2,so.getAxis(2)) heat_content_tsanom_depthInteg.units = 'J' so_depthAve = cdm.createVariable(so_depthAve,id='so_depthAve') so_depthAve.id = 'so_depthAve' so_depthAve.setAxis(0,newdepth) so_depthAve.setAxis(1,so.getAxis(1)) so_depthAve.setAxis(2,so.getAxis(2)) so_depthAve.units = '1e-3' temp_depthAve = cdm.createVariable(temp_depthAve,id='temp_depthAve') temp_depthAve.id = 'temp_depthAve' temp_depthAve.setAxis(0,newdepth) temp_depthAve.setAxis(1,so.getAxis(1)) temp_depthAve.setAxis(2,so.getAxis(2)) temp_depthAve.units = 'degrees_C' steric_height_depthInterp = cdm.createVariable(steric_height_depthInterp,id='steric_height_depthInterp') steric_height_depthInterp.setAxis(0,newdepth) steric_height_depthInterp.setAxis(1,so.getAxis(1)) steric_height_depthInterp.setAxis(2,so.getAxis(2)) steric_height_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_anom_depthInterp = cdm.createVariable(steric_height_anom_depthInterp,id='steric_height_anom_depthInterp') steric_height_anom_depthInterp.setAxis(0,newdepth) steric_height_anom_depthInterp.setAxis(1,so.getAxis(1)) steric_height_anom_depthInterp.setAxis(2,rho.getAxis(2)) steric_height_anom_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_thermo_anom_depthInterp = cdm.createVariable(steric_height_thermo_anom_depthInterp,id='steric_height_thermo_anom_depthInterp') steric_height_thermo_anom_depthInterp.setAxis(0,newdepth) steric_height_thermo_anom_depthInterp.setAxis(1,so.getAxis(1)) steric_height_thermo_anom_depthInterp.setAxis(2,so.getAxis(2)) steric_height_thermo_anom_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_halo_anom_depthInterp = cdm.createVariable(steric_height_halo_anom_depthInterp,id='steric_height_halo_anom_depthInterp') steric_height_halo_anom_depthInterp.setAxis(0,newdepth) steric_height_halo_anom_depthInterp.setAxis(1,so.getAxis(1)) steric_height_halo_anom_depthInterp.setAxis(2,so.getAxis(2)) steric_height_halo_anom_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_halo_anom2_depthInterp = cdm.createVariable(steric_height_halo_anom2_depthInterp,id='steric_height_halo_anom2_depthInterp') steric_height_halo_anom2_depthInterp.setAxis(0,newdepth) steric_height_halo_anom2_depthInterp.setAxis(1,so.getAxis(1)) steric_height_halo_anom2_depthInterp.setAxis(2,so.getAxis(2)) steric_height_halo_anom2_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)' # Cleanup workspace del(newdepth) ; gc.collect() # Write variables to file if os.path.isfile(outFileName): os.remove(outFileName) filehandle = cdm.open(outFileName,'w') # Global attributes globalAttWrite(filehandle,options=None) ; # Use function to write standard global atts # Write seawater version filehandle.seawater_library_version = sw.__version__ # Write makeSteric version makeStericPath = str(makeSteric.__code__).split(' ')[6] makeStericPath = replace(replace(makeStericPath,'"',''),',','') ; # Clean scraped path filehandle.makeSteric_version = ' '.join(getGitInfo(makeStericPath)[0:3]) # Master variables filehandle.write(so.astype('float32')) filehandle.write(so_chg.astype('float32')) filehandle.write(so_depthAve.astype('float32')) filehandle.write(temp.astype('float32')) filehandle.write(temp_chg.astype('float32')) filehandle.write(temp_depthAve.astype('float32')) # Derived variables filehandle.write(cp.astype('float32')) filehandle.write(cp_halo.astype('float32')) filehandle.write(cp_thermo.astype('float32')) filehandle.write(rho.astype('float32')) filehandle.write(rho_halo.astype('float32')) filehandle.write(rho_thermo.astype('float32')) filehandle.write(heat_content.astype('float32')) filehandle.write(heat_content_sanom.astype('float32')) filehandle.write(heat_content_sanom_depthInteg.astype('float32')) filehandle.write(heat_content_tanom.astype('float32')) filehandle.write(heat_content_tanom_depthInteg.astype('float32')) filehandle.write(heat_content_tsanom.astype('float32')) filehandle.write(heat_content_tsanom_depthInteg.astype('float32')) filehandle.write(steric_height.astype('float32')) filehandle.write(steric_height_depthInterp.astype('float32')) filehandle.write(steric_height_anom.astype('float32')) filehandle.write(steric_height_anom_depthInterp.astype('float32')) filehandle.write(steric_height_halo_anom.astype('float32')) filehandle.write(steric_height_halo_anom2.astype('float32')) filehandle.write(steric_height_halo_anom_depthInterp.astype('float32')) filehandle.write(steric_height_halo_anom2_depthInterp.astype('float32')) filehandle.write(steric_height_thermo_anom.astype('float32')) filehandle.write(steric_height_thermo_anom_depthInterp.astype('float32')) filehandle.close() # Cleanup workspace del(outFileName) ; gc.collect()
def makeHeatContent(salt, temp, destMask, thetao, pressure): """ The makeHeatContent() function takes 3D (not temporal) arguments and creates heat content which is then mapped to a destination grid and written to a specified variable Author: Paul J. Durack : [email protected] : @durack1. Created on Tue Nov 24 15:34:30 2015. Inputs: ------ - salt(lev,lat,lon) - 3D array. - temp(lev,lat,lon) - 3D array either in-situ or potential temperature. - destGridArray(str) - 2D array with valid grid and mask. - thetao(bool) - boolean value specifying either in-situ or potential temperature arrays provided. - pressure(bool) - boolean value specifying whether lev-coordinate is pressure (dbar) or depth (m). Usage: ------ >>> from oceanLib import makeHeatContent >>> makeHeatContent(salt,temp,destGridArray,thetao=True,pressure=False) Notes: ----- - PJD 24 Nov 2015 - Migrated into new oceanLib from heatContentLib - TODO: Better deal with insitu vs thetao variables - TODO: """ # Remap variables to short names #print salt.getAxisIds() s = salt(squeeze=1) # Trim off singleton time dimension #print s.getAxisIds() t = temp(squeeze=1) mask = destMask #print mask.getAxisIds() del (salt, temp, destMask) gc.collect() depthInd = 0 # Set depth coordinate index #print 's: ',s.min(),s.max() #print 't: ',t.min(),t.max() # Fix out of bounds values t = mv.where(t < -2.6, -2.6, t) # Fix for NaN values # Calculate pressure - inputs depth & lat # Create z-coordinate from salinity input if not pressure: zCoord = s.getAxis(depthInd) # Assume time,depth,latitude,longitude grid yCoord = s.getAxis(depthInd + 1) yCoord = tile(yCoord, (s.shape[depthInd + 2], 1)).transpose() depthLevels = tile( zCoord.getValue(), (s.shape[depthInd + 2], s.shape[depthInd + 1], 1)).transpose() pressureLevels = sw.pres(np.array(depthLevels), np.array(yCoord)) del (zCoord, yCoord, depthLevels) gc.collect() else: pressureLevels = s.getAxis(depthInd) #print pressureLevels.getValue() pressureLevels = transpose( tile(pressureLevels, (s.shape[depthInd + 2], s.shape[depthInd + 1], 1))) pressureLevels = cdm.createVariable(pressureLevels, id='pressureLevels') pressureLevels.setAxis(0, s.getAxis(depthInd)) pressureLevels.setAxis(1, s.getAxis(depthInd + 1)) pressureLevels.setAxis(2, s.getAxis(depthInd + 2)) pressureLevels.units_long = 'decibar (pressure)' pressureLevels.positive = 'down' pressureLevels.long_name = 'sea_water_pressure' pressureLevels.standard_name = 'sea_water_pressure' pressureLevels.units = 'decibar' pressureLevels.axis = 'Z' #print 'pres: ',pressureLevels.min(),pressureLevels.max() #print pressureLevels.shape #print s.shape #print t.shape #print mask.shape # Calculate temp,rho,cp - inputs temp,salt,pressure if thetao: # Process potential temperature to in-situ temp = sw.temp(np.array(s), np.array(t), np.array(pressureLevels)) # units degrees C rho = sw.dens(np.array(s), np.array(temp), np.array(pressureLevels)) # units kg m-3 cp = sw.cp(np.array(s), np.array(temp), np.array(pressureLevels)) # units J kg-1 C-1 # Correct instances of NaN values and fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset temp = scrubNaNAndMask(temp, s) rho = scrubNaNAndMask(rho, s) cp = scrubNaNAndMask(cp, s) #print 'temp: ',temp.min(),temp.max() #print 'rho: ',rho.min(),rho.max() #print 'cp: ',cp.min(),cp.max() # Calculate heatContent - inputs temp,rho,cp heatContent = np.array(temp) * np.array(rho) * np.array(cp) # units J # Correct instances of NaN values and fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset heatContent = scrubNaNAndMask(heatContent, s) #print 'hc: ',heatContent.min(),heatContent.max() # Interpolate to standard levels - inputs heatContent,levels newDepth = np.array([ 5, 10, 20, 30, 40, 50, 75, 100, 125, 150, 200, 300, 500, 700, 1000, 1500, 1800, 2000 ]).astype('f') newDepth_bounds = np.array([[0, 5], [5, 10], [10, 20], [20, 30], [30, 40], [40, 50], [50, 75], [75, 100], [100, 125], [125, 150], [150, 200], [200, 300], [300, 500], [500, 700], [700, 1000], [1000, 1500], [1500, 1800], [1800, 2000]]).astype('f') # Interpolate to standard levels #print heatContent.shape #print heatContent.getAxisIds() #print pressureLevels.shape #print pressureLevels.getAxisIds() # Reset variable axes heatContent.setAxis(0, s.getAxis(0)) #heatContent.setAxis(1,s.getAxis(1)) #heatContent.setAxis(2,s.getAxis(2)) pdb.set_trace() heatContent.setGrid(s.getGrid()) #print heatContent.shape #print heatContent.getAxisIds() #print pressureLevels.shape #print pressureLevels.getAxisIds() heatContent_depthInterp = cdu.linearInterpolation(heatContent, pressureLevels, levels=newDepth) # Fix bounds newDepth = heatContent_depthInterp.getAxis(0) newDepth.setBounds(newDepth_bounds) del (newDepth_bounds) newDepth.id = 'depth2' newDepth.units_long = 'decibar (pressure)' newDepth.positive = 'down' newDepth.long_name = 'sea_water_pressure' newDepth.standard_name = 'sea_water_pressure' newDepth.units = 'decibar' newDepth.axis = 'Z' #print 'hc_interp:',heatContent_depthInterp.min(),heatContent_depthInterp.max() # Integrate to 700 dbar - inputs heatContent heatContent_depthInteg = cdu.averager( heatContent_depthInterp[0:14, ...], axis=0, weights='weighted', action='sum')(squeeze=1) # Calculate depth-weighted-integrated thetao # Assign all axis info #print heatContent_depthInteg.shape pdb.set_trace() # Interpolate in x,y - inputs heatContent #tmp1 = heatContent_depthInteg.regrid(mask.getGrid(),regridTool='esmf',regridMethod='linear') ; # Use defaults - ,coordSys='deg',diag = {},periodicity=1) tmp1 = heatContent_depthInteg.regrid(mask, regridTool='esmf', regridMethod='linear') # Use defaults - ,coordSys='deg',diag = {},periodicity=1) #print tmp1.shape tmp1 = mv.where(tmp1 < 0, 0, tmp1) # Fix for negative values # Infill - inputs heatContent # Create inputs for interpolation points = np.zeros([(mask.shape[0] * mask.shape[1]), 2]) # Create 25380 vectors of lon/lat latcounter = 0 loncounter = 0 for count, data in enumerate(points): if not np.mod(count, 180) and not count == 0: latcounter = latcounter + 1 loncounter = 0 points[count, 0] = mask.getLatitude().getValue()[latcounter] points[count, 1] = mask.getLongitude().getValue()[loncounter] loncounter = loncounter + 1 del (count, data, latcounter, loncounter) gc.collect() valid = np.logical_not(tmp1.mask) # Get inverted-logic boolean mask from variable if valid.size == 1: print '** No valid mask found, skipping **' return valid = valid.flatten() # Flatten 2D to 1D #maskFilled = mask(tmp,points,valid) interpolant = interpolate.LinearNDInterpolator( points[valid, :], np.array(tmp1.flatten())[valid]) # Create interpolant maskFill = interpolant(points[:, 0].squeeze(), points[:, 1].squeeze()) # Use interpolant to create filled matrix maskFill = np.reshape(maskFill, mask.shape) # Resize to original dimensions # Fix issues with interpolant tmp2 = mv.where(np.isnan(maskFill), 1e+20, maskFill) # Fix for NaN values tmp2 = mv.where(tmp2 > tmp1.max(), 0, tmp2) # Fix for max values tmp2 = mv.where(tmp2 < tmp1.min(), 0, tmp2) # Fix for min values tmp = mv.masked_where(mask.mask, tmp2) #print tmp.shape # Redress variable heatContent = cdm.createVariable([tmp], id='heatContent') depthInt = cdm.createAxis([350], id='depth') depthInt.setBounds(np.array([0, 700])) depthInt.units_long = 'decibar (pressure)' depthInt.positive = 'down' depthInt.long_name = 'sea_water_pressure' depthInt.standard_name = 'sea_water_pressure' depthInt.units = 'decibar' depthInt.axis = 'Z' heatContent.setAxis(0, depthInt) heatContent.setAxis(1, mask.getAxis(0)) heatContent.setAxis(2, mask.getAxis(1)) heatContent.units_long = 'Joules' heatContent.long_name = 'sea_water_heat_content' heatContent.standard_name = 'sea_water_heat_content' heatContent.units = 'J' return heatContent
def makeSteric(salinity, salinityChg, temp, tempChg, outFileName, thetao, pressure): """ The makeSteric() function takes 3D (not temporal) arguments and creates heat content and steric fields which are written to a specified outfile Author: Paul J. Durack : [email protected] : @durack1. Created on Thu Jul 18 13:03:37 2013. Inputs: ------ - salinity(lev,lat,lon) - 3D array for the climatological period. - salinityChg(lev,lat,lon) - 3D array for the temporal change period. - temp(lev,lat,lon) - 3D array for the climatological period either in-situ or potential temperature. - tempChg(lev,lat,lon) - 3D array for the temporal change period as with temp, either in-situ or potential temperature. - outFileName(str) - output filename with full path specified. - thetao(bool) - boolean value specifying either in-situ or potential temperature arrays provided. - pressure(bool) - boolean value specifying whether lev-coordinate is pressure (dbar) or depth (m). Usage: ------ >>> from makeStericLib import makeSteric >>> makeSteric(salinity,salinityChg,thetao,thetaoChg,'outfile.nc',True,False) Notes: ----- - PJD 18 Jul 2013 - Validated Ishii v6.13 data against WOA94 - checks out ok. Units: dyn decimeter compared to http://www.nodc.noaa.gov/OC5/WOA94/dyn.html uses cm (not decimeter; x 10) - PJD 18 Jul 2013 - Added attribute scrub to incoming variables (so,so_chg,temp,temp_chg) to maintain output consistency - PJD 22 Jul 2013 - Added name attributes to so and temp variables, added units to so_chg - PJD 22 Jul 2013 - removed duplicated code by converting repetition to function scrubNaNAndMask - PJD 23 Jul 2013 - Further cleaned up so,so_chg,temp,temp_chg outputs specifying id/name attributes - PJD 5 Aug 2013 - Updated python-seawater library to version 3.3.1 from github repo, git clone http://github.com/ocefpaf/python-seawater, python setup.py install --user - PJD 7 Aug 2013 - FIXED: thetao rather than in-situ temperature propagating throughout calculations - PJD 7 Aug 2013 - Replaced looping with 3D gpan - PJD 7 Aug 2013 - Further code duplication cleanup - PJD 8 Aug 2013 - FIXED: scrubNanAndMask function type/mask/grid issue - encase sw arguments in np.array() (attempt to strip cdms fluff) - PJD 8 Aug 2013 - FIXED: removed depth variable unit edits - not all inputs are depth (m) - PJD 15 Aug 2013 - Increased interpolated field resolution [200,300,500,700,1000,1500,1800,2000] - [5,10,20,30,40,50,75,100,125,150,200, ...] - PJD 18 Aug 2013 - AR5 hard coded rho=1020,cp=4187 == 4.3e6 vs Ishii 1970 rho.mean=1024,cp.mean=3922 == 4.1e6 ~5% too high - PJD 13 Jan 2014 - Corrected steric_height_anom and steric_height_thermo_anom to true anomaly fields, needed to remove climatology - PJD 3 May 2014 - Turned off thetao conversion, although convert to numpy array rather than cdms2 transient variable - PJD 13 Oct 2014 - Added seawater_library_version as a global attribute - PJD 13 Oct 2014 - FIXED: bug with calculation of rho_halo variable was calculating gpan - PJD 13 Oct 2014 - Added alternate calculation of halosteric anomaly (direct salinity anomaly calculation, rather than total-thermosteric) - PJD 13 Oct 2014 - Added makeSteric_version as a global attribute - TODO: Better deal with insitu vs thetao variables - TODO: Query Charles on why *.name attributes are propagating - TODO: validate outputs and compare to matlab versions - 10e-7 errors. """ # Remap all variables to short names so = salinity so_chg = salinityChg temp = temp temp_chg = tempChg del (salinity, salinityChg, tempChg) gc.collect() # Strip attributes to maintain consistency between datasets for count, x in enumerate(so.attributes.keys()): delattr(so, x) #print so.listattributes() ; # Print remaining attributes for count, x in enumerate(so_chg.attributes.keys()): delattr(so_chg, x) for count, x in enumerate(temp.attributes.keys()): delattr(temp, x) for count, x in enumerate(temp_chg.attributes.keys()): delattr(temp_chg, x) del (count, x) # Create z-coordinate from salinity input if not pressure: z_coord = so.getAxis(0) y_coord = so.getAxis(1) y_coord = tile(y_coord, (so.shape[2], 1)).transpose() depth_levels = tile(z_coord.getValue(), (so.shape[2], so.shape[1], 1)).transpose() pressure_levels = sw.pres(np.array(depth_levels), np.array(y_coord)) del (z_coord, y_coord, depth_levels) gc.collect() else: pressure_levels = so.getAxis(0) pressure_levels = transpose( tile(pressure_levels, (so.shape[2], so.shape[1], 1))) pressure_levels = cdm.createVariable(pressure_levels, id='pressure_levels') pressure_levels.setAxis(0, so.getAxis(0)) pressure_levels.setAxis(1, so.getAxis(1)) pressure_levels.setAxis(2, so.getAxis(2)) pressure_levels.id = 'pressure_levels' pressure_levels.units_long = 'decibar (pressure)' pressure_levels.positive = 'down' pressure_levels.long_name = 'sea_water_pressure' pressure_levels.standard_name = 'sea_water_pressure' pressure_levels.units = 'decibar' pressure_levels.axis = 'Z' # Cleanup depth axis attributes depth = so.getAxis(0) depth.id = 'depth' depth.name = 'depth' depth.long_name = 'depth' depth.standard_name = 'depth' depth.axis = 'Z' so.setAxis(0, depth) so_chg.setAxis(0, depth) temp.setAxis(0, depth) temp_chg.setAxis(0, depth) del (depth) # Convert using python-seawater library (v3.3.1 - 130807) if thetao: # Process potential temperature to in-situ - default conversion sets reference pressure to 0 (surface) #temp_chg = sw.temp(np.array(so),np.array(temp_chg),np.array(pressure_levels)); # units degrees C #temp = sw.temp(np.array(so),np.array(temp),np.array(pressure_levels)); # units degrees C #temp_chg = sw.ptmp(np.array(so),np.array(temp_chg),np.array(pressure_levels),np.array(pressure_levels)); # units degrees C #temp = sw.ptmp(np.array(so),np.array(temp),np.array(pressure_levels),np.array(pressure_levels)); # units degrees C temp_chg = np.array(temp_chg) # units degrees C temp = np.array(temp) # units degrees C # Climatologies - rho,cp,steric_height rho = sw.dens(np.array(so), np.array(temp), np.array(pressure_levels)) # units kg m-3 cp = sw.cp(np.array(so), np.array(temp), np.array(pressure_levels)) # units J kg-1 C-1 steric_height = sw.gpan(np.array(so), np.array(temp), np.array(pressure_levels)) # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) # Halosteric - rho,cp ss = map(array, (so + so_chg)) rho_halo = sw.dens(np.array(ss), np.array(temp), np.array(pressure_levels)) # units kg m-3 cp_halo = sw.cp(np.array(ss), np.array(temp), np.array(pressure_levels)) # units J kg-1 C-1 tmp = sw.gpan(np.array(ss), np.array(temp), np.array(pressure_levels)) # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) steric_height_halo_anom2 = tmp - steric_height # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) # Full steric - steric_height tt = map(array, (temp + temp_chg)) tmp = sw.gpan(np.array(ss), np.array(tt), np.array(pressure_levels)) # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) steric_height_anom = tmp - steric_height # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) del (ss, tmp) gc.collect() # Thermosteric - rho,cp,steric_height rho_thermo = sw.dens(np.array(so), np.array(tt), np.array(pressure_levels)) # units kg m-3 cp_thermo = sw.cp(np.array(so), np.array(tt), np.array(pressure_levels)) # units J kg-1 C-1 tmp = sw.gpan(np.array(so), np.array(tt), np.array(pressure_levels)) # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) steric_height_thermo_anom = tmp - steric_height # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) del (tt, tmp) gc.collect() # Halosteric - steric_height steric_height_halo_anom = steric_height_anom - steric_height_thermo_anom # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter) # Create heat content heat_content = np.array(temp) * np.array(rho) * np.array(cp) # units J heat_content_sanom = np.array(temp) * np.array(rho_halo) * np.array( cp_halo) # units J heat_content_tanom = np.array(temp_chg) * np.array(rho) * np.array(cp) # units J #heat_content_tanom = np.array(temp_chg)*np.array(1020)*np.array(4187) ; # units J - try hard-coded - AR5 numbers heat_content_tsanom = np.array(temp_chg) * np.array(rho_halo) * np.array( cp_halo) # units J # Correct all instances of NaN values and fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset temp = scrubNaNAndMask(temp, so) temp_chg = scrubNaNAndMask(temp_chg, so) rho = scrubNaNAndMask(rho, so) cp = scrubNaNAndMask(cp, so) rho_halo = scrubNaNAndMask(rho_halo, so) cp_halo = scrubNaNAndMask(cp_halo, so) rho_thermo = scrubNaNAndMask(rho_thermo, so) cp_thermo = scrubNaNAndMask(cp_thermo, so) steric_height = scrubNaNAndMask(steric_height, so) steric_height_anom = scrubNaNAndMask(steric_height_anom, so) steric_height_thermo_anom = scrubNaNAndMask(steric_height_thermo_anom, so) steric_height_halo_anom = scrubNaNAndMask(steric_height_halo_anom, so) steric_height_halo_anom2 = scrubNaNAndMask(steric_height_halo_anom2, so) heat_content = scrubNaNAndMask(heat_content, so) heat_content_sanom = scrubNaNAndMask(heat_content_sanom, so) heat_content_tanom = scrubNaNAndMask(heat_content_tanom, so) heat_content_tsanom = scrubNaNAndMask(heat_content_tsanom, so) # Recreate and redress variables so.id = 'so_mean' so.units = '1e-3' so_chg.id = 'so_chg' so_chg.units = '1e-3' temp = cdm.createVariable(temp, id='temp_mean') temp.setAxis(0, so.getAxis(0)) temp.setAxis(1, so.getAxis(1)) temp.setAxis(2, so.getAxis(2)) temp.units = 'degrees_C' temp_chg = cdm.createVariable(temp_chg, id='temp_chg') temp_chg.setAxis(0, so.getAxis(0)) temp_chg.setAxis(1, so.getAxis(1)) temp_chg.setAxis(2, so.getAxis(2)) temp_chg.units = 'degrees_C' rho = cdm.createVariable(rho, id='rho') rho.setAxis(0, so.getAxis(0)) rho.setAxis(1, so.getAxis(1)) rho.setAxis(2, so.getAxis(2)) rho.name = 'density_mean' rho.units = 'kg m^-3' cp = cdm.createVariable(cp, id='cp') cp.setAxis(0, so.getAxis(0)) cp.setAxis(1, so.getAxis(1)) cp.setAxis(2, so.getAxis(2)) cp.name = 'heat_capacity_mean' cp.units = 'J kg^-1 C^-1' rho_halo = cdm.createVariable(rho_halo, id='rho_halo') rho_halo.setAxis(0, so.getAxis(0)) rho_halo.setAxis(1, so.getAxis(1)) rho_halo.setAxis(2, so.getAxis(2)) rho_halo.name = 'density_mean_halo' rho_halo.units = 'kg m^-3' cp_halo = cdm.createVariable(cp_halo, id='cp_halo') cp_halo.setAxis(0, so.getAxis(0)) cp_halo.setAxis(1, so.getAxis(1)) cp_halo.setAxis(2, so.getAxis(2)) cp_halo.name = 'heat_capacity_mean_halo' cp_halo.units = 'J kg^-1 C^-1' rho_thermo = cdm.createVariable(rho_thermo, id='rho_thermo') rho_thermo.setAxis(0, so.getAxis(0)) rho_thermo.setAxis(1, so.getAxis(1)) rho_thermo.setAxis(2, so.getAxis(2)) rho_thermo.name = 'density_mean_thermo' rho_thermo.units = 'kg m^-3' cp_thermo = cdm.createVariable(cp_thermo, id='cp_thermo') cp_thermo.setAxis(0, so.getAxis(0)) cp_thermo.setAxis(1, so.getAxis(1)) cp_thermo.setAxis(2, so.getAxis(2)) cp_thermo.name = 'heat_capacity_mean_thermo' cp_thermo.units = 'J kg^-1 C^-1' steric_height = cdm.createVariable(steric_height, id='steric_height') steric_height.setAxis(0, so.getAxis(0)) steric_height.setAxis(1, so.getAxis(1)) steric_height.setAxis(2, so.getAxis(2)) steric_height.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_anom = cdm.createVariable(steric_height_anom, id='steric_height_anom') steric_height_anom.setAxis(0, so.getAxis(0)) steric_height_anom.setAxis(1, so.getAxis(1)) steric_height_anom.setAxis(2, so.getAxis(2)) steric_height_anom.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_thermo_anom = cdm.createVariable( steric_height_thermo_anom, id='steric_height_thermo_anom') steric_height_thermo_anom.setAxis(0, so.getAxis(0)) steric_height_thermo_anom.setAxis(1, so.getAxis(1)) steric_height_thermo_anom.setAxis(2, so.getAxis(2)) steric_height_thermo_anom.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_halo_anom = cdm.createVariable(steric_height_halo_anom, id='steric_height_halo_anom') steric_height_halo_anom.setAxis(0, so.getAxis(0)) steric_height_halo_anom.setAxis(1, so.getAxis(1)) steric_height_halo_anom.setAxis(2, so.getAxis(2)) steric_height_halo_anom.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_halo_anom2 = cdm.createVariable( steric_height_halo_anom2, id='steric_height_halo_anom2') steric_height_halo_anom2.setAxis(0, so.getAxis(0)) steric_height_halo_anom2.setAxis(1, so.getAxis(1)) steric_height_halo_anom2.setAxis(2, so.getAxis(2)) steric_height_halo_anom2.units = 'm^3 kg^-1 Pa (dynamic decimeter)' heat_content = cdm.createVariable(heat_content, id='heat_content') heat_content.setAxis(0, so.getAxis(0)) heat_content.setAxis(1, so.getAxis(1)) heat_content.setAxis(2, so.getAxis(2)) heat_content.units = 'J' heat_content_sanom = cdm.createVariable(heat_content_sanom, id='heat_content_sanom') heat_content_sanom.setAxis(0, so.getAxis(0)) heat_content_sanom.setAxis(1, so.getAxis(1)) heat_content_sanom.setAxis(2, so.getAxis(2)) heat_content_sanom.units = 'J' heat_content_tanom = cdm.createVariable(heat_content_tanom, id='heat_content_tanom') heat_content_tanom.setAxis(0, so.getAxis(0)) heat_content_tanom.setAxis(1, so.getAxis(1)) heat_content_tanom.setAxis(2, so.getAxis(2)) heat_content_tanom.units = 'J' heat_content_tsanom = cdm.createVariable(heat_content_tsanom, id='heat_content_tsanom') heat_content_tsanom.setAxis(0, so.getAxis(0)) heat_content_tsanom.setAxis(1, so.getAxis(1)) heat_content_tsanom.setAxis(2, so.getAxis(2)) heat_content_tsanom.units = 'J' # Create model-based depth index for subset target levels newdepth = np.array([ 5, 10, 20, 30, 40, 50, 75, 100, 125, 150, 200, 300, 500, 700, 1000, 1500, 1800, 2000 ]).astype('f') newdepth_bounds = np.array([[0, 5], [5, 10], [10, 20], [20, 30], [30, 40], [40, 50], [50, 75], [75, 100], [100, 125], [125, 150], [150, 200], [200, 300], [300, 500], [500, 700], [700, 1000], [1000, 1500], [1500, 1800], [1800, 2000]]).astype('f') #newdepth = np.array([200,300,500,700,1000,1500,1800,2000]).astype('f'); #newdepth_bounds = np.array([[0,200],[200,300],[300,500],[500,700],[700,1000],[1000,1500],[1500,1800],[1800,2000]]).astype('f') # Interpolate to depths so_depthInterp = cdu.linearInterpolation(so, pressure_levels, levels=newdepth) temp_depthInterp = cdu.linearInterpolation(temp, pressure_levels, levels=newdepth) steric_height_depthInterp = cdu.linearInterpolation(steric_height, pressure_levels, levels=newdepth) steric_height_anom_depthInterp = cdu.linearInterpolation( steric_height_anom, pressure_levels, levels=newdepth) steric_height_thermo_anom_depthInterp = cdu.linearInterpolation( steric_height_thermo_anom, pressure_levels, levels=newdepth) steric_height_halo_anom_depthInterp = cdu.linearInterpolation( steric_height_halo_anom, pressure_levels, levels=newdepth) steric_height_halo_anom2_depthInterp = cdu.linearInterpolation( steric_height_halo_anom2, pressure_levels, levels=newdepth) heat_content_sanom_depthInterp = cdu.linearInterpolation( heat_content_sanom, pressure_levels, levels=newdepth) heat_content_tanom_depthInterp = cdu.linearInterpolation( heat_content_tanom, pressure_levels, levels=newdepth) heat_content_tsanom_depthInterp = cdu.linearInterpolation( heat_content_tanom, pressure_levels, levels=newdepth) # Fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset temp_depthInterp = scrubNaNAndMask(temp_depthInterp, so_depthInterp) steric_height_depthInterp = scrubNaNAndMask(steric_height_depthInterp, so_depthInterp) steric_height_anom_depthInterp = scrubNaNAndMask( steric_height_anom_depthInterp, so_depthInterp) steric_height_thermo_anom_depthInterp = scrubNaNAndMask( steric_height_thermo_anom_depthInterp, so_depthInterp) steric_height_halo_anom_depthInterp = scrubNaNAndMask( steric_height_halo_anom_depthInterp, so_depthInterp) steric_height_halo_anom2_depthInterp = scrubNaNAndMask( steric_height_halo_anom2_depthInterp, so_depthInterp) heat_content_sanom_depthInterp = scrubNaNAndMask( heat_content_sanom_depthInterp, so_depthInterp) heat_content_tanom_depthInterp = scrubNaNAndMask( heat_content_tanom_depthInterp, so_depthInterp) heat_content_tsanom_depthInterp = scrubNaNAndMask( heat_content_tsanom_depthInterp, so_depthInterp) # Fix bounds newdepth = so_depthInterp.getAxis(0) newdepth.setBounds(newdepth_bounds) del (newdepth_bounds) newdepth.id = 'depth2' newdepth.units_long = 'decibar (pressure)' newdepth.positive = 'down' newdepth.long_name = 'sea_water_pressure' newdepth.standard_name = 'sea_water_pressure' newdepth.units = 'decibar' newdepth.axis = 'Z' # Assign corrected bounds so_depthInterp.setAxis(0, newdepth) temp_depthInterp.setAxis(0, newdepth) steric_height_depthInterp.setAxis(0, newdepth) steric_height_anom_depthInterp.setAxis(0, newdepth) steric_height_thermo_anom_depthInterp.setAxis(0, newdepth) steric_height_halo_anom_depthInterp.setAxis(0, newdepth) steric_height_halo_anom2_depthInterp.setAxis(0, newdepth) heat_content_sanom_depthInterp.setAxis(0, newdepth) heat_content_tanom_depthInterp.setAxis(0, newdepth) heat_content_tsanom_depthInterp.setAxis(0, newdepth) # Average/integrate to surface - configure bounds # Preallocate arrays so_depthAve = np.ma.zeros([len(newdepth), shape(so)[1], shape(so)[2]]) temp_depthAve = so_depthAve.copy() heat_content_sanom_depthInteg = so_depthAve.copy() heat_content_tanom_depthInteg = so_depthAve.copy() heat_content_tsanom_depthInteg = so_depthAve.copy() for count, depth in enumerate(newdepth): tmp = cdu.averager(so_depthInterp[0:(count + 1), ...], axis=0, weights='weighted', action='average') so_depthAve[count, ] = tmp tmp = cdu.averager(temp_depthInterp[0:(count + 1), ...], axis=0, weights='weighted', action='average') temp_depthAve[count, ] = tmp tmp = cdu.averager(heat_content_sanom_depthInterp[0:(count + 1), ...], axis=0, weights='weighted', action='sum') heat_content_sanom_depthInteg[count, ] = tmp tmp = cdu.averager(heat_content_tanom_depthInterp[0:(count + 1), ...], axis=0, weights='weighted', action='sum') heat_content_tanom_depthInteg[count, ] = tmp tmp = cdu.averager(heat_content_tsanom_depthInterp[0:(count + 1), ...], axis=0, weights='weighted', action='sum') heat_content_tsanom_depthInteg[count, ] = tmp del (heat_content_tanom_depthInterp, heat_content_tsanom_depthInterp) gc.collect() # Fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset so_depthAve = scrubNaNAndMask(so_depthAve, so_depthInterp) temp_depthAve = scrubNaNAndMask(temp_depthAve, so_depthInterp) heat_content_sanom_depthInteg = scrubNaNAndMask( heat_content_sanom_depthInteg, so_depthInterp) heat_content_tanom_depthInteg = scrubNaNAndMask( heat_content_tanom_depthInteg, so_depthInterp) heat_content_tsanom_depthInteg = scrubNaNAndMask( heat_content_tsanom_depthInteg, so_depthInterp) del (so_depthInterp) # Convert numpy arrays to cdms objects heat_content_sanom_depthInteg = cdm.createVariable( heat_content_sanom_depthInteg, id='heat_content_sanom_depthInteg') heat_content_sanom_depthInteg.id = 'heat_content_sanom_depthInteg' heat_content_sanom_depthInteg.setAxis(0, newdepth) heat_content_sanom_depthInteg.setAxis(1, so.getAxis(1)) heat_content_sanom_depthInteg.setAxis(2, so.getAxis(2)) heat_content_sanom_depthInteg.units = 'J' heat_content_tanom_depthInteg = cdm.createVariable( heat_content_tanom_depthInteg, id='heat_content_tanom_depthInteg') heat_content_tanom_depthInteg.id = 'heat_content_tanom_depthInteg' heat_content_tanom_depthInteg.setAxis(0, newdepth) heat_content_tanom_depthInteg.setAxis(1, so.getAxis(1)) heat_content_tanom_depthInteg.setAxis(2, so.getAxis(2)) heat_content_tanom_depthInteg.units = 'J' heat_content_tsanom_depthInteg = cdm.createVariable( heat_content_tsanom_depthInteg, id='heat_content_tsanom_depthInteg') heat_content_tsanom_depthInteg.id = 'heat_content_tsanom_depthInteg' heat_content_tsanom_depthInteg.setAxis(0, newdepth) heat_content_tsanom_depthInteg.setAxis(1, so.getAxis(1)) heat_content_tsanom_depthInteg.setAxis(2, so.getAxis(2)) heat_content_tsanom_depthInteg.units = 'J' so_depthAve = cdm.createVariable(so_depthAve, id='so_depthAve') so_depthAve.id = 'so_depthAve' so_depthAve.setAxis(0, newdepth) so_depthAve.setAxis(1, so.getAxis(1)) so_depthAve.setAxis(2, so.getAxis(2)) so_depthAve.units = '1e-3' temp_depthAve = cdm.createVariable(temp_depthAve, id='temp_depthAve') temp_depthAve.id = 'temp_depthAve' temp_depthAve.setAxis(0, newdepth) temp_depthAve.setAxis(1, so.getAxis(1)) temp_depthAve.setAxis(2, so.getAxis(2)) temp_depthAve.units = 'degrees_C' steric_height_depthInterp = cdm.createVariable( steric_height_depthInterp, id='steric_height_depthInterp') steric_height_depthInterp.setAxis(0, newdepth) steric_height_depthInterp.setAxis(1, so.getAxis(1)) steric_height_depthInterp.setAxis(2, so.getAxis(2)) steric_height_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_anom_depthInterp = cdm.createVariable( steric_height_anom_depthInterp, id='steric_height_anom_depthInterp') steric_height_anom_depthInterp.setAxis(0, newdepth) steric_height_anom_depthInterp.setAxis(1, so.getAxis(1)) steric_height_anom_depthInterp.setAxis(2, rho.getAxis(2)) steric_height_anom_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_thermo_anom_depthInterp = cdm.createVariable( steric_height_thermo_anom_depthInterp, id='steric_height_thermo_anom_depthInterp') steric_height_thermo_anom_depthInterp.setAxis(0, newdepth) steric_height_thermo_anom_depthInterp.setAxis(1, so.getAxis(1)) steric_height_thermo_anom_depthInterp.setAxis(2, so.getAxis(2)) steric_height_thermo_anom_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_halo_anom_depthInterp = cdm.createVariable( steric_height_halo_anom_depthInterp, id='steric_height_halo_anom_depthInterp') steric_height_halo_anom_depthInterp.setAxis(0, newdepth) steric_height_halo_anom_depthInterp.setAxis(1, so.getAxis(1)) steric_height_halo_anom_depthInterp.setAxis(2, so.getAxis(2)) steric_height_halo_anom_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)' steric_height_halo_anom2_depthInterp = cdm.createVariable( steric_height_halo_anom2_depthInterp, id='steric_height_halo_anom2_depthInterp') steric_height_halo_anom2_depthInterp.setAxis(0, newdepth) steric_height_halo_anom2_depthInterp.setAxis(1, so.getAxis(1)) steric_height_halo_anom2_depthInterp.setAxis(2, so.getAxis(2)) steric_height_halo_anom2_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)' # Cleanup workspace del (newdepth) gc.collect() # Write variables to file if os.path.isfile(outFileName): os.remove(outFileName) filehandle = cdm.open(outFileName, 'w') # Global attributes globalAttWrite(filehandle, options=None) # Use function to write standard global atts # Write seawater version filehandle.seawater_library_version = sw.__version__ # Write makeSteric version makeStericPath = str(makeSteric.__code__).split(' ')[6] makeStericPath = replace(replace(makeStericPath, '"', ''), ',', '') # Clean scraped path filehandle.makeSteric_version = ' '.join(getGitInfo(makeStericPath)[0:3]) # Master variables filehandle.write(so.astype('float32')) filehandle.write(so_chg.astype('float32')) filehandle.write(so_depthAve.astype('float32')) filehandle.write(temp.astype('float32')) filehandle.write(temp_chg.astype('float32')) filehandle.write(temp_depthAve.astype('float32')) # Derived variables filehandle.write(cp.astype('float32')) filehandle.write(cp_halo.astype('float32')) filehandle.write(cp_thermo.astype('float32')) filehandle.write(rho.astype('float32')) filehandle.write(rho_halo.astype('float32')) filehandle.write(rho_thermo.astype('float32')) filehandle.write(heat_content.astype('float32')) filehandle.write(heat_content_sanom.astype('float32')) filehandle.write(heat_content_sanom_depthInteg.astype('float32')) filehandle.write(heat_content_tanom.astype('float32')) filehandle.write(heat_content_tanom_depthInteg.astype('float32')) filehandle.write(heat_content_tsanom.astype('float32')) filehandle.write(heat_content_tsanom_depthInteg.astype('float32')) filehandle.write(steric_height.astype('float32')) filehandle.write(steric_height_depthInterp.astype('float32')) filehandle.write(steric_height_anom.astype('float32')) filehandle.write(steric_height_anom_depthInterp.astype('float32')) filehandle.write(steric_height_halo_anom.astype('float32')) filehandle.write(steric_height_halo_anom2.astype('float32')) filehandle.write(steric_height_halo_anom_depthInterp.astype('float32')) filehandle.write(steric_height_halo_anom2_depthInterp.astype('float32')) filehandle.write(steric_height_thermo_anom.astype('float32')) filehandle.write(steric_height_thermo_anom_depthInterp.astype('float32')) filehandle.close() # Cleanup workspace del (outFileName) gc.collect()
hefti = heft*1. # empta = empt*1. emptp = empt*1. empti = empt*1. # # Compute density rhon[t,...] = eosNeutral(tost.data, sost.data) - 1000. rhon[t,...].mask = maski rhon[t,...] = maskVal(rhon[t,...], valmask) rhonl = rhon.data[t,...] # Compute buoyancy/density flux as mass fluxes in kg/m2/s (SI units) # convwf : kg/m2/s = mm/s -> m/s convwf = 1.e-3 pres = tost.data*0. denflxh[t,...] = (-sw.alpha(sost.data,tost.data,pres)/sw.cp(sost.data,tost.data,pres))*heft.data if empsw == 0: denflxw[t,...] = (rhonl+1000.)*sw.beta(sost.data,tost.data,pres)*sost.data*empt.data*convwf else: denflxw[t,...] = (rhonl+1000.)*sw.beta(sost.data,tost.data,pres)*empt.data*convwf denflx [t,...] = denflxh[t,...] + denflxw[t,...] denflx [t,...].mask = maski denflxh[t,...].mask = maski denflxw[t,...].mask = maski denflx [t,...] = maskVal(denflx [t,...], valmask) denflxh[t,...] = maskVal(denflxh[t,...], valmask) denflxw[t,...] = maskVal(denflxw[t,...], valmask) dflxh = denflxh.data[t,:,:] dflxw = denflxw.data[t,:,:] # # Transformation (integral of density flux on density outcrops)
def test(fileout='python-test.txt'): r"""Copy of the Matlab test. Modifications: Phil Morgan 03-12-12. Lindsay Pender, Converted to ITS-90. """ f = open(fileout, 'w') asterisks = '*' * 76 f.write(asterisks) f.write('\n TEST REPORT ') f.write('\n') f.write('\n SEA WATER LIBRARY %s' % sw.__version__) f.write('\n') # Show some info about this Python. f.write('\npython version: %s' % sys.version) f.write('\n on %s computer %s' % (uname()[0], uname()[-1])) f.write('\n') f.write('\n') f.write(asctime(localtime())) f.write('\n') f.write('\n') # Test main module ptmp. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: ptmp') f.write('\n** and SUB-MODULE: adtg') f.write('\n%s' % asterisks) f.write('\n') f.write('\n') # Test 1 - data from Unesco 1983 p45. T = np.array([[0, 0, 0, 0, 0, 0], [10, 10, 10, 10, 10, 10], [20, 20, 20, 20, 20, 20], [30, 30, 30, 30, 30, 30], [40, 40, 40, 40, 40, 40]]) T = T / 1.00024 S = np.array([[25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35]]) P = np.array([[0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000]]) Pr = np.array([0, 0, 0, 0, 0, 0]) UN_ptmp = np.array([[0, -0.3061, -0.9667, 0, -0.3856, -1.0974], [10, 9.3531, 8.4684, 10, 9.2906, 8.3643], [20, 19.0438, 17.9426, 20, 18.9985, 17.8654], [30, 28.7512, 27.4353, 30, 28.7231, 27.3851], [40, 38.4607, 36.9254, 40, 38.4498, 36.9023]]) PT = sw.ptmp(S, T, P, Pr) * 1.00024 # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from UNESCO 1983 ') f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p45)') f.write('\n%s' % asterisks) f.write('\n') m, n = S.shape # TODO: so many loops there must be a better way. for icol in range(0, n): f.write('\n Sal Temp Press PTMP ptmp') f.write('\n (psu) (C) (db) (C) (C)\n') result = np.vstack((S[:, icol], T[:, icol], P[:, icol], UN_ptmp[:, icol], PT[:, icol])) for iline in range(0, m): f.write(" %4.0f %4.0f %5.0f %8.4f %11.5f\n" % tuple(result[:, iline])) # Test main module svan. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: svan') f.write('\n** and SUB-MODULE: dens dens0 smow seck pden ptmp') f.write('\n%s' % asterisks) # Test data FROM: Unesco Tech. Paper in Marine Sci. No. 44, p22. s = np.array([0, 0, 0, 0, 35, 35, 35, 35]) p = np.array([0, 10000, 0, 10000, 0, 10000, 0, 10000]) t = np.array([0, 0, 30, 30, 0, 0, 30, 30]) / 1.00024 UN_svan = np.array([2749.54, 2288.61, 3170.58, 3147.85, 0.0, 0.00, 607.14, 916.34]) SVAN = sw.svan(s, t, p) # DISPLAY RESULTS f.write('\n') f.write('\n%s' % asterisks) f.write('\n') f.write('\nComparison of accepted values from UNESCO 1983') f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p22)') f.write('\n%s' % asterisks) f.write('\n') f.write('\n Sal Temp Press SVAN svan') f.write('\n (psu) (C) (db) (1e-8*m3/kg) (1e-8*m3/kg)\n') result = np.vstack([s, t, p, UN_svan, 1e+8 * SVAN]) for iline in range(0, len(SVAN)): f.write(" %4.0f %4.0f %5.0f %11.2f %11.3f\n" % tuple(result[:, iline])) # Test main module salt. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: salt') f.write('\n** and SUB-MODULE: salrt salrp sals') f.write('\n%s' % asterisks) f.write('\n') # Test 1 - data from Unesco 1983 p9. R = np.array([1, 1.2, 0.65]) # cndr = R. T = np.array([15, 20, 5]) / 1.00024 P = np.array([0, 2000, 1500]) #Rt = np.array([ 1, 1.0568875, 0.81705885]) UN_S = np.array([35, 37.245628, 27.995347]) S = sw.salt(R, T, P) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from UNESCO 1983 ') f.write('\n(Unesco Tech. Paper in Marine Sci. No. 44, p9)') f.write('\n%s' % asterisks) f.write('\n') f.write('\n Temp Press R S salt') f.write('\n (C) (db) (no units) (psu) (psu)\n') table = np.vstack([T, P, R, UN_S, S]) m, n = table.shape for iline in range(0, n): f.write(" %4.0f %4.0f %8.2f %11.6f %14.7f\n" % tuple(table[:, iline])) # Test main module cndr. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: cndr') f.write('\n** and SUB-MODULE: salds') f.write('\n%s' % asterisks) # Test 1 - data from Unesco 1983 p9. T = np.array([0, 10, 0, 10, 10, 30]) / 1.00024 P = np.array([0, 0, 1000, 1000, 0, 0]) S = np.array([25, 25, 25, 25, 40, 40]) UN_R = np.array([0.498088, 0.654990, 0.506244, 0.662975, 1.000073, 1.529967]) R = sw.cndr(S, T, P) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from UNESCO 1983 ') f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p14)') f.write('\n%s' % asterisks) f.write('\n') f.write('\n') f.write('\n Temp Press S cndr cndr') f.write('\n (C) (db) (psu) (no units) (no units)\n') table = np.vstack([T, P, S, UN_R, R]) m, n = table.shape for iline in range(0, n): f.write(" %4.0f %4.0f %8.6f %11.6f %14.8f\n" % tuple(table[:, iline])) # Test main module depth. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: depth') f.write('\n%s' % asterisks) # Test data - matrix "pressure", vector "lat" Unesco 1983 data p30. lat = np.array([0, 30, 45, 90]) P = np.array([[500, 500, 500, 500], [5000, 5000, 5000, 5000], [10000, 10000, 10000, 10000]]) UN_dpth = np.array([[496.65, 496.00, 495.34, 494.03], [4915.04, 4908.56, 4902.08, 4889.13], [9725.47, 9712.65, 9699.84, 9674.23]]) dpth = sw.dpth(P, lat) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from Unesco 1983 ') f.write('\n(Unesco Tech. Paper in Marine Sci. No. 44, p28)') f.write('\n%s' % asterisks) f.write('\n') f.write('\n') for irow in range(0, 3): f.write('\n Lat Press DPTH dpth') f.write('\n (degree) (db) (meter) (meter)\n') table = np.vstack([lat, P[irow, :], UN_dpth[irow, :], dpth[irow, :]]) m, n = table.shape for iline in range(0, n): f.write(" %6.3f %6.0f %8.2f %8.3f\n" % tuple(table[:, iline])) # Test main module fp. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: fp') f.write('\n%s' % asterisks) # Test 1 - UNESCO data p.30. S = np.array([[5, 10, 15, 20, 25, 30, 35, 40], [5, 10, 15, 20, 25, 30, 35, 40]]) P = np.array([[0, 0, 0, 0, 0, 0, 0, 0], [500, 500, 500, 500, 500, 500, 500, 500]]) UN_fp = np.array([[-0.274, -0.542, -0.812, -1.083, -1.358, -1.638, -1.922, -2.212], [-0.650, -0.919, -1.188, -1.460, -1.735, -2.014, -2.299, -2.589]]) FP = sw.fp(S, P) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from UNESCO 1983 ') f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p30)') f.write('\n%s' % asterisks) f.write('\n') f.write('\n') for irow in range(0, 2): f.write('\n Sal Press fp fp') f.write('\n (psu) (db) (C) (C)\n') table = np.vstack([S[irow, :], P[irow, :], UN_fp[irow, :], FP[irow, :]]) m, n = table.shape for iline in range(0, n): f.write(" %4.0f %5.0f %8.3f %11.4f\n" % tuple(table[:, iline])) # Test main module cp. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: cp') f.write('\n%s' % asterisks) # Test 1. # Data from Pond and Pickard Intro. Dynamical Oceanography 2nd ed. 1986 T = np.array([[0, 0, 0, 0, 0, 0], [10, 10, 10, 10, 10, 10], [20, 20, 20, 20, 20, 20], [30, 30, 30, 30, 30, 30], [40, 40, 40, 40, 40, 40]]) / 1.00024 S = np.array([[25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35]]) P = np.array([[0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000]]) UN_cp = np.array([[4048.4, 3896.3, 3807.7, 3986.5, 3849.3, 3769.1], [4041.8, 3919.6, 3842.3, 3986.3, 3874.7, 3804.4], [4044.8, 3938.6, 3866.7, 3993.9, 3895.0, 3828.3], [4049.1, 3952.0, 3883.0, 4000.7, 3909.2, 3844.3], [4051.2, 3966.1, 3905.9, 4003.5, 3923.9, 3868.3]]) CP = sw.cp(S, T, P) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from UNESCO 1983 ') f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p37)') f.write('\n%s' % asterisks) f.write('\n') m, n = S.shape f.write('\n') for icol in range(0, n): f.write('\n Sal Temp Press Cp cp') f.write('\n (psu) (C) (db) (J/kg.C) (J/kg.C)\n') result = np.vstack([S[:, icol], T[:, icol], P[:, icol], UN_cp[:, icol], CP[:, icol]]) for iline in range(0, m): f.write(" %4.0f %4.0f %5.0f %8.1f %11.2f\n" % tuple(result[:, iline])) # Test main module svel. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: svel') f.write('\n%s' % asterisks) # Test 1. # Data from Pond and Pickard Intro. Dynamical Oceanography 2nd ed. 1986 T = np.array([[0, 0, 0, 0, 0, 0], [10, 10, 10, 10, 10, 10], [20, 20, 20, 20, 20, 20], [30, 30, 30, 30, 30, 30], [40, 40, 40, 40, 40, 40]]) / 1.00024 S = np.array([[25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35]]) P = np.array([[0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000], [0, 5000, 10000, 0, 5000, 10000]]) UN_svel = np.array([[1435.8, 1520.4, 1610.4, 1449.1, 1534.0, 1623.2], [1477.7, 1561.3, 1647.4, 1489.8, 1573.4, 1659.0], [1510.3, 1593.6, 1676.8, 1521.5, 1604.5, 1687.2], [1535.2, 1619.0, 1700.6, 1545.6, 1629.0, 1710.1], [1553.4, 1638.0, 1719.2, 1563.2, 1647.3, 1727.8]]) SVEL = sw.svel(S, T, P) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from UNESCO 1983 ') f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p50)') f.write('\n%s' % asterisks) f.write('\n') m, n = SVEL.shape f.write('\n') for icol in range(0, n): f.write('\n Sal Temp Press SVEL svel') f.write('\n (psu) (C) (db) (m/s) (m/s)\n') result = np.vstack([S[:, icol], T[:, icol], P[:, icol], UN_svel[:, icol], SVEL[:, icol]]) for iline in range(0, m): f.write(" %4.0f %4.0f %5.0f %8.1f %11.3f\n" % tuple(result[:, iline])) # Test submodules alpha beta aonb. f.write('\n%s' % asterisks) f.write('\n** and SUB-MODULE: alpha beta aonb') f.write('\n%s' % asterisks) # Data from McDouogall 1987. s = 40 PT = 10 p = 4000 beta_lit = 0.72088e-03 aonb_lit = 0.34763 alpha_lit = aonb_lit * beta_lit BETA = sw.beta(s, PT, p, pt=True) ALPHA = sw.alpha(s, PT, p, pt=True) AONB = sw.aonb(s, PT, p, pt=True) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from MCDOUGALL 1987 ') f.write('\n%s' % asterisks) f.write('\n') f.write('\n') f.write('\n Sal Temp Press BETA beta') f.write('\n (psu) (C) (db) (psu^-1) (psu^-1)\n') table = np.hstack([s, PT, p, beta_lit, BETA]) f.write(" %4.0f %4.0f %5.0f %11.4e %11.5e\n" % tuple(table)) f.write('\n Sal Temp Press AONB aonb') f.write('\n (psu) (C) (db) (psu C^-1) (psu C^-1)\n') table = np.hstack([s, PT, p, aonb_lit, AONB]) f.write(" %4.0f %4.0f %5.0f %8.5f %11.6f\n" % tuple(table)) f.write('\n Sal Temp Press ALPHA alpha') f.write('\n (psu) (C) (db) (psu^-1) (psu^-1)\n') table = np.hstack([s, PT, p, alpha_lit, ALPHA]) f.write(" %4.0f %4.0f %5.0f %11.4e %11.4e\n" % tuple(table)) # Test main moduleS satO2 satN2 satAr. f.write('\n%s' % asterisks) f.write('\n** TESTING MODULE: satO2 satN2 satAr') f.write('\n%s' % asterisks) f.write('\n') # Data from Weiss 1970. T = np.array([[-1, -1], [10, 10], [20, 20], [40, 40]]) / 1.00024 S = np.array([[20, 40], [20, 40], [20, 40], [20, 40]]) lit_O2 = np.array([[9.162, 7.984], [6.950, 6.121], [5.644, 5.015], [4.050, 3.656]]) lit_N2 = np.array([[16.28, 14.01], [12.64, 11.01], [10.47, 9.21], [7.78, 6.95]]) lit_Ar = np.array([[0.4456, 0.3877], [0.3397, 0.2989], [0.2766, 0.2457], [0.1986, 0.1794]]) O2 = sw.satO2(S, T) N2 = sw.satN2(S, T) Ar = sw.satAr(S, T) # Display results. f.write('\n') f.write('\n%s' % asterisks) f.write('\nComparison of accepted values from Weiss, R.F. 1979 ') f.write('\n"The solubility of nitrogen, oxygen and argon in water') f.write('\n and seawater." Deep-Sea Research., 1970, Vol 17, pp721-735.') f.write('\n%s' % asterisks) f.write('\n') m, n = S.shape f.write('\n') for icol in range(0, n): f.write('\n Sal Temp O2 satO2') f.write('\n (psu) (C) (ml/l) (ml/l)\n') result = np.vstack([S[:, icol], T[:, icol], lit_O2[:, icol], O2[:, icol]]) for iline in range(0, m): f.write(" %4.0f %4.0f %8.2f %9.3f\n" % tuple(result[:, iline])) for icol in range(0, n): f.write('\n Sal Temp N2 satN2') f.write('\n (psu) (C) (ml/l) (ml/l)\n') result = np.vstack([S[:, icol], T[:, icol], lit_N2[:, icol], N2[:, icol]]) for iline in range(0, m): f.write(" %4.0f %4.0f %8.2f %9.3f\n" % tuple(result[:, iline])) for icol in range(0, n): f.write('\n Sal Temp Ar satAr') f.write('\n (psu) (C) (ml/l) (ml/l)\n') result = np.vstack([S[:, icol], T[:, icol], lit_Ar[:, icol], Ar[:, icol]]) for iline in range(0, m): f.write(" %4.0f %4.0f %8.4f %9.4f\n" % tuple(result[:, iline]))