|
16 | 16 | # |
17 | 17 | # ECCOv4 uses the $z^*$ coordinate system in which the depth of the vertical coordinate, $z^*$ varies with time as: |
18 | 18 | # |
19 | | -# $$ z^* = \frac{z - \eta(x,y,t)}{H(x,y) + \eta(x,y,t)} H(x,y)$$ |
| 19 | +# \begin{equation} |
| 20 | +# z^* = \frac{z - \eta(x,y,t)}{H(x,y) + \eta(x,y,t)} H(x,y) |
| 21 | +# \end{equation} |
20 | 22 | # |
21 | 23 | # With $H$ being the model depth, $\eta$ being the model sea level anomaly, and $z$ being depth. |
22 | 24 | # |
|
45 | 47 | # |
46 | 48 | # To make budget calculations easier we provide the scaled velocities quantities ``UVELMASS`` and ``VVELMASS``, |
47 | 49 | # |
48 | | -# \begin{equation} |
| 50 | +# \begin{align} |
49 | 51 | # \mathit{UVELMASS}(x,y,k) = \mathit{UVEL}(x,y,k) \times \mathit{hFacW}(x,y,k) \times s^{*}(x,y,k,t) |
50 | | -# \end{equation} |
| 52 | +# \end{align} |
51 | 53 | # and |
52 | | -# \begin{equation} |
| 54 | +# \begin{align} |
53 | 55 | # \mathit{VVELMASS}(x,y,k) = \mathit{VVEL}(x,y,k) \times \mathit{hFacS}(x,y,k) \times s^{*}(x,y,k,t) |
54 | | -# \end{equation} |
| 56 | +# \end{align} |
55 | 57 | # |
56 | | -# > **Note:** The word **mass** in ``UVELMASS`` and ``VVELMASS`` is confusing since there is no mass involved here. Think of these terms as simply being ``UVEL`` and ``VVEL`` multiplied by the scaled grid cell area fraction. |
| 58 | +# It is worth noting that the word **mass** in ``UVELMASS`` and ``VVELMASS`` is confusing since there is no mass involved here. Think of these terms as simply being ``UVEL`` and ``VVEL`` multiplied by the fraction of the grid cell height that is open grid cell face across which the volume transport occurs. Partial cell bathymetry can make this fraction (hFacW, hFacS) less than one, and the $s^*$ scaling factor further adjusts this fraction higher or lower through time. |
57 | 59 | # |
58 | 60 | # Fully closing the budget requires the vertical volume fluxes across the top and bottom 'w' faces of the grid cell and surface freshwater fluxes. Regarding vertical volume fluxes, there are no $s^*$ or ``hFac`` equivalent scaling factors that modify our top and bottom grid cell areas. Therefore, vertical volume fluxes through 'w' faces are simply: |
59 | 61 | # |
|
71 | 73 | # |
72 | 74 | # Greatbatch, 1994. J. of Geophys. Res. Oceans, https://doi.org/10.1029/94JC00847 |
73 | 75 |
|
74 | | -# # Evaluating the model sea level anomaly ``ETAN`` volume budget |
| 76 | +# ## Evaluating the model sea level anomaly ``ETAN`` volume budget |
75 | 77 |
|
76 | 78 | # We will evalute |
77 | 79 | # |
|
101 | 103 | # |
102 | 104 | # The ``UVELMASS, VVELMASS, WVELMASS`` and ``oceFWflx`` terms must be time-average quantities between the monthly $\eta$ snapshots. |
103 | 105 | # |
104 | | -# ## Prepare environment and loading the relevant model variables |
| 106 | +# ### Prepare environment and loading the relevant model variables |
105 | 107 |
|
106 | 108 | # In[1]: |
107 | 109 |
|
|
117 | 119 | warnings.filterwarnings('ignore') |
118 | 120 |
|
119 | 121 |
|
120 | | -# In[2]: |
| 122 | +# In[62]: |
121 | 123 |
|
122 | 124 |
|
123 | 125 | # Density kg/m^3 |
124 | 126 | rhoconst = 1029 |
125 | 127 |
|
126 | 128 | ## needed to convert surface mass fluxes to volume fluxes |
127 | 129 |
|
128 | | -# lat/lon resolution in degrees to interpolate the model fields for the purposes of plotting |
| 130 | +# lat/lon resolution in degrees to interpolate the model |
| 131 | +# fields for the purposes of plotting |
129 | 132 | map_dx = .2 |
130 | 133 | map_dy = .2 |
131 | 134 |
|
|
180 | 183 |
|
181 | 184 |
|
182 | 185 | # load one extra year worth of snapshots |
183 | | -ecco_monthly_snaps = ecco.recursive_load_ecco_var_from_years_nc(data_dir, vars_to_load=['ETAN'], years_to_load=range(year_start, year_end+1)).load() |
| 186 | +ecco_monthly_snaps = ecco.recursive_load_ecco_var_from_years_nc(data_dir, vars_to_load=['ETAN'], years_to_load=range(year_start, year_end+1)).load() |
184 | 187 |
|
185 | 188 | num_months = len(ecco_monthly_snaps.time.values) |
186 | 189 | # drop the last 11 months so that we have one snapshot at the beginning and end of each month within the |
|
200 | 203 |
|
201 | 204 |
|
202 | 205 | # find the record of the last ETAN snapshot |
203 | | -last_record_date = ecco.extract_yyyy_mm_dd_hh_mm_ss_from_datetime64(ecco_monthly_snaps.time[-1].values) |
| 206 | +last_record_date = |
| 207 | + ecco.extract_yyyy_mm_dd_hh_mm_ss_from_datetime64(ecco_monthly_snaps.time[-1].values) |
204 | 208 | print(last_record_date) |
205 | 209 | last_record_year = last_record_date[0] |
206 | 210 |
|
|
236 | 240 | print('number of monthly snapshot records: ', len(ecco_monthly_snaps.time)) |
237 | 241 |
|
238 | 242 |
|
239 | | -# ## Create the xgcm 'grid' object |
| 243 | +# ### Create the xgcm 'grid' object |
240 | 244 | # |
241 | 245 | # the xgcm grid object makes it easy to make flux divergence calculations across different tiles of the lat-lon-cap grid. |
242 | 246 |
|
|
415 | 419 | cmin=-1, cmax=1, \ |
416 | 420 | cmap=cmocean.cm.balance, user_lon_0=-67,\ |
417 | 421 | dx=map_dx,dy=map_dy); |
| 422 | + |
418 | 423 | plt.title('Actual $\Delta \eta$ [m]', fontsize=20); |
419 | 424 |
|
420 | 425 |
|
|
440 | 445 | tmp = ecco.extract_yyyy_mm_dd_hh_mm_ss_from_datetime64(G_total_tendency.time[100].values) |
441 | 446 | print(tmp) |
442 | 447 | ecco.plot_proj_to_latlon_grid(ecco_grid.XC, ecco_grid.YC, G_total_tendency.isel(time=100), show_colorbar=True, cmin=-1e-7, cmax=1e-7, cmap=cmocean.cm.balance, user_lon_0=-67, dx=map_dx,dy=map_dy); |
| 448 | + |
443 | 449 | plt.title('$\partial \eta / \partial t$ [m/s] during ' + |
444 | 450 | str(tmp[0]) +'/' + str(tmp[1]), fontsize=20); |
445 | 451 |
|
|
621 | 627 | fontsize=20); |
622 | 628 |
|
623 | 629 |
|
624 | | -# These values are all essentially zero (at the noise level). On average the only vertical flux divergence in the column is across the ocean surface, because the column integrated vertical flux divergences below the surface is in the noise. This may be related to the $z^*$ coordinate system. When water is added or removed from he column, $\eta$ changes and the depth levels of top and bottom 'w' faces of the grid cells are scaled up or down via the $s*$ factor. Because grid cells change thickness via $s*$ no vertical flux divergence is required. Thus, the fact that the vertical flux divergences are zero may be an artifact of the $z*$ coordinate system. If you, dear reader, have a better explanation, please share. |
| 630 | +# These values are everywhere essentially zero (numerical noise). On average, the only vertical flux divergence in the column is across the ocean surface. Below the surface, the sum of vertical flux divergence in all tracer cells in the column must be zero because any divergence in any one particular cell is exactly offset by convergence in another cell. Net convergence into the column manifests as a positive vertical velocity at the surface which is equal to oceFWflux in the time-mean. **Thanks to Hong Zhang for comments that improved this explanation** |
625 | 631 |
|
626 | 632 | # ### Horizontal Volume Flux Divergence |
627 | 633 |
|
|
858 | 864 | plt.grid() |
859 | 865 |
|
860 | 866 | plt.subplots_adjust(hspace = .5, wspace=.2) |
861 | | -plt.suptitle('Volume Budget for one Arctic Ocean point',fontsize=20); |
| 867 | +plt.suptitle('Volume Budget for one Arctic Ocean point', |
| 868 | + fontsize=20); |
862 | 869 |
|
863 | 870 |
|
864 | 871 | # Indeed, the volume divergence term does contribute to $\eta$ variations at this one point. |
|
875 | 882 | plt.title('d(eta)/d(t) from surf. fluxes in 1995 [m/s]'); |
876 | 883 |
|
877 | 884 |
|
878 | | -# # Predicted vs. actual $\eta$ |
| 885 | +# ## Predicted vs. actual $\eta$ |
879 | 886 | # |
880 | 887 | # As we have shown, in our Boussinesq model the only term that can change global mean model sea level anomaly $\eta$ is net surface freshwater flux. Let us compare the time-evolution of $\eta$ implied by surface freshwater fluxes and the actual $\eta$ from the model output. |
881 | 888 | # |
|
887 | 894 |
|
888 | 895 | area_masked = ecco_grid.rA.where(ecco_grid.maskC.isel(k=0) == 1) |
889 | 896 |
|
890 | | -dETA_per_month_predicted_from_surf_fluxes = ((G_surf_fluxes * area_masked).sum(dim=('i','j','tile'))/area_masked.sum())*secs_per_month |
| 897 | +dETA_per_month_predicted_from_surf_fluxes = ((G_surf_fluxes * area_masked).sum(dim=('i','j','tile')) / |
| 898 | + area_masked.sum())*secs_per_month |
891 | 899 |
|
892 | 900 | ETA_predicted_by_surf_fluxes = np.cumsum(dETA_per_month_predicted_from_surf_fluxes.values) |
893 | 901 |
|
894 | | -ETA_from_ETAN = (ecco_monthly_snaps.ETAN * area_masked).sum(dim=('i','j','tile'))/ area_masked.sum() |
| 902 | +ETA_from_ETAN = |
| 903 | + (ecco_monthly_snaps.ETAN * area_masked).sum(dim=('i','j','tile')) / |
| 904 | + area_masked.sum() |
895 | 905 |
|
896 | 906 | # plotting |
897 | 907 | plt.figure(figsize=(14,5)); |
|
901 | 911 | plt.grid() |
902 | 912 | plt.ylabel('global mean $\eta$'); |
903 | 913 | plt.legend(('predicted', 'actual')); |
904 | | -plt.title('$\eta(t)$ as predicted from net surface fluxes and model ETAN [m]', fontsize=20); |
| 914 | +plt.title('$\eta(t)$ as predicted from net surface fluxes and model ETAN [m]', |
| 915 | + fontsize=20); |
905 | 916 |
|
906 | 917 |
|
907 | | -# > **Note:** the first predicted $\eta$ occurs at the end of the first month (one month time integral of $\partial \eta / \partial t$. The first *actual* $\eta$ is set to be zero. |
| 918 | +# The first predicted $\eta$ occurs at the end of the first month (one month time integral of $\partial \eta / \partial t$. The first *actual* $\eta$ is set to be zero. |
908 | 919 | # |
909 | 920 | # The above plot is another way of confirming that in our Boussinesq model the only term that can change global mean model sea level anomaly $\eta$ is net surface freshwater flux. To account for changes in global mean density we must apply the Greatbatch correction, inverse-barometer correction, and a correction term to account for the fact that sea-ice does not 'float' on top of the ocean but in fact displaces seawater upwards. All of these corrections are made for the term ``SSH``, dynamic sea surface height anomaly (not shown here). |
910 | 921 |
|
|
933 | 944 | # the -0.13 is to make the starting value comparable with WCRP fig 16. |
934 | 945 | plt.bar(annual_mean_GMSL_due_to_mass_fluxes.year.values[12:num_years], 1000*(annual_mean_GMSL_due_to_mass_fluxes.values[12:num_years]-.017), color='k') |
935 | 946 | plt.grid() |
936 | | -plt.xticks(np.arange(2005, annual_mean_GMSL_due_to_mass_fluxes.year.values[-1]+1,step=1)); |
| 947 | +plt.xticks(np.arange(2005, |
| 948 | + annual_mean_GMSL_due_to_mass_fluxes.year.values[-1]+1,step=1)); |
937 | 949 | plt.title('Sea level (mm) caused by mass fluxes'); |
938 | 950 |
|
939 | 951 |
|
|
0 commit comments