├── .gitignore ├── docu ├── matvis │ ├── .dropbox.attr │ ├── LT.png │ ├── Lu.png │ ├── Lv.png │ ├── GTx.png │ ├── GTy.png │ ├── Gqx.png │ ├── Gqy.png │ ├── Gux.png │ ├── Guy.png │ ├── Gvx.png │ ├── Gvy.png │ ├── ITq.png │ ├── ITu.png │ ├── ITv.png │ ├── IqT.png │ ├── Iqu.png │ ├── Iqv.png │ ├── IuT.png │ ├── Iuq.png │ ├── Iuv.png │ ├── IvT.png │ ├── Ivq.png │ ├── Ivu.png │ ├── LLT.png │ ├── LLu.png │ ├── LLv.png │ ├── AL_stencil1.png │ ├── AL_stencil2.png │ ├── relative_nodes.png │ └── scripts │ │ ├── grid_vis.py │ │ ├── matvis.py │ │ ├── forc_vis.py │ │ └── grid_vis_rel.py ├── thesis_methods.pdf ├── thesis_appendix.pdf └── swm_documentation.pdf ├── plot ├── plots │ ├── e_mean.png │ ├── spec_eke.pdf │ ├── energymap.png │ ├── power_maps.png │ ├── bs_timescales.pdf │ ├── mean_section.pdf │ ├── power_maps_bs.png │ ├── pv_gradient.pdf │ ├── Ro_hist_nadiga.pdf │ ├── budget_closure.pdf │ ├── energy_timeseries.pdf │ ├── power_maps_bs_weak.png │ ├── relvort_snapshot.png │ ├── energy_budget_terms.png │ ├── power_maps_bs_cntrl.png │ ├── power_maps_bs_strong.png │ └── power_maps_bs_crosssection.png ├── mean_e_plot.py ├── spec_plot.py ├── last_timestep_plot.py ├── Ro_hist_plot.py ├── mean_sections_plot.py ├── powermap_plot.py ├── pv_gradient.py ├── powermap_bs_crosssection.py ├── Ro_hist_plot_balu.py ├── streamplot.py ├── energy_timeseries.py ├── powermap_plot_bs.py └── energymap_plot.py ├── calc ├── process │ ├── var_subset_e.py │ ├── var_subset.py │ └── var_subset_last.py ├── mean_e_calc.py ├── misc │ ├── streamfunction.py │ ├── streamf_calc.py │ ├── pv_calc.py │ ├── pv_plot.py │ ├── tempautocorr.py │ ├── tempautocorr_plot.py │ ├── ReRo_hist_plot.py │ ├── cospec_calc.py │ ├── Re_hist_plot.py │ ├── trispec_calc.py │ ├── ReRo_hist.py │ ├── taylor_diagram_plot.py │ ├── taylor_convergence.py │ ├── trispec_plot.py │ ├── cospec_plot.py │ ├── tempautocorr_plot_bf.py │ ├── spec_ens _calc.py │ ├── trispec.py │ ├── Re_hist_calc.py │ ├── diss_vis.py │ ├── c_diss_plot.py │ ├── Re_hist_calc_bs.py │ └── Re_hist_calc_bs_old.py ├── Ro_hist_calc.py ├── floats │ ├── floats_plot.py │ ├── floats_plot_bf.py │ ├── floats_calc_meanflow.py │ └── floats_calc.py ├── power_inout_calc.py ├── mean_calc.py ├── mean_timeseries_calc.py ├── spec_calc.py └── power_inout_bs_calc.py ├── swm_run.py ├── README.md ├── swm_integration.py ├── swm_rhs.py └── swm_output.py /.gitignore: -------------------------------------------------------------------------------- 1 | data 2 | *.nc 3 | -------------------------------------------------------------------------------- /docu/matvis/.dropbox.attr: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /docu/matvis/LT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/LT.png -------------------------------------------------------------------------------- /docu/matvis/Lu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Lu.png -------------------------------------------------------------------------------- /docu/matvis/Lv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Lv.png -------------------------------------------------------------------------------- /docu/matvis/GTx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/GTx.png -------------------------------------------------------------------------------- /docu/matvis/GTy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/GTy.png -------------------------------------------------------------------------------- /docu/matvis/Gqx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Gqx.png -------------------------------------------------------------------------------- /docu/matvis/Gqy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Gqy.png -------------------------------------------------------------------------------- /docu/matvis/Gux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Gux.png -------------------------------------------------------------------------------- /docu/matvis/Guy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Guy.png -------------------------------------------------------------------------------- /docu/matvis/Gvx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Gvx.png -------------------------------------------------------------------------------- /docu/matvis/Gvy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Gvy.png -------------------------------------------------------------------------------- /docu/matvis/ITq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/ITq.png -------------------------------------------------------------------------------- /docu/matvis/ITu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/ITu.png -------------------------------------------------------------------------------- /docu/matvis/ITv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/ITv.png -------------------------------------------------------------------------------- /docu/matvis/IqT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/IqT.png -------------------------------------------------------------------------------- /docu/matvis/Iqu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Iqu.png -------------------------------------------------------------------------------- /docu/matvis/Iqv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Iqv.png -------------------------------------------------------------------------------- /docu/matvis/IuT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/IuT.png -------------------------------------------------------------------------------- /docu/matvis/Iuq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Iuq.png -------------------------------------------------------------------------------- /docu/matvis/Iuv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Iuv.png -------------------------------------------------------------------------------- /docu/matvis/IvT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/IvT.png -------------------------------------------------------------------------------- /docu/matvis/Ivq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Ivq.png -------------------------------------------------------------------------------- /docu/matvis/Ivu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/Ivu.png -------------------------------------------------------------------------------- /docu/matvis/LLT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/LLT.png -------------------------------------------------------------------------------- /docu/matvis/LLu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/LLu.png -------------------------------------------------------------------------------- /docu/matvis/LLv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/LLv.png -------------------------------------------------------------------------------- /docu/thesis_methods.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/thesis_methods.pdf -------------------------------------------------------------------------------- /plot/plots/e_mean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/e_mean.png -------------------------------------------------------------------------------- /plot/plots/spec_eke.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/spec_eke.pdf -------------------------------------------------------------------------------- /docu/thesis_appendix.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/thesis_appendix.pdf -------------------------------------------------------------------------------- /plot/plots/energymap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/energymap.png -------------------------------------------------------------------------------- /plot/plots/power_maps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/power_maps.png -------------------------------------------------------------------------------- /docu/matvis/AL_stencil1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/AL_stencil1.png -------------------------------------------------------------------------------- /docu/matvis/AL_stencil2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/AL_stencil2.png -------------------------------------------------------------------------------- /docu/swm_documentation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/swm_documentation.pdf -------------------------------------------------------------------------------- /plot/plots/bs_timescales.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/bs_timescales.pdf -------------------------------------------------------------------------------- /plot/plots/mean_section.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/mean_section.pdf -------------------------------------------------------------------------------- /plot/plots/power_maps_bs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/power_maps_bs.png -------------------------------------------------------------------------------- /plot/plots/pv_gradient.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/pv_gradient.pdf -------------------------------------------------------------------------------- /docu/matvis/relative_nodes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/docu/matvis/relative_nodes.png -------------------------------------------------------------------------------- /plot/plots/Ro_hist_nadiga.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/Ro_hist_nadiga.pdf -------------------------------------------------------------------------------- /plot/plots/budget_closure.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/budget_closure.pdf -------------------------------------------------------------------------------- /plot/plots/energy_timeseries.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/energy_timeseries.pdf -------------------------------------------------------------------------------- /plot/plots/power_maps_bs_weak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/power_maps_bs_weak.png -------------------------------------------------------------------------------- /plot/plots/relvort_snapshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/relvort_snapshot.png -------------------------------------------------------------------------------- /plot/plots/energy_budget_terms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/energy_budget_terms.png -------------------------------------------------------------------------------- /plot/plots/power_maps_bs_cntrl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/power_maps_bs_cntrl.png -------------------------------------------------------------------------------- /plot/plots/power_maps_bs_strong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/power_maps_bs_strong.png -------------------------------------------------------------------------------- /plot/plots/power_maps_bs_crosssection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milankl/swm/HEAD/plot/plots/power_maps_bs_crosssection.png -------------------------------------------------------------------------------- /calc/process/var_subset_e.py: -------------------------------------------------------------------------------- 1 | ## READ VARIABLE FROM SEVERAL NCFILES and store subset of it as NPY 2 | from __future__ import print_function 3 | 4 | path = '/home/mkloewer/python/swm/' 5 | 6 | import os; os.chdir(path) # change working directory 7 | import numpy as np 8 | from netCDF4 import Dataset 9 | 10 | # OPTIONS 11 | runfolder = [10,11,12,13,14,15] 12 | sub = 4 13 | 14 | for r in runfolder: 15 | print(('Subsampling from run %i') % r) 16 | 17 | ## read data 18 | runpath = path+'data/run%04i' % r 19 | nce = Dataset(runpath+'/e.nc') 20 | e = nce['e'][:][::sub,:,:] 21 | nce.close() 22 | 23 | # save subset as .npy 24 | np.save(runpath+'/e_sub.npy',e) 25 | del e 26 | -------------------------------------------------------------------------------- /swm_run.py: -------------------------------------------------------------------------------- 1 | ## SHALLOW WATER MODEL 2 | from __future__ import print_function # tested with python 3.6 and 2.7.12 3 | 4 | # path 5 | import os 6 | path = os.getcwd() + '/' 7 | 8 | # import modules 9 | import numpy as np # version 1.11.3-py36 10 | from scipy import sparse # version 0.19-py36 11 | import time as tictoc 12 | from netCDF4 import Dataset # version 1.2.4-py36, hdf5 version 1.8.17-py36, hdf4 version 4.2.12-py36 13 | import glob 14 | import zipfile 15 | 16 | ## import all functions 17 | exec(open(path+'swm_param.py').read()) 18 | exec(open(path+'swm_operators.py').read()) 19 | exec(open(path+'swm_rhs.py').read()) 20 | exec(open(path+'swm_integration.py').read()) 21 | exec(open(path+'swm_output.py').read()) 22 | 23 | ## set all parameters and initial conditions, and run model 24 | u,v,eta = set_param() 25 | u,v,eta = time_integration(u,v,eta) 26 | -------------------------------------------------------------------------------- /calc/mean_e_calc.py: -------------------------------------------------------------------------------- 1 | ## PRODUCE MEAN CALCULATIONS AND EXPORT AS .NPY 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import time as tictoc 8 | from netCDF4 import Dataset 9 | 10 | # OPTIONS 11 | runfolder = 15 12 | print('Calculating subgrid-EKE means from run ' + str(runfolder)) 13 | 14 | ## read data 15 | runpath = path+'data/run%04i' % runfolder 16 | 17 | skip = 5*365 18 | e = np.load(runpath+'/e_sub.npy')[skip:,:,:] 19 | print('run %i read.' % runfolder) 20 | 21 | ## create ouputfolder 22 | try: 23 | os.mkdir(runpath+'/analysis') 24 | except: 25 | pass 26 | 27 | ## U,V,H mean 28 | em = e.mean(axis=0) 29 | print('e mean done.') 30 | 31 | ## STORING 32 | dic = dict() 33 | all_var2export = ['em'] 34 | 35 | for v in all_var2export: 36 | exec('dic[v] ='+v) 37 | 38 | np.save(runpath+'/analysis/mean_e.npy',dic) 39 | print('Everything stored.') 40 | -------------------------------------------------------------------------------- /calc/process/var_subset.py: -------------------------------------------------------------------------------- 1 | ## READ VARIABLE FROM SEVERAL NCFILES and store subset of it as NPY 2 | from __future__ import print_function 3 | 4 | path = '/home/mkloewer/python/swm/' 5 | 6 | import os; os.chdir(path) # change working directory 7 | import numpy as np 8 | from netCDF4 import Dataset 9 | 10 | 11 | # OPTIONS 12 | runfolder = [14] 13 | sub = 4 14 | 15 | for r in runfolder: 16 | print(('Subsampling from run %i') % r) 17 | 18 | # read data 19 | runpath = path+'data/run%04i' % r 20 | 21 | ncu = Dataset(runpath+'/u.nc') 22 | u = ncu['u'][:][::sub,:,:] 23 | ncu.close() 24 | print('u read.') 25 | np.save(runpath+'/u_sub.npy',u) 26 | del u 27 | 28 | ncv = Dataset(runpath+'/v.nc') 29 | v = ncv['v'][:][::sub,:,:] 30 | ncv.close() 31 | print('v read.') 32 | np.save(runpath+'/v_sub.npy',v) 33 | del v 34 | 35 | nceta = Dataset(runpath+'/eta.nc') 36 | eta = nceta['eta'][:][::sub,:,:] 37 | time = nceta['t'][::sub] # in seconds 38 | t = time / 3600. / 24. # in days 39 | nceta.close() 40 | print('eta read.') 41 | np.save(runpath+'/eta_sub.npy',eta) 42 | np.save(runpath+'/t_sub.npy',time) 43 | del eta 44 | del time,t 45 | -------------------------------------------------------------------------------- /calc/process/var_subset_last.py: -------------------------------------------------------------------------------- 1 | ## READ VARIABLE FROM SEVERAL NCFILES and store subset of it as NPY 2 | from __future__ import print_function 3 | 4 | path = '/network/aopp/cirrus/pred/kloewer/swm_bf_cntrl/data/' 5 | #path = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 6 | 7 | import os; os.chdir(path) # change working directory 8 | import numpy as np 9 | from netCDF4 import Dataset 10 | 11 | # OPTIONS 12 | runfolder = [0,6] 13 | s = 40 # read s-th last time step 14 | 15 | 16 | for r in runfolder: 17 | print(('Store last time step from run %i') % r) 18 | 19 | ## read data 20 | runpath = path+'run%04i' % r 21 | 22 | ncu = Dataset(runpath+'/u.nc') 23 | u = ncu['u'][-s,:,:] 24 | ncu.close() 25 | print('u read.') 26 | np.save(runpath+'/u_last.npy',u) 27 | del u 28 | 29 | ncv = Dataset(runpath+'/v.nc') 30 | v = ncv['v'][-s,:,:] 31 | ncv.close() 32 | print('v read.') 33 | np.save(runpath+'/v_last.npy',v) 34 | del v 35 | 36 | nceta = Dataset(runpath+'/eta.nc') 37 | eta = nceta['eta'][-s,:,:] 38 | #time = nceta['t'][::sub] # in seconds 39 | #t = time / 3600. / 24. # in days 40 | nceta.close() 41 | print('eta read.') 42 | np.save(runpath+'/eta_last.npy',eta) 43 | del eta 44 | -------------------------------------------------------------------------------- /calc/misc/streamfunction.py: -------------------------------------------------------------------------------- 1 | # PLOT STREAMFUNCTION 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | from scipy.integrate import cumtrapz 8 | import matplotlib.pyplot as plt 9 | import time as tictoc 10 | from netCDF4 import Dataset 11 | import glob 12 | from cmocean import cm 13 | 14 | ## OPTIONS 15 | runfolder = [3,10] 16 | print('Compare mean plots from run ' + str(runfolder)) 17 | 18 | ## read data 19 | 20 | runpath1 = path+'data/run%04i' % runfolder[0] 21 | D1 = np.load(runpath1+'/analysis/mean.npy').all() 22 | param1 = np.load(runpath1+'/param.npy').all() 23 | 24 | # runpath2 = path+'data/run%04i' % runfolder[1] 25 | # D2 = np.load(runpath2+'/analysis/mean.npy').all() 26 | # param2 = np.load(runpath2+'/param.npy').all() 27 | # 28 | # runpath3 = path+'stoch/data/run%04i' % 5 29 | # D3 = np.load(runpath3+'/analysis/mean.npy').all() 30 | # param3 = np.load(runpath3+'/param.npy').all() 31 | 32 | ## CALCULATE STREAMFUNCTION 33 | global param 34 | param = np.load(runpath1+'/param.npy').all() 35 | exec(open(path+'swm_operators.py').read()) 36 | exec(open(path+'swm_output.py').read()) 37 | param['output'] = 0 38 | set_grad_mat() 39 | set_interp_mat() 40 | 41 | PSI1v = cumtrapz(v2mat(D1['vm']),axis=1,dx=param['dx'],initial=0) 42 | PSI1u = -cumtrapz(u2mat(D1['um']),axis=0,dx=param['dy'],initial=0) 43 | 44 | levs = np.linspace(-abs(PSI1u).max(),abs(PSI1u).max(),64) 45 | 46 | fig,(ax1,ax2) = plt.subplots(1,2,sharex=True,sharey=True) 47 | 48 | ax1.contourf(param['x_v'],param['y_v'],PSI1v,levs,cmap=cm.balance) 49 | ax2.contourf(param['x_u'],param['y_u'],PSI1u,levs,cmap=cm.balance) 50 | 51 | plt.show() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Project Status: Inactive – The project has reached a stable, usable state but is no longer being actively developed; support/maintenance will be provided as time allows.](https://www.repostatus.org/badges/latest/inactive.svg)](https://www.repostatus.org/#inactive) 2 | 3 | # swm - Shallow water model 4 | Shallow water equations solver with finite differences. Arakawa C-grid, Arakawa and Lamb advection scheme, Shchepetkin and O'Brian-like biharmonic diffusion operator. 4th order Runge-Kutta for time integration. 5 | 6 | A documentation is available at http://www.github.com/milankl/swm/tree/master/docu 7 | 8 | This model is written in python, relies on numpy, scipy and netCDF4. 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | # RUN 24 | 25 | You may want to change settings in swm_param.py before you run the model. Then simply do 26 | 27 | python swm_run.py 28 | 29 | # Energy budget-based backscatter 30 | 31 | An implementation of the energy budget-based backscatter as described in Kloewer et al 2018, Ocean Modelling can be found in the separate branch "backscatter". 32 | 33 | Copyright (C) 2018, Milan Kloewer (milan.kloewer@physics.ox.ac.uk, milank.de) 34 | 35 | # Citation 36 | 37 | If you use this package in your research, please cite us 38 | 39 | > Klöwer M, MF Jansen, M Claus, RJ Greatbatch and S Thomsen, 2018. *Energy budget-based backscatter in a shallow water model of a double gyre basin*, __Ocean Modelling__, 132, [10.1016/j.ocemod.2018.09.006](https://doi.org/10.1016/j.ocemod.2018.09.006) 40 | -------------------------------------------------------------------------------- /docu/matvis/scripts/grid_vis.py: -------------------------------------------------------------------------------- 1 | ## Visualize Arakawa C-grid numbering 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | 5 | nx = 3 6 | ny = 3 7 | 8 | Lx = nx 9 | Ly = ny 10 | 11 | dx = Lx/nx 12 | dy = Ly/ny 13 | 14 | # grid vectors for T-points 15 | x_T = np.arange(dx/2.,Lx,dx) 16 | y_T = np.arange(dy/2.,Ly,dy) 17 | 18 | # grid vectors for u-points 19 | x_u = x_T[:-1] + dx/2. 20 | y_u = y_T 21 | 22 | #grid vectors for v-points 23 | x_v = x_T 24 | y_v = y_T[:-1] + dy/2. 25 | 26 | # grid vectors for q-points 27 | x_q = np.arange(0,Lx+dx/2.,dx) 28 | y_q = np.arange(0,Ly+dy/2.,dy) 29 | 30 | ## meshgrid 31 | 32 | xx_T,yy_T = np.meshgrid(x_T,y_T) 33 | xx_u,yy_u = np.meshgrid(x_u,y_u) 34 | xx_v,yy_v = np.meshgrid(x_v,y_v) 35 | xx_q,yy_q = np.meshgrid(x_q,y_q) 36 | 37 | xx_T = xx_T.flatten() 38 | xx_u = xx_u.flatten() 39 | xx_v = xx_v.flatten() 40 | xx_q = xx_q.flatten() 41 | 42 | yy_T = yy_T.flatten() 43 | yy_u = yy_u.flatten() 44 | yy_v = yy_v.flatten() 45 | yy_q = yy_q.flatten() 46 | 47 | fig,ax = plt.subplots(1,1) 48 | 49 | ax.plot(xx_T,yy_T,'r.',ms=10,mec='k') 50 | ax.plot(xx_u,yy_u,'g.',ms=10,mec='k') 51 | ax.plot(xx_v,yy_v,'b.',ms=10,mec='k') 52 | ax.plot(xx_q,yy_q,'k.',ms=10) 53 | 54 | ax.plot(x_v,[0]*nx,'b.',ms=10,alpha=.6) 55 | ax.plot(x_v,[Ly]*nx,'b.',ms=10,alpha=.6) 56 | ax.plot([0]*ny,y_u,'g.',ms=10,alpha=.6) 57 | ax.plot([Lx]*ny,y_u,'g.',ms=10,alpha=.6) 58 | 59 | 60 | plt.grid() 61 | 62 | for xx,yy,vv in zip([xx_T,xx_u,xx_v,xx_q],[yy_T,yy_u,yy_v,yy_q],['T','u','v','q']): 63 | for i in range(len(xx)): 64 | ax.text(xx[i]+0.03,yy[i]+0.03,r'$'+vv+'_{%i}$' %(i+1),fontsize=15) 65 | 66 | ax.set_xlabel(r'$x$') 67 | ax.set_ylabel(r'$y$') 68 | 69 | ax.set_xticks(range(Lx+1)) 70 | ax.set_yticks(range(Ly+1)) 71 | 72 | ax.set_xlim(-0.1,nx+0.1) 73 | ax.set_ylim(-0.1,ny+0.1) 74 | 75 | ax.set_frame_on(False) 76 | 77 | dxstring = [(r'$%i\Delta x$' % i) if i > 1 else r'$\Delta x$' for i in range(1,nx)] 78 | dystring = [(r'$%i\Delta y$' % i) if i > 1 else r'$\Delta y$' for i in range(1,ny)] 79 | 80 | ax.set_xticklabels([r'$0$']+dxstring+[r'$L_x$']) 81 | ax.set_yticklabels([r'$0$']+dystring+[r'$L_y$']) 82 | plt.tight_layout() 83 | plt.show() -------------------------------------------------------------------------------- /calc/misc/streamf_calc.py: -------------------------------------------------------------------------------- 1 | ## PRODUCE MEAN CALCULATIONS FOR STREAMFUNCTIONS AND OUTPUT AS .NPY 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import time as tictoc 8 | from netCDF4 import Dataset 9 | import glob 10 | 11 | # OPTIONS 12 | runfolder = [2,3] 13 | print('Calculating means from run ' + str(runfolder)) 14 | 15 | ## read data 16 | for r,i in zip(runfolder,range(len(runfolder))): 17 | runpath = path+'data/run%04i' % r 18 | 19 | if i == 0: 20 | u = np.load(runpath+'/u_sub.npy') 21 | v = np.load(runpath+'/v_sub.npy') 22 | h = np.load(runpath+'/h_sub.npy') 23 | time = np.load(runpath+'/t_sub.npy') 24 | print('run %i read.' % r) 25 | 26 | else: 27 | u = np.concatenate((u,np.load(runpath+'/u_sub.npy'))) 28 | v = np.concatenate((v,np.load(runpath+'/v_sub.npy'))) 29 | h = np.concatenate((h,np.load(runpath+'/h_sub.npy'))) 30 | time = np.hstack((time,np.load(runpath+'/t_sub.npy'))) 31 | print('run %i read.' % r) 32 | 33 | t = time / 3600. / 24. # in days 34 | ## read param 35 | global param 36 | param = np.load(runpath+'/param.npy').all() 37 | param['dat_type'] = np.float32 38 | 39 | # import functions 40 | exec(open(path+'swm_param.py').read()) 41 | exec(open(path+'swm_operators.py').read()) 42 | exec(open(path+'swm_output.py').read()) 43 | param['output'] = 0 44 | 45 | set_grad_mat() 46 | set_interp_mat() 47 | set_lapl_mat() 48 | set_coriolis() 49 | 50 | tlen = len(time) 51 | ## create ouputfolder 52 | try: 53 | os.mkdir(runpath+'/analysis') 54 | except: 55 | pass 56 | 57 | ## reshape u,v 58 | u = u.reshape((tlen,param['Nu'])).T 59 | v = v.reshape((tlen,param['Nv'])).T 60 | h = h.reshape((tlen,param['NT'])).T 61 | print('Reshape done.') 62 | 63 | ## U,V,H mean 64 | uhm = (u * ITu.dot(h)).mean(axis=1) # temporal averages 65 | vhm = (v * ITv.dot(h)).mean(axis=1) 66 | print('uh,vh mean done.') 67 | 68 | ## STORING 69 | dic = dict() 70 | all_var2export = ['uhm','vhm'] 71 | 72 | for v in all_var2export: 73 | exec('dic[v] ='+v) 74 | 75 | np.save(runpath+'/analysis/uh_vh_mean.npy',dic) 76 | print('Everything stored.') -------------------------------------------------------------------------------- /docu/matvis/scripts/matvis.py: -------------------------------------------------------------------------------- 1 | ## PLOTTING OPERATOR MATRICES 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import time as tictoc 8 | import matplotlib.pyplot as plt 9 | from cmocean import cm 10 | 11 | # import functions 12 | exec(open(path+'swm_operators.py').read()) 13 | exec(open(path+'swm_output.py').read()) 14 | param = dict() 15 | param['output'] = 0 16 | param['dat_type'] = np.float32 17 | 18 | param['dx'] = 1 19 | param['dy'] = 1 20 | param['nx'] = 3 21 | param['ny'] = 3 22 | param['NT'] = param['nx']*param['ny'] 23 | param['Nu'] = (param['nx']-1)*param['ny'] 24 | param['Nv'] = (param['ny']-1)*param['nx'] 25 | param['Nq'] = (param['nx']+1)*(param['ny']+1) 26 | 27 | set_grad_mat() 28 | set_interp_mat() 29 | set_lapl_mat() 30 | set_arakawa_mat() 31 | 32 | ## 33 | 34 | #mnames = ['GTx','GTy','Gux','Guy','Gvx','Gvy','Gqy','Gqx'] 35 | #mnames = ['Lu','Lv','LT'] 36 | mnames = ['IuT','ITu','IvT','ITv','Iuv','Ivu','ITq','IqT','Iqu','Iuq','Iqv','Ivq'] 37 | 38 | for mname in mnames: 39 | exec('M = '+mname) 40 | levs = np.sort(np.array(list(set(M.data)))) 41 | linlevs = np.arange(1,len(levs)+1) 42 | 43 | # replace data by linlevs 44 | idx = [] 45 | for l in levs: 46 | idx.append(M.data == l) 47 | 48 | for i,r in zip(idx,range(len(idx))): 49 | M.data[i] = linlevs[r] 50 | 51 | M = M.todense() 52 | M = np.ma.masked_array(M,mask=(M == 0)) 53 | 54 | aspectratio = M.shape[0]/M.shape[1] 55 | 56 | fig,ax = plt.subplots(1,1,figsize=(6,5*aspectratio)) 57 | 58 | if len(levs) > 1: 59 | cmapd = cm.thermal.from_list('cmapd',plt.cm.jet(np.linspace(0,1,len(linlevs))),len(linlevs)) 60 | else: 61 | cmapd = cm.thermal.from_list('cmapd',plt.cm.gray([0,1]),2) 62 | 63 | 64 | q = ax.matshow(M,cmap=cmapd,vmin=.5,vmax=linlevs.max()+.5) 65 | cbar = plt.colorbar(q,ax=ax,ticks=linlevs,drawedges=True) 66 | cbar.ax.set_yticklabels(levs) 67 | ax.set_xlabel(r'$\mathbf{'+mname[0]+'}^'+mname[2]+'_'+mname[1]+'$ for $n_x =$%i, $n_y =$%i' % (param['nx'],param['ny']),fontsize=20) 68 | plt.tight_layout() 69 | fig.savefig(path+'matvis/img/'+mname+'.png',dpi=150) 70 | plt.close(fig) 71 | #plt.show() -------------------------------------------------------------------------------- /plot/mean_e_plot.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | path = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 4 | outpath = '/network/home/aopp/kloewer/swm/paperplot/' 5 | 6 | import numpy as np 7 | import matplotlib.pyplot as plt 8 | from cmocean import cm 9 | 10 | plt.rcParams['mathtext.fontset'] = 'cm' 11 | plt.rcParams['mathtext.rm'] = 'serif' 12 | 13 | runfolders = [0,3,8] 14 | 15 | D = [] 16 | p = [] 17 | 18 | for r in runfolders: 19 | runpath = path+'run%04i' % r 20 | D.append(np.load(runpath+'/analysis/mean_e.npy').all()['em']) 21 | p.append(np.load(runpath+'/param.npy').all()) 22 | 23 | ## 24 | expo = 1/3. 25 | 26 | for i in range(len(D)): 27 | D[i] = np.sign(D[i])*abs(D[i])**expo 28 | 29 | ## colormap 30 | 31 | thermal2 = cm.thermal.from_list('thermal2',np.vstack(([0.5,0.5,0.5,1],cm.thermal(np.arange(1,256))))) 32 | 33 | 34 | ## plotting 35 | 36 | levs = np.linspace(0,np.percentile(np.array(D),98),32) 37 | 38 | s = 1e3 39 | 40 | fig,axs = plt.subplots(1,len(D),sharex=True,sharey=True,figsize=(10,4.8)) 41 | fig.tight_layout(rect=[0.03,.15,1,0.9]) 42 | fig.subplots_adjust(wspace=0.03,hspace=0.03) 43 | 44 | pos = axs[0].get_position() 45 | pos2 = axs[-1].get_position() 46 | cax = fig.add_axes([pos.x0,0.1,pos2.x1-pos.x0,0.03]) 47 | 48 | for i,(iD,ip) in enumerate(zip(D,p)): 49 | q = axs[i].contourf(ip['x_T']/s,ip['y_T']/s,iD,levs,extend='both',cmap=thermal2) 50 | 51 | 52 | axs[0].set_title('LR + weak backscatter') 53 | axs[1].set_title('LR + moderate backscatter') 54 | axs[2].set_title('LR + strong backscatter') 55 | 56 | tiks = np.array([0,0.005,0.05,.2,.5,1,1.8,2.4]) 57 | 58 | cbar = fig.colorbar(q,cax=cax,orientation='horizontal',ticks=tiks**expo) 59 | cbar.set_label(r'[m$^3$s$^{-2}$]') 60 | cbar.set_ticklabels(tiks) 61 | 62 | axs[0].set_xticks([0,1000,2000,3000]) 63 | axs[1].set_xticks([0,1000,2000,3000]) 64 | axs[2].set_xticks([0,1000,2000,3000]) 65 | axs[0].set_yticks([0,1000,2000,3000]) 66 | 67 | axs[0].set_title('a',loc='left',fontweight='bold') 68 | axs[1].set_title('b',loc='left',fontweight='bold') 69 | axs[2].set_title('c',loc='left',fontweight='bold') 70 | 71 | axs[0].set_ylabel(r'$y$ [km]') 72 | axs[1].set_xlabel(r'$x$ [km]') 73 | 74 | 75 | plt.suptitle(r'Climatological mean subgrid-EKE $\overline{e}$',x=0.22) 76 | 77 | plt.savefig(outpath+'plots/e_mean.png',dpi=300) 78 | plt.close(fig) -------------------------------------------------------------------------------- /docu/matvis/scripts/forc_vis.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | from matplotlib import gridspec 4 | 5 | plt.rcParams['mathtext.fontset'] = 'cm' 6 | plt.rcParams['mathtext.rm'] = 'serif' 7 | 8 | param = dict() 9 | 10 | param['nx'] = 128 # number of grid points in x-direction 11 | param['ny'] = 128 # number of grid points in y-direction 12 | 13 | param['Lx'] = 3840e3 # basin width L [meters] 14 | param['Ly'] = 3840e3 # north-south basin extent [meters] 15 | 16 | param['dx'] = param['Lx'] / param['nx'] # grid spacing in x-direction 17 | param['dy'] = param['Ly'] / param['ny'] # grid spacing in y-direction 18 | 19 | param['x_T'] = np.arange(param['dx']/2.,param['Lx'],param['dx']) 20 | param['y_T'] = np.arange(param['dy']/2.,param['Ly'],param['dy']) 21 | 22 | # grid vectors for u-points 23 | param['x_u'] = param['x_T'][:-1] + param['dx']/2. 24 | param['y_u'] = param['y_T'] 25 | 26 | Lx,Ly = param['Lx'],param['Ly'] # for convenience 27 | param['rho'] = 1e3 # density 28 | 29 | xx_u,yy_u = np.meshgrid(param['x_u'],param['y_u']) 30 | 31 | param['Fx0'] = 0.12 # was 0.12 32 | Fx = param['Fx0']*(np.cos(2*np.pi*(yy_u-Ly/2)/Ly) + 2*np.sin(np.pi*(yy_u - Ly/2)/Ly)) 33 | 34 | 35 | fig = plt.figure(figsize=(6, 4.5)) 36 | gs = gridspec.GridSpec(1, 2, width_ratios=[3, 1]) 37 | ax0 = plt.subplot(gs[0]) 38 | ax1 = plt.subplot(gs[1]) 39 | 40 | s = 6 41 | ax0.quiver(xx_u[2::s,::s]/1e3,yy_u[2::s,::s]/1e3,Fx[2::s,::s],np.zeros_like(Fx)[2::s,::s], scale=6, headwidth=5) 42 | 43 | ax0.set_title('a',loc='left',fontweight='bold') 44 | ax0.set_title(r'$(F_x,F_y)$') 45 | ax0.set_xlabel(r'$x$ [km]') 46 | ax0.set_ylabel(r'$y$ [km]') 47 | 48 | ax0.set_xlim(0,Lx/1e3) 49 | ax0.set_ylim(0,Ly/1e3) 50 | 51 | ax0.scatter(300,1920,40,'C0',label='Point A') 52 | ax0.scatter(2880,1920,40,'C1',label='Point B') 53 | 54 | ax0.legend(loc=1) 55 | 56 | ax1.plot(Fx[:,0],param['y_u'],lw=1.5) 57 | ax1.plot(np.zeros_like(param['y_u']),param['y_u'],lw=0.5,alpha=0.5,color='k') 58 | ax1.set_title('b',loc='left',fontweight='bold') 59 | ax1.set_title(r'$\gamma(y)$') 60 | ax1.set_ylim(0,Ly) 61 | ax1.set_yticks([]) 62 | ax1.set_xticks([-0.2,0,0.2]) 63 | ax1.set_xticklabels([-0.2,0,0.2]) 64 | ax1.set_xlabel('[Pa]') 65 | 66 | 67 | 68 | 69 | plt.tight_layout() 70 | plt.savefig('/home/mkloewer/Dropbox/thesis/Chapter1/Chapter1Figs/forcing.pdf') -------------------------------------------------------------------------------- /calc/misc/pv_calc.py: -------------------------------------------------------------------------------- 1 | ## PRODUCE MEAN CALCULATIONS AND EXPORT AS .NPY 2 | # FOR POTENTIAL VORTICITY 3 | from __future__ import print_function 4 | path = '/home/mkloewer/python/swm/' 5 | import os; os.chdir(path) # change working directory 6 | import numpy as np 7 | from scipy import sparse 8 | import time as tictoc 9 | from netCDF4 import Dataset 10 | import glob 11 | 12 | # OPTIONS 13 | runfolder = [3] 14 | print('Calculating means from run ' + str(runfolder)) 15 | 16 | ## read data 17 | for r,i in zip(runfolder,range(len(runfolder))): 18 | runpath = path+'data/run%04i' % r 19 | 20 | if i == 0: 21 | u = np.load(runpath+'/u_sub.npy') 22 | v = np.load(runpath+'/v_sub.npy') 23 | h = np.load(runpath+'/h_sub.npy') 24 | time = np.load(runpath+'/t_sub.npy') 25 | print('run %i read.' % r) 26 | 27 | else: 28 | u = np.concatenate((u,np.load(runpath+'/u_sub.npy'))) 29 | v = np.concatenate((v,np.load(runpath+'/v_sub.npy'))) 30 | h = np.concatenate((h,np.load(runpath+'/h_sub.npy'))) 31 | time = np.hstack((time,np.load(runpath+'/t_sub.npy'))) 32 | print('run %i read.' % r) 33 | 34 | t = time / 3600. / 24. # in days 35 | ## read param 36 | global param 37 | param = np.load(runpath+'/param.npy').all() 38 | param['dat_type'] = np.float32 39 | 40 | # import functions 41 | exec(open(path+'swm_param.py').read()) 42 | exec(open(path+'swm_operators.py').read()) 43 | exec(open(path+'swm_output.py').read()) 44 | param['output'] = 0 45 | 46 | set_grad_mat() 47 | set_interp_mat() 48 | set_lapl_mat() 49 | set_coriolis() 50 | 51 | tlen = len(time) 52 | ## create ouputfolder 53 | try: 54 | os.mkdir(runpath+'/analysis') 55 | except: 56 | pass 57 | 58 | ## reshape u,v 59 | u = u.reshape((tlen,param['Nu'])).T 60 | v = v.reshape((tlen,param['Nv'])).T 61 | h = h.reshape((tlen,param['NT'])).T 62 | print('Reshape done.') 63 | 64 | h_q = ITq.dot(h+param['H']) 65 | 66 | ## POTENTIAL VORTICITY MEAN 67 | Z = (Gvx.dot(v) - Guy.dot(u)) 68 | PVm = ((f_q + Z.T).T/h_q).mean(axis=1) 69 | 70 | ## LENGTH SCALE MEAN 71 | KE = .5*(IuT.dot((u.T - u.mean(axis=1)).T**2) + IvT.dot((v.T - v.mean(axis=1)).T**2)) 72 | Lm = np.sqrt(KE/IqT.dot(Z**2)) 73 | 74 | ## STORING 75 | dic = dict() 76 | all_var2export = ['PVm','Lm'] 77 | 78 | for var in all_var2export: 79 | exec('dic[var] ='+var) 80 | 81 | np.save(runpath+'/analysis/PVm_Lm.npy',dic) 82 | print('Everything stored.') -------------------------------------------------------------------------------- /calc/misc/pv_plot.py: -------------------------------------------------------------------------------- 1 | ## PLOT PV MEAN 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | from scipy.integrate import cumtrapz 8 | import matplotlib.pyplot as plt 9 | import time as tictoc 10 | from netCDF4 import Dataset 11 | import glob 12 | from cmocean import cm 13 | 14 | # OPTIONS 15 | runfolder = [3,10] 16 | print('Compare mean plots from run ' + str(runfolder)) 17 | 18 | ## read data 19 | 20 | runpath1 = path+'data/run%04i' % runfolder[0] 21 | D1 = np.load(runpath1+'/analysis/PVm_Lm.npy').all() 22 | D11 = np.load(runpath1+'/analysis/mean.npy').all() 23 | param1 = np.load(runpath1+'/param.npy').all() 24 | 25 | runpath2 = path+'data/run%04i' % runfolder[1] 26 | D2 = np.load(runpath2+'/analysis/PVm_Lm.npy').all() 27 | D21 = np.load(runpath2+'/analysis/mean.npy').all() 28 | param2 = np.load(runpath2+'/param.npy').all() 29 | 30 | #runpath3 = path+'stoch/data/run%04i' % 7 31 | #D3 = np.load(runpath3+'/analysis/PVm_Lm.npy').all() 32 | #param3 = np.load(runpath3+'/param.npy').all() 33 | 34 | # import functions 35 | exec(open(path+'swm_param.py').read()) 36 | exec(open(path+'swm_operators.py').read()) 37 | exec(open(path+'swm_output.py').read()) 38 | exec(open(path+'swm_rhs.py').read()) 39 | param1['output'] = 0 40 | param2['output'] = 0 41 | 42 | ## Plotting 43 | fig,axs = plt.subplots(1,2,sharex=True,sharey=True,figsize=(6,4)) 44 | fig.tight_layout(rect=[0,.13,1,0.95]) 45 | fig.subplots_adjust(wspace=0.05,hspace=0.05) 46 | 47 | pos = axs[0].get_position() 48 | pos2 = axs[-1].get_position() 49 | cax = fig.add_axes([pos.x0,0.13,pos2.x1-pos.x0,0.03]) 50 | 51 | s = 1e7 # scaling factor 52 | 53 | levs = np.linspace(np.percentile(D2['PVm'],1)*s,np.percentile(D2['PVm'],99)*s,32) 54 | 55 | global param 56 | for i,(D,p) in enumerate(zip([D1,D2],[param1,param2])): 57 | param = p 58 | q = axs[i].contourf(p['x_q'],p['y_q'],q2mat(D['PVm'])*1e7,levs,cmap=cm.thermal,extend='both') 59 | 60 | cbar = fig.colorbar(q,cax=cax,orientation='horizontal') 61 | cbar.set_label('Potential Vorticity [$m^{-1}s^{-1} \cdot$ 1e-7]') 62 | cbar.set_ticks([1,1.25,1.5,1.75,2]) 63 | axs[0].set_xticks([0,p['Lx']]) 64 | axs[0].set_yticks([0,p['Ly']]) 65 | 66 | axs[0].set_xticklabels([0,r'$L_x$']) 67 | axs[0].set_yticklabels([0,r'$L_y$']) 68 | 69 | axs[0].set_xlim(0,param['Lx']) 70 | axs[0].set_ylim(0,param['Ly']) 71 | 72 | axs[0].set_title(r'Low resolution, $\Delta x = 30$km') 73 | axs[1].set_title(r'High resolution, $\Delta x = 7.5$km') 74 | 75 | plt.savefig(path+'compare/pv_mean.png',dpi=300) 76 | plt.close(fig) -------------------------------------------------------------------------------- /calc/misc/tempautocorr.py: -------------------------------------------------------------------------------- 1 | ## COMPUTE AND PRODUCE TIMESCALE PLOTS 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | import matplotlib.pyplot as plt 7 | from netCDF4 import Dataset 8 | 9 | def acf(x,l): 10 | """ autocorrelation function of vector x up to lag l.""" 11 | return np.array([1]+[np.corrcoef(x[:-i],x[i:])[0,1] for i in range(1,l)]) 12 | 13 | def findc(x,a): 14 | """ find crossing of vector x with value a.""" 15 | return np.argmin(abs(x-a)) 16 | 17 | runfolders = [7,8,9,10] 18 | 19 | p1 = np.array([300,1920])*1e3 20 | p2 = np.array([2880,1920])*1e3 21 | pi = np.zeros((3,2,2),dtype=np.int) # (u,v,T) x (p1,p2) x (i,j) 22 | 23 | ## read data 24 | for r,i in zip(runfolders,range(len(runfolders))): 25 | runpath = path+'data/run%04i' % r 26 | param = np.load(runpath+'/param.npy').all() 27 | 28 | # find p1 and p2 indices 29 | for ig,g in enumerate(['u','v','T']): 30 | for ip,p in enumerate([p1,p2]): 31 | for ij,xy in enumerate(['x','y']): 32 | pi[ig,ip,ij] = findc(param[xy+'_'+g],p[ij]) 33 | 34 | ncu = Dataset(runpath+'/u.nc') 35 | ncv = Dataset(runpath+'/v.nc') 36 | nch = Dataset(runpath+'/h.nc') 37 | 38 | istart = 0 39 | 40 | if i == 0: 41 | u = ncu.variables['u'][istart:,pi[0,:,0],pi[0,:,1]][:,[0,1],[0,1]] 42 | v = ncv.variables['v'][istart:,pi[1,:,0],pi[1,:,1]][:,[0,1],[0,1]] 43 | h = nch.variables['h'][istart:,pi[2,:,0],pi[2,:,1]][:,[0,1],[0,1]] 44 | t = nch.variables['t'][istart:] 45 | 46 | else: 47 | u = np.concatenate((u,ncu.variables['u'][1:,pi[0,:,0],pi[0,:,1]][:,[0,1],[0,1]])) 48 | v = np.concatenate((v,ncv.variables['v'][1:,pi[1,:,0],pi[1,:,1]][:,[0,1],[0,1]])) 49 | h = np.concatenate((h,nch.variables['h'][1:,pi[2,:,0],pi[2,:,1]][:,[0,1],[0,1]])) 50 | t = np.hstack((t,nch.variables['t'][1:])) 51 | 52 | ncu.close() 53 | ncv.close() 54 | nch.close() 55 | 56 | print('run %i read.' % r) 57 | 58 | ## computation 59 | l = 200 # in 1/4 days 60 | 61 | acfs = np.zeros((l,3,2)) 62 | for iv,var in enumerate([u,v,h]): 63 | for ip in range(2): 64 | acfs[:,iv,ip] = acf(var[:,ip],l) 65 | 66 | dt = t[1]-t[0] 67 | time = np.arange(l)*dt/24/3600 68 | 69 | ## STORING 70 | dic = dict() 71 | all_var2export = ['time','acfs','p1','p2'] 72 | 73 | for var in all_var2export: 74 | exec('dic[var] ='+var) 75 | 76 | np.save(runpath+'/analysis/acfs.npy',dic) 77 | print('Everything stored.') 78 | -------------------------------------------------------------------------------- /calc/misc/tempautocorr_plot.py: -------------------------------------------------------------------------------- 1 | ## TEMPAUTOCORR PLOT 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | import matplotlib.pyplot as plt 7 | from scipy.integrate import cumtrapz 8 | 9 | ## read data 10 | 11 | runpath1 = path+'data/run%04i' % 3 12 | D1 = np.load(runpath1+'/analysis/acfs.npy').all() 13 | param1 = np.load(runpath1+'/param.npy').all() 14 | 15 | runpath2 = path+'data/run%04i' % 10 16 | D2 = np.load(runpath2+'/analysis/acfs.npy').all() 17 | param2 = np.load(runpath2+'/param.npy').all() 18 | 19 | runpath3 = path+'stoch/data/run%04i' % 13 20 | D3 = np.load(runpath3+'/analysis/acfs.npy').all() 21 | param3 = np.load(runpath3+'/param.npy').all() 22 | 23 | runpath4 = path+'stoch/data/run%04i' % 12 24 | D4 = np.load(runpath4+'/analysis/acfs.npy').all() 25 | param4 = np.load(runpath4+'/param.npy').all() 26 | 27 | runpath5 = path+'stoch/data/run%04i' % 14 28 | D5 = np.load(runpath5+'/analysis/acfs.npy').all() 29 | param5 = np.load(runpath5+'/param.npy').all() 30 | 31 | ## Plotting 32 | 33 | fig,axs = plt.subplots(2,3,sharex=True,sharey=True,figsize=(9,6)) 34 | plt.tight_layout(rect=[0.05,.05,1,0.93]) 35 | fig.subplots_adjust(wspace=0.05,hspace=0.26) 36 | 37 | for i in range(3): 38 | for j in range(2): 39 | axs[j,i].plot(D1['time'],D1['acfs'][:,i,j],'C0',label=r'Low resolution, $\Delta x = 30$km',lw=2) 40 | axs[j,i].plot(D2['time'],D2['acfs'][:,i,j],'C2',label=r'High resolution, $\Delta x = 7.5$km',lw=2) 41 | axs[j,i].plot(D3['time'],D3['acfs'][:,i,j],'C3',label=r'Low res. + backscatter, $n_{diss}$=%.2f' % param3['n_diss'],lw=1) 42 | axs[j,i].plot(D4['time'],D4['acfs'][:,i,j],'C1',label=r'Low res. + backscatter, $n_{diss}$=%.2f' % param4['n_diss'],lw=1) 43 | axs[j,i].plot(D5['time'],D5['acfs'][:,i,j],'C4',label=r'Low res. + backscatter, $n_{diss}$=%.2f' % param5['n_diss'],lw=1) 44 | axs[j,i].plot([0,50],[0,0],'C7',alpha=.5) 45 | 46 | axs[0,0].set_xlim(0,49) 47 | axs[0,0].set_ylim(-0.9,1) 48 | 49 | axs[1,1].legend(bbox_to_anchor=(-1, 1.02, 3., .102), loc=3, fontsize=9, ncol=3, mode="expand", borderaxespad=0.) 50 | 51 | axs[0,0].set_title(r'$u$') 52 | axs[0,1].set_title(r'$v$') 53 | axs[0,2].set_title(r'$h$') 54 | 55 | axs[1,0].set_xlabel('lag [days]') 56 | axs[1,1].set_xlabel('lag [days]') 57 | axs[1,2].set_xlabel('lag [days]') 58 | 59 | axs[0,0].set_ylabel('Point A (x=%ikm,y=%ikm)' % tuple(D1['p1']/1e3)) 60 | axs[1,0].set_ylabel('Point B (x=%ikm,y=%ikm)' % tuple(D1['p2']/1e3)) 61 | 62 | plt.suptitle('Autocorrelation function',x=0.53) 63 | 64 | plt.savefig(path+'compare/autocorrelation.png',dpi=150) 65 | plt.close(fig) 66 | #plt.show() -------------------------------------------------------------------------------- /calc/misc/ReRo_hist_plot.py: -------------------------------------------------------------------------------- 1 | ## HISTOGRAM PLOTTING FOR REYNOLDS AND ROSSBY NUMBERS 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import matplotlib.pyplot as plt 8 | import time as tictoc 9 | from netCDF4 import Dataset 10 | import glob 11 | import matplotlib 12 | 13 | # OPTIONS 14 | runfolder = [3,10] 15 | print('Creating ReRo histogram plot from run '+str(runfolder)) 16 | 17 | ## read data 18 | runpath = path+'data/run%04i' % runfolder[0] 19 | D1 = np.load(runpath+'/analysis/ReRo_hist.npy').all() 20 | D11 = np.load(runpath+'/analysis/mean.npy').all() 21 | 22 | runpath = path+'data/run%04i' % runfolder[1] 23 | D2 = np.load(runpath+'/analysis/ReRo_hist.npy').all() 24 | D21 = np.load(runpath+'/analysis/mean.npy').all() 25 | 26 | runpath = path+'stoch/data/run%04i' % 12 27 | D3 = np.load(runpath+'/analysis/ReRo_hist.npy').all() 28 | D31 = np.load(runpath+'/analysis/mean.npy').all() 29 | 30 | ## PLOT 31 | fig,ax1 = plt.subplots(1,1,figsize=(8,6)) 32 | 33 | levs = np.array([12000,40000,106000]) 34 | 35 | ax1.contour(D2['Re_mid'],D2['Ro_mid'],D2['ReRoH'].T,levs*16.,colors='C2',linewidths=np.linspace(1,5,3),alpha=0.8) 36 | ax1.contour(D1['Re_mid'],D1['Ro_mid'],D1['ReRoH'].T,levs,colors='C0',linewidths=np.linspace(1,5,3),alpha=0.8) 37 | ax1.contour(D3['Re_mid'],D3['Ro_mid'],D3['ReRoH'].T,levs,colors='C1',linewidths=np.linspace(1,5,3),alpha=0.8) 38 | 39 | maxij = [0,]*3 40 | maxij[0] = np.unravel_index(np.argmax(D1['ReRoH']),(200,200)) 41 | maxij[1] = np.unravel_index(np.argmax(D2['ReRoH']),(200,200)) 42 | maxij[2] = np.unravel_index(np.argmax(D3['ReRoH']),(200,200)) 43 | 44 | Remaxs = [D['Re_mid'][ij[0]] for D,ij in zip([D1,D2,D3],maxij)] 45 | Romaxs = [D['Ro_mid'][ij[1]] for D,ij in zip([D1,D2,D3],maxij)] 46 | 47 | Remeans = [np.log10(D['Rem'].mean()) for D in [D11,D21,D31]] 48 | Romeans = [np.log10(D['Rom'].mean()) for D in [D11,D21,D31]] 49 | 50 | ax1.scatter(Remaxs,Romaxs,80,c=['C0','C2','C1'],edgecolors='k',zorder=2,label='mode') 51 | ax1.scatter(Remeans,Romeans,80,c=['C0','C2','C1'],edgecolors='k',zorder=2,label='mean',marker='v') 52 | 53 | # for legend 54 | ax1.plot([0,0],[0,0],'C2',label=r'High resolution, $\Delta x = 7.5$km') 55 | ax1.plot([0,0],[0,0],'C0',label=r'Low resolution, $\Delta x = 30$km') 56 | ax1.plot([0,0],[0,0],'C1',label=r'Low resolution + backscatter') 57 | 58 | ax1.legend(loc=4,scatterpoints=3) 59 | 60 | ax1.set_xlim(0,4) 61 | ax1.set_ylim(-3,0) 62 | ax1.set_xlabel(r'$\log_{10}(Re)$') 63 | ax1.set_ylabel(r'$\log_{10}(Ro)$') 64 | ax1.set_title('2D Histogram of Reynolds and Rossby number') 65 | 66 | plt.tight_layout() 67 | plt.savefig(path+'compare/ReRo_2dhist.png') 68 | plt.close(fig) -------------------------------------------------------------------------------- /calc/Ro_hist_calc.py: -------------------------------------------------------------------------------- 1 | ## HISTOGRAM COMPUTATIONS FOR REYNOLDS AND ROSSBY NUMBERS 2 | from __future__ import print_function 3 | 4 | # path 5 | import os 6 | #path = '/network/aopp/cirrus/pred/kloewer/swm_bf_cntrl/' 7 | path = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 8 | os.chdir(path) # change working directory 9 | 10 | # import functions 11 | funpath = '/network/home/aopp/kloewer/git/swm/' 12 | exec(open(funpath+'swm_param.py').read()) 13 | exec(open(funpath+'swm_operators.py').read()) 14 | 15 | import numpy as np 16 | from scipy import sparse 17 | 18 | # OPTIONS 19 | runfolder = [5] 20 | print('Calculating Rossby histograms from run ' + str(runfolder)) 21 | 22 | RoH = [] 23 | Ro_mean = [] 24 | Ro_median = [] 25 | 26 | ## read data - calculate each run separately 27 | for r,i in zip(runfolder,range(len(runfolder))): 28 | runpath = path+'run%04i' % r 29 | 30 | if i == 0: 31 | skip = 5*365 32 | else: 33 | skip = 0 34 | 35 | u = np.load(runpath+'/u_sub.npy')[skip:,...] 36 | v = np.load(runpath+'/v_sub.npy')[skip:,...] 37 | #eta = np.load(runpath+'/eta_sub.npy')[skip:,...] 38 | t = np.load(runpath+'/t_sub.npy')[skip:,...] 39 | print('run %i read.' % r) 40 | 41 | ## read param 42 | global param 43 | param = np.load(runpath+'/param.npy').all() 44 | 45 | set_grad_mat() 46 | set_interp_mat() 47 | set_coriolis() 48 | 49 | tlen = len(t) 50 | ## create ouputfolder 51 | try: 52 | os.mkdir(runpath+'/analysis') 53 | except: 54 | pass 55 | 56 | ## reshape u,v 57 | u = u.reshape((tlen,param['Nu'])).T 58 | v = v.reshape((tlen,param['Nv'])).T 59 | print('Reshape done.') 60 | 61 | ## COMPUTE ROSSBY VIA DEFORMATION RATE 62 | 63 | # Deformation rate / coriolis parameter 64 | Ro = (np.sqrt((Gux.dot(u) - Gvy.dot(v))**2 + IqT.dot((Guy.dot(u) + Gvx.dot(v))**2)).T / f_T).flatten() 65 | print('Ro computed.') 66 | 67 | Ro_mean.append(Ro.mean()) 68 | Ro_median.append(np.median(Ro)) 69 | Ro = np.log10(Ro) 70 | 71 | # histogram 72 | Ro_min = -5. # in log scale 73 | Ro_max = 0.5 74 | N = 300 75 | 76 | RoH_temp,Ro_edges = np.histogram(Ro,np.linspace(Ro_min,Ro_max,N)) 77 | print('Ro histogram done.') 78 | del Ro 79 | 80 | # store each run in a list 81 | RoH.append(RoH_temp) 82 | 83 | Ro_mid = Ro_edges[:-1] + np.diff(Ro_edges)/2. 84 | 85 | 86 | RoH = np.array(RoH).sum(axis=0) 87 | Ro_mean = np.array(Ro_mean).mean() 88 | Ro_median = np.median(np.array(Ro_median)) #actually median of medians though... 89 | 90 | ## STORING in last 91 | dic = dict() 92 | all_var2export = ['RoH','Ro_mid','Ro_edges','Ro_mean','Ro_median'] 93 | 94 | for vars in all_var2export: 95 | exec('dic[vars] ='+vars) 96 | 97 | np.save(runpath+'/analysis/Ro_defo_hist.npy',dic) 98 | -------------------------------------------------------------------------------- /calc/misc/cospec_calc.py: -------------------------------------------------------------------------------- 1 | ## COMPUTE COSPEC 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import time as tictoc 8 | from netCDF4 import Dataset 9 | import glob 10 | import matplotlib.pyplot as plt 11 | 12 | # OPTIONS 13 | runfolder = [2,3] 14 | print('Calculating cospecs from run ' + str(runfolder)) 15 | 16 | def cospec(A,dx,dt): 17 | """ assumed shape of A is time x space. """ 18 | nt,nx = np.shape(A) 19 | 20 | f = np.fft.fftfreq(nt,dt) 21 | k = np.fft.fftfreq(nx,dx) 22 | 23 | idxf = int(np.ceil(nt/2.)) # index of maximum positive frequency 24 | idxk = int(np.ceil(nx/2.)) # index of maximum positive wavenumber 25 | 26 | # 2D FFT 27 | p = abs(np.fft.fft2(A))**2 28 | 29 | f = f[1:idxf] # kill 0 and negative frequencies 30 | # reorder to have -kmax to +kmax 31 | k = np.hstack((k[idxk:],k[1:idxk])) 32 | # apply also for p 33 | p = np.hstack((p[1:idxf,idxk:],p[1:idxf,1:idxk]))[:,::-1] 34 | 35 | #TODO issue: p_max is shifted by -1 in positive k-direction 36 | return f,k,p 37 | 38 | ## read data 39 | for r,i in zip(runfolder,range(len(runfolder))): 40 | runpath = path+'data/run%04i' % r 41 | 42 | if i == 0: 43 | u = np.load(runpath+'/u_sub.npy') 44 | v = np.load(runpath+'/v_sub.npy') 45 | #h = np.load(runpath+'/h_sub.npy') 46 | time = np.load(runpath+'/t_sub.npy') 47 | print('run %i read.' % r) 48 | 49 | else: 50 | u = np.concatenate((u,np.load(runpath+'/u_sub.npy'))) 51 | v = np.concatenate((v,np.load(runpath+'/v_sub.npy'))) 52 | #h = np.concatenate((h,np.load(runpath+'/h_sub.npy'))) 53 | time = np.hstack((time,np.load(runpath+'/t_sub.npy'))) 54 | print('run %i read.' % r) 55 | 56 | t = time / 3600. / 24. # in days 57 | dt = time[1] - time[0] 58 | 59 | ## read param 60 | global param 61 | param = np.load(runpath+'/param.npy').all() 62 | 63 | # import functions 64 | exec(open(path+'swm_param.py').read()) 65 | exec(open(path+'swm_operators.py').read()) 66 | exec(open(path+'swm_output.py').read()) 67 | param['output'] = 0 68 | 69 | set_grad_mat() 70 | set_interp_mat() 71 | set_lapl_mat() 72 | set_coriolis() 73 | 74 | tlen = len(time) 75 | 76 | ## 77 | p_all = [] 78 | 79 | lats = range(10,125,5) 80 | lats = [64] 81 | #lons = [64] 82 | for lat in lats: 83 | #for lon in lons: 84 | #f,k,p = cospec(u[:,:,lon],param['dy'],dt) 85 | f,k,pu = cospec(u[:,lat,:],param['dx'],dt) 86 | f,k,pv = cospec(v[:,lat,:-1],param['dx'],dt) 87 | 88 | p_all.append(pu+pv) 89 | print(lat) 90 | #print(lon) 91 | 92 | p = np.array(p_all).mean(axis=0) 93 | 94 | ## 95 | 96 | dic = dict() 97 | all_var2export = ['f','k','p'] 98 | 99 | for v in all_var2export: 100 | exec('dic[v] ='+v) 101 | 102 | np.save(runpath+'/analysis/cospec_eke_1lat.npy',dic) 103 | print('Everything stored.') -------------------------------------------------------------------------------- /docu/matvis/scripts/grid_vis_rel.py: -------------------------------------------------------------------------------- 1 | ## Visualize Arakawa C-grid numbering 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import matplotlib as mpl 5 | 6 | mpl.rcParams['mathtext.fontset'] = 'cm' 7 | mpl.rcParams['mathtext.rm'] = 'serif' 8 | 9 | 10 | nx = 3 11 | ny = 3 12 | 13 | Lx = nx 14 | Ly = ny 15 | 16 | dx = Lx/nx 17 | dy = Ly/ny 18 | 19 | # grid vectors for T-points 20 | x_T = np.arange(dx/2.,Lx,dx) 21 | y_T = np.arange(dy/2.,Ly,dy) 22 | 23 | # grid vectors for u-points 24 | x_u = x_T[:-1] + dx/2. 25 | y_u = y_T 26 | 27 | #grid vectors for v-points 28 | x_v = x_T 29 | y_v = y_T[:-1] + dy/2. 30 | 31 | # grid vectors for q-points 32 | x_q = np.arange(0,Lx+dx/2.,dx) 33 | y_q = np.arange(0,Ly+dy/2.,dy) 34 | 35 | ## meshgrid 36 | 37 | xx_T,yy_T = np.meshgrid(x_T,y_T) 38 | xx_u,yy_u = np.meshgrid(x_u,y_u) 39 | xx_v,yy_v = np.meshgrid(x_v,y_v) 40 | xx_q,yy_q = np.meshgrid(x_q,y_q) 41 | 42 | xx_T = xx_T.flatten() 43 | xx_u = xx_u.flatten() 44 | xx_v = xx_v.flatten() 45 | xx_q = xx_q.flatten() 46 | 47 | yy_T = yy_T.flatten() 48 | yy_u = yy_u.flatten() 49 | yy_v = yy_v.flatten() 50 | yy_q = yy_q.flatten() 51 | 52 | fig,ax = plt.subplots(1,1,figsize=(3,3)) 53 | 54 | ax.plot(xx_T,yy_T,'r.',ms=10,mec='k') 55 | ax.plot(xx_u,yy_u,'g.',ms=10,mec='k') 56 | ax.plot(xx_v,yy_v,'b.',ms=10,mec='k') 57 | ax.plot(xx_q,yy_q,'k.',ms=10) 58 | 59 | ax.plot(x_v,[0]*nx,'b.',ms=10,alpha=.6) 60 | ax.plot(x_v,[Ly]*nx,'b.',ms=10,alpha=.6) 61 | ax.plot([0]*ny,y_u,'g.',ms=10,alpha=.6) 62 | ax.plot([Lx]*ny,y_u,'g.',ms=10,alpha=.6) 63 | 64 | 65 | plt.grid() 66 | 67 | #for xx,yy,vv in zip([xx_T,xx_u,xx_v,xx_q],[yy_T,yy_u,yy_v,yy_q],['T','u','v','q']): 68 | # for i in range(len(xx)): 69 | # ax.text(xx[i]+0.03,yy[i]+0.03,r'$'+vv+'_{%i}$' %(i+1),fontsize=15) 70 | 71 | s = 0.02 72 | 73 | ax.text(xx_T[4]+s,yy_T[4]+s,r'$T$',fontsize=15) 74 | ax.text(xx_u[3]+s,yy_u[3]+s,r'$u^\rightarrow$',fontsize=15) 75 | ax.text(xx_u[2]+s,yy_u[2]+s,r'$u^\leftarrow$',fontsize=15) 76 | 77 | ax.text(xx_v[4]+s,yy_v[4]+s,r'$v^\uparrow$',fontsize=15) 78 | ax.text(xx_v[1]+s,yy_v[1]+s,r'$v^\downarrow$',fontsize=15) 79 | 80 | ax.text(xx_q[5]+s,yy_q[5]+s,r'$q^\swarrow$',fontsize=15) 81 | ax.text(xx_q[6]+s,yy_q[6]+s,r'$q^\searrow$',fontsize=15) 82 | 83 | ax.text(xx_q[9]+s,yy_q[9]+s,r'$q^\nwarrow$',fontsize=15) 84 | ax.text(xx_q[10]+s,yy_q[10]+s,r'$q^\nearrow$',fontsize=15) 85 | 86 | ax.set_xlabel(r'$\Delta x$',size=15) 87 | ax.set_ylabel(r'$\Delta y$',size=15) 88 | 89 | ax.set_xticks(range(Lx+1)) 90 | ax.set_yticks(range(Ly+1)) 91 | 92 | ax.set_xlim(0.8,2.2) 93 | ax.set_ylim(0.8,2.2) 94 | 95 | ax.set_frame_on(False) 96 | 97 | #dxstring = [(r'$%i\Delta x$' % i) if i > 1 else r'$\Delta x$' for i in range(1,nx)] 98 | #dystring = [(r'$%i\Delta y$' % i) if i > 1 else r'$\Delta y$' for i in range(1,ny)] 99 | 100 | #ax.set_xticklabels([r'$0$']+dxstring+[r'$L_x$']) 101 | #ax.set_yticklabels([r'$0$']+dystring+[r'$L_y$']) 102 | ax.set_xticklabels([]) 103 | ax.set_yticklabels([]) 104 | plt.tight_layout() 105 | fig.savefig(path+'matvis/relative_nodes.png',dpi=150) 106 | plt.close(fig) -------------------------------------------------------------------------------- /calc/misc/Re_hist_plot.py: -------------------------------------------------------------------------------- 1 | ## HISTOGRAM PLOTTING FOR REYNOLDS AND ROSSBY NUMBERS 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import matplotlib.pyplot as plt 8 | import time as tictoc 9 | from netCDF4 import Dataset 10 | import glob 11 | import matplotlib 12 | 13 | plt.rcParams['mathtext.fontset'] = 'cm' 14 | plt.rcParams['mathtext.rm'] = 'serif' 15 | 16 | # OPTIONS 17 | # runfolder = [0,6,10,14,15] 18 | # print('Creating ReRo histogram plot from run '+str(runfolder)) 19 | # 20 | # # read data 21 | # runpath = path+'data/run%04i' % runfolder[0] 22 | # D1 = np.load(runpath+'/analysis/Re_hist.npy').all() 23 | # 24 | # runpath = path+'data/run%04i' % runfolder[1] 25 | # D2 = np.load(runpath+'/analysis/Re_hist.npy').all() 26 | # 27 | # runpath = path+'data/run%04i' % runfolder[2] 28 | # D3 = np.load(runpath+'/analysis/Re_hist.npy').all() 29 | # 30 | # runpath = path+'data/run%04i' % runfolder[3] 31 | # D4 = np.load(runpath+'/analysis/Re_hist.npy').all() 32 | # 33 | # runpath = path+'data/run%04i' % runfolder[4] 34 | # D5 = np.load(runpath+'/analysis/Re_hist.npy').all() 35 | 36 | 37 | # OPTIONS 38 | runfolder = [3,10,13,12,14] 39 | print('Creating ReRo histogram plot from run '+str(runfolder)) 40 | 41 | ## read data 42 | runpath = path+'data/newold/run%04i' % runfolder[0] 43 | D1 = np.load(runpath+'/analysis/Re_hist.npy').all() 44 | 45 | runpath = path+'data/newold/run%04i' % runfolder[1] 46 | D2 = np.load(runpath+'/analysis/Re_hist.npy').all() 47 | 48 | runpath = path+'stoch/data/run%04i' % runfolder[2] 49 | D3 = np.load(runpath+'/analysis/Re_hist.npy').all() 50 | 51 | runpath = path+'stoch/data/run%04i' % runfolder[3] 52 | D4 = np.load(runpath+'/analysis/Re_hist.npy').all() 53 | 54 | runpath = path+'stoch/data/run%04i' % runfolder[4] 55 | D5 = np.load(runpath+'/analysis/Re_hist.npy').all() 56 | 57 | ## PLOT 58 | fig,ax1 = plt.subplots(1,1,figsize=(8,6)) 59 | 60 | ax1.plot(D1['Re_mid'],D1['ReH'],'C0',label=r'Low resolution, $\Delta x = $30km',lw=3) 61 | ax1.plot(D2['Re_mid'],D2['ReH']/16,'C2',label=r'High resolution, $\Delta x = $7.5km',lw=3) 62 | ax1.plot(D3['Re_mid'],D3['ReH'],'C3',label=r'LR + weak backscatter',ls='--') 63 | ax1.plot(D4['Re_mid'],D4['ReH'],'C1',label=r'LR + moderate backscatter',ls='--') 64 | ax1.plot(D5['Re_mid'],D5['ReH'],'C5',label=r'LR + strong backscatter',ls='--') 65 | 66 | ax1.axvline(np.log10(D1['Re_mean']),c='C0',ls='-',lw=2) 67 | ax1.axvline(np.log10(D2['Re_mean']),c='C2',ls='-',lw=2) 68 | ax1.axvline(np.log10(D3['Re_mean']),c='C3',ls='--') 69 | ax1.axvline(np.log10(D4['Re_mean']),c='C1',ls='--') 70 | ax1.axvline(np.log10(D5['Re_mean']),c='C5',ls='--') 71 | 72 | ax1.text(np.log10(D1['Re_mean']),5e5,'mean($R_e$)',rotation=90,ha='right',color='k') 73 | 74 | #ax1.set_yscale('log') 75 | 76 | ax1.legend(loc=2) 77 | 78 | ax1.set_xlim(-3,5) 79 | ax1.set_ylim(1,3e6) 80 | 81 | ax1.set_title('Reynolds number histogram',loc='left') 82 | ax1.set_xlabel('log$_{10}(R_e)$') 83 | ax1.set_ylabel(r'$N$') 84 | 85 | plt.tight_layout() 86 | plt.savefig(path+'compare/Re_hist_nobf.png') 87 | plt.close(fig) -------------------------------------------------------------------------------- /swm_integration.py: -------------------------------------------------------------------------------- 1 | ## TIME INTEGRATION 2 | def time_integration(u,v,eta): 3 | 4 | tic = tictoc.time() # measure time 5 | global dt 6 | dt = param['dt'] # for convenience 7 | t = param['t0'] # initial time 8 | feedback_ini(u,v,eta,t) # output 9 | 10 | ## RUNGE KUTTA 4th ORDER 11 | rk_a = np.array([1/6.,1/3.,1/3.,1/6.]) 12 | rk_b = np.array([0.5,0.5,1.]) 13 | 14 | # can't trigger deep copy through [:] use .copy() instead 15 | u0,v0,eta0 = u.copy(),v.copy(),eta.copy() 16 | u1,v1,eta1 = u.copy(),v.copy(),eta.copy() 17 | 18 | global i # iteration index 19 | for i in range(param['Nt']): 20 | 21 | # trigger deep copy through [:] 22 | u1[:],v1[:],eta1[:] = u,v,eta 23 | 24 | for rki in range(4): 25 | du,dv,deta = rhs(u1,v1,eta1) 26 | 27 | if rki < 3: # RHS update for the next RK-step 28 | u1 = u + rk_b[rki]*dt*du 29 | v1 = v + rk_b[rki]*dt*dv 30 | eta1 = eta + rk_b[rki]*dt*deta 31 | 32 | # Summing all the RHS on the go 33 | u0 += rk_a[rki]*dt*du 34 | v0 += rk_a[rki]*dt*dv 35 | eta0 += rk_a[rki]*dt*deta 36 | 37 | # deep copy through [:] 38 | u[:],v[:],eta[:] = u0,v0,eta0 39 | 40 | t += dt 41 | feedback(u,v,eta,t,tic) 42 | 43 | print(('Integration done in '+readable_secs(tictoc.time() - tic)+' on '+tictoc.asctime())) 44 | output_txt(('\nTime integration done in '+readable_secs(tictoc.time() - tic)+' on '+tictoc.asctime())) 45 | 46 | # finalising output 47 | if param['output']: 48 | output_nc_fin() # finalise nc file 49 | output_txt_fin() # finalise info txt file 50 | 51 | return u,v,eta 52 | 53 | ## FEEDBACK ON INTEGRATION 54 | def feedback_ini(u,v,eta,t): 55 | if param['output']: 56 | output_nc_ini() 57 | output_nc(u,v,eta,t) # store initial conditions 58 | output_param() # store the param dictionnary 59 | 60 | # Store information in txt file 61 | output_txt('Integrating %.1f days with dt=%.2f min in %i time steps' % (param['Ndays'],dt/60.,param['Nt'])) 62 | output_txt('Time integration scheme is '+param['scheme']+' with CFL = %.2f' % param['cfl']) 63 | output_txt('') 64 | output_txt('Starting shallow water model on '+tictoc.asctime()) 65 | print(('Starting shallow water model run %i on ' % param['run_id'])+tictoc.asctime()) 66 | else: 67 | print('Starting shallow water model on '+tictoc.asctime()) 68 | 69 | def feedback(u,v,eta,t,tic): 70 | if (i+1) % param['output_n'] == 0: 71 | if param['output']: # storing u,v,h as netCDF4 72 | output_nc(u,v,eta,t) 73 | 74 | # feedback on progress every 5% step. 75 | if ((i+1)/param['Nt']*100 % 5) < (i/param['Nt']*100 % 5): 76 | progress = str(int((i+1)/param['Nt']*100.))+'%' 77 | print(progress, end='\r') 78 | if i > 100: 79 | output_txt(progress,'\n') 80 | 81 | if i == 100: 82 | # estimate total time for integration after 100 time steps. 83 | duration_est(tic) 84 | -------------------------------------------------------------------------------- /calc/misc/trispec_calc.py: -------------------------------------------------------------------------------- 1 | ## COMPUTE TRISPEC 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import time as tictoc 8 | from netCDF4 import Dataset 9 | import glob 10 | import matplotlib.pyplot as plt 11 | 12 | # OPTIONS 13 | runfolder = [3] 14 | print('Calculating 3D spectrogramms from run ' + str(runfolder)) 15 | 16 | ## 17 | def trispec(a,dt,dx,dy): 18 | """ Computes a wavenumber-frequency plot for 3D (t,x,y) data via radial (k = sqrt(kx**2 + ky**2)) integration. TODO: correct normalisation, so that the integral in normal space corresponds to the integral in Fourier space. 19 | """ 20 | 21 | nt,ny,nx = np.shape(a) 22 | kx = (1/(dx))*np.hstack((np.arange(0,(nx+1)/2.),np.arange(-nx/2.+1,0)))/float(nx) 23 | ky = (1/(dy))*np.hstack((np.arange(0,(ny+1)/2.),np.arange(-ny/2.+1,0)))/float(ny) 24 | f = (1/(dt))*np.hstack((np.arange(0,(nt+1)/2.),np.arange(-nt/2.+1,0)))/float(nt) 25 | 26 | kxx,kyy = np.meshgrid(kx,ky) 27 | # radial distance from kx,ky = 0 28 | kk = np.sqrt(kxx**2 + kyy**2) 29 | 30 | if nx >= ny: #kill negative wavenumbers 31 | k = kx[:int(nx/2)+1] 32 | else: 33 | k = ky[:int(ny/2)+1] 34 | 35 | f = f[:int(nt/2)+1] #kill negative frequencies 36 | dk = k[1] - k[0] 37 | 38 | # create radial coordinates, associated with k[i] 39 | # nearest point interpolation to get points within the -.5,.5 annulus 40 | rcoords = [] 41 | for i in range(len(k)): 42 | rcoords.append(np.where((kk>(k[i]-.5*dk))*(kk<=(k[i]+.5*dk)))) 43 | 44 | # 3D FFT 45 | p = np.fft.fftn(a) 46 | p = np.real(p * np.conj(p)) 47 | 48 | # mulitply by dk to have the corresponding integral 49 | spec = np.zeros((len(f),len(k))) 50 | for i in range(len(k)): 51 | spec[:,i] = np.sum(p[:int(nt/2)+1,rcoords[i][0],rcoords[i][1]],axis=1)*dk 52 | 53 | return k[1:],f[1:],spec[1:,1:] # eliminate zero frequency and zero wavenumber 54 | 55 | ## read data 56 | for r,i in zip(runfolder,range(len(runfolder))): 57 | runpath = path+'data/run%04i' % r 58 | 59 | if i == 0: 60 | #u = np.load(runpath+'/u_sub.npy') 61 | #v = np.load(runpath+'/v_sub.npy') 62 | h = np.load(runpath+'/h_sub.npy') 63 | time = np.load(runpath+'/t_sub.npy') 64 | print('run %i read.' % r) 65 | 66 | else: 67 | #u = np.concatenate((u,np.load(runpath+'/u_sub.npy'))) 68 | #v = np.concatenate((v,np.load(runpath+'/v_sub.npy'))) 69 | h = np.concatenate((h,np.load(runpath+'/h_sub.npy'))) 70 | time = np.hstack((time,np.load(runpath+'/t_sub.npy'))) 71 | print('run %i read.' % r) 72 | 73 | t = time / 3600. / 24. # in days 74 | tlen = len(time) 75 | dt = time[1] - time[0] 76 | 77 | ## read param 78 | global param 79 | param = np.load(runpath+'/param.npy').all() 80 | 81 | ## 82 | k,f,p = trispec(h,dt,param['dx'],param['dy']) 83 | 84 | ## 85 | dic = dict() 86 | all_var2export = ['f','k','p'] 87 | 88 | for v in all_var2export: 89 | exec('dic[v] ='+v) 90 | 91 | np.save(runpath+'/analysis/trispec_h.npy',dic) 92 | print('Everything stored.') -------------------------------------------------------------------------------- /plot/spec_plot.py: -------------------------------------------------------------------------------- 1 | ## EKE SPEC PLOT 2 | from __future__ import print_function 3 | 4 | path1 = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 5 | path2 = '/network/aopp/cirrus/pred/kloewer/swm_bf_cntrl/data/' 6 | outpath = '/network/home/aopp/kloewer/swm/paperplot/' 7 | 8 | import os; os.chdir(path2) # change working directory 9 | import numpy as np 10 | from scipy import sparse 11 | import time as tictoc 12 | from netCDF4 import Dataset 13 | import glob 14 | import matplotlib.pyplot as plt 15 | from cmocean import cm 16 | 17 | plt.rcParams['mathtext.fontset'] = 'cm' 18 | plt.rcParams['mathtext.rm'] = 'serif' 19 | 20 | # OPTIONS 21 | runfolder = [0,6,0,3,8] 22 | print('Compare ek spec plots from run ' + str(runfolder)) 23 | 24 | runpath1 = path2+'run%04i' % runfolder[0] 25 | D1 = np.load(runpath1+'/analysis/spec_eke.npy').all() 26 | param1 = np.load(runpath1+'/param.npy').all() 27 | 28 | runpath2 = path2+'run%04i' % runfolder[1] 29 | D2 = np.load(runpath2+'/analysis/spec_eke.npy').all() 30 | param2 = np.load(runpath2+'/param.npy').all() 31 | 32 | runpath3 = path1+'run%04i' % runfolder[2] 33 | D3 = np.load(runpath3+'/analysis/spec_eke.npy').all() 34 | param3 = np.load(runpath3+'/param.npy').all() 35 | 36 | runpath4 = path1+'run%04i' % runfolder[3] 37 | D4 = np.load(runpath4+'/analysis/spec_eke.npy').all() 38 | param4 = np.load(runpath4+'/param.npy').all() 39 | 40 | runpath5 = path1+'run%04i' % runfolder[4] 41 | D5 = np.load(runpath5+'/analysis/spec_eke.npy').all() 42 | param5 = np.load(runpath5+'/param.npy').all() 43 | 44 | Ro_max = param1['c_phase']/(param1['f_0'] - param1['beta']*param1['Ly']/2.) 45 | Ro_min = param1['c_phase']/(param1['f_0'] + param1['beta']*param1['Ly']/2.) 46 | 47 | ## PLOTTING 48 | 49 | kf = 1e3 50 | 51 | fig,ax = plt.subplots(1,1,figsize=(7,5)) 52 | 53 | ax.loglog(D1['k']*kf,D1['p']/(2*np.pi),'C0',label=r'Low resolution $\Delta x = $30km',lw=2) 54 | ax.loglog(D2['k']*kf,D2['p']/(2*np.pi),'C2',label=r'High resolution $\Delta x = $7.5km',lw=2) 55 | ax.loglog(D3['k']*kf,D3['p']/(2*np.pi),'C1',label=r'LR + weak backscatter',ls='--') 56 | ax.loglog(D4['k']*kf,D4['p']/(2*np.pi),'C3',label=r'LR + moderate backscatter',ls='--') 57 | ax.loglog(D5['k']*kf,D5['p']/(2*np.pi),'C5',label=r'LR + strong backscatter',ls='--') 58 | 59 | ylim = ax.get_ylim() 60 | 61 | ax.loglog(kf/Ro_max*np.ones(2),ylim,'k',lw=0.5) 62 | ax.loglog(kf/Ro_min*np.ones(2),ylim,'k',lw=0.5) 63 | 64 | ax.text(1/1900,5e-1,'$L_{Ro}^{max}$',rotation=90,fontsize=12) 65 | ax.text(1/590,5e-1,'$L_{Ro}^{min}$',rotation=90,fontsize=12) 66 | 67 | k1 = D1['k'][7]*kf 68 | k2 = D1['k'][-1]*kf 69 | 70 | s = 2e-4 71 | ax.loglog([k1,k2],[s*k1**(-3),s*k2**(-3)],'C4',label=r'$K^{-3}$') 72 | 73 | xtick = np.array([4000,2000,1000,500,200,100,50,20,10]) 74 | xtickm = np.array([3000,900,800,700,600,400,300,90,80,70,60,40,30]) 75 | ax.set_xticks(1./xtick) 76 | ax.set_xticks(1./xtickm,minor=True) 77 | ax.set_xticklabels([],minor=True) 78 | ax.set_xticklabels(xtick) 79 | 80 | ax.set_xlim(D1['k'][1]*kf,1./xtick[-1]) 81 | ax.set_ylim(*ylim) 82 | 83 | ax.set_xticklabels(ax.xaxis.get_majorticklabels(), rotation=90) 84 | 85 | ax.set_ylabel('EKE [m$^3$s$^{-2}$]') 86 | ax.set_xlabel('wavelength [km]') 87 | 88 | ax.legend(loc=1) 89 | ax.set_title('Eddy kinetic energy spectrum',loc='left') 90 | 91 | plt.tight_layout() 92 | plt.savefig(outpath+'plots/spec_eke.eps') 93 | plt.close(fig) -------------------------------------------------------------------------------- /calc/misc/ReRo_hist.py: -------------------------------------------------------------------------------- 1 | ## HISTOGRAM COMPUTATIONS FOR REYNOLDS AND ROSSBY NUMBERS 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import time as tictoc 8 | from netCDF4 import Dataset 9 | import glob 10 | 11 | # OPTIONS 12 | runfolder = [12] 13 | print('Calculating histograms from run ' + str(runfolder)) 14 | 15 | ## read data 16 | for r,i in zip(runfolder,range(len(runfolder))): 17 | runpath = path+'stoch/data/run%04i' % r 18 | 19 | if i == 0: 20 | u = np.load(runpath+'/u_sub.npy')[10*365:,:,:] 21 | v = np.load(runpath+'/v_sub.npy')[10*365:,:,:] 22 | h = np.load(runpath+'/h_sub.npy')[10*365:,:,:] 23 | time = np.load(runpath+'/t_sub.npy')[10*365:] 24 | print('run %i read.' % r) 25 | 26 | else: 27 | u = np.concatenate((u,np.load(runpath+'/u_sub.npy'))) 28 | v = np.concatenate((v,np.load(runpath+'/v_sub.npy'))) 29 | h = np.concatenate((h,np.load(runpath+'/h_sub.npy'))) 30 | time = np.hstack((time,np.load(runpath+'/t_sub.npy'))) 31 | print('run %i read.' % r) 32 | 33 | t = time / 3600. / 24. # in days 34 | ## read param 35 | global param 36 | param = np.load(runpath+'/param.npy').all() 37 | 38 | # import functions 39 | exec(open(path+'swm_param.py').read()) 40 | exec(open(path+'swm_operators.py').read()) 41 | exec(open(path+'swm_output.py').read()) 42 | param['output'] = 0 43 | 44 | set_grad_mat() 45 | set_interp_mat() 46 | set_lapl_mat() 47 | set_coriolis() 48 | 49 | tlen = len(time) 50 | ## create ouputfolder 51 | try: 52 | os.mkdir(runpath+'/analysis') 53 | except: 54 | pass 55 | 56 | ## reshape u,v 57 | u = u.reshape((tlen,param['Nu'])).T 58 | v = v.reshape((tlen,param['Nv'])).T 59 | h = h.reshape((tlen,param['NT'])).T 60 | print('Reshape done.') 61 | 62 | ## COMPUTE REYNOLDS, ROSSBY 63 | u_T = IuT.dot(u) 64 | v_T = IvT.dot(v) 65 | print('u,v interpolation done.') 66 | 67 | #advective term 68 | adv_u = u_T*Gux.dot(u) + v_T*IqT.dot(Guy.dot(u)) 69 | adv_v = u_T*IqT.dot(Gvx.dot(v)) + v_T*Gvy.dot(v) 70 | del u_T,v_T 71 | adv_term = np.sqrt(adv_u**2 + adv_v**2) 72 | del adv_u, adv_v 73 | print('Advection term done.') 74 | 75 | #coriolis term 76 | cor_term = (f_T*np.sqrt(IuT.dot(u**2) + IvT.dot(v**2)).T).T 77 | print('Coriolis term done.') 78 | 79 | #diffusive term 80 | diff_u = param['nu_B']*LLu.dot(u) 81 | diff_v = param['nu_B']*LLv.dot(v) 82 | diff_term = np.sqrt(IuT.dot(diff_u**2) + IvT.dot(diff_v**2)) 83 | del diff_u,diff_v 84 | print('Diffusion term done.') 85 | 86 | # actual numbers 87 | Re = np.log10(adv_term / diff_term).flatten() 88 | Ro = np.log10(adv_term / cor_term).flatten() 89 | del adv_term, cor_term, diff_term 90 | print('Non dim numbers computed.') 91 | 92 | # histogram 93 | ReRoH,Re_edges,Ro_edges = np.histogram2d(Re,Ro,200) 94 | print('ReRo histogram done.') 95 | del Re,Ro 96 | 97 | Re_mid = Re_edges[:-1] + np.diff(Re_edges)/2. 98 | Ro_mid = Ro_edges[:-1] + np.diff(Ro_edges)/2. 99 | 100 | ## STORING 101 | dic = dict() 102 | all_var2export = ['ReRoH','Re_mid','Ro_mid','Re_edges','Ro_edges'] 103 | 104 | for v in all_var2export: 105 | exec('dic[v] ='+v) 106 | 107 | np.save(runpath+'/analysis/ReRo_hist.npy',dic) -------------------------------------------------------------------------------- /calc/misc/taylor_diagram_plot.py: -------------------------------------------------------------------------------- 1 | ## TAYLOR DIAGRAM PLOT 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import time as tictoc 8 | from netCDF4 import Dataset 9 | import glob 10 | import matplotlib.pyplot as plt 11 | from cmocean import cm 12 | 13 | exec(open(path+'analyses/taylor_diagram.py').read()) 14 | 15 | # OPTIONS 16 | runfolder = [3,10] 17 | print('Compare mean plots from run ' + str(runfolder)) 18 | 19 | ## read data 20 | 21 | runpath1 = path+'data/run%04i' % runfolder[0] 22 | D1 = np.load(runpath1+'/analysis/mean.npy').all() 23 | param1 = np.load(runpath1+'/param.npy').all() 24 | 25 | runpath2 = path+'data/run%04i' % runfolder[1] 26 | D2 = np.load(runpath2+'/analysis/mean.npy').all() 27 | param2 = np.load(runpath2+'/param.npy').all() 28 | 29 | runpath3 = path+'stoch/data/run%04i' % 13 30 | D3 = np.load(runpath3+'/analysis/mean.npy').all() 31 | param3 = np.load(runpath3+'/param.npy').all() 32 | 33 | runpath4 = path+'stoch/data/run%04i' % 12 34 | D4 = np.load(runpath4+'/analysis/mean.npy').all() 35 | param4 = np.load(runpath4+'/param.npy').all() 36 | 37 | runpath5 = path+'stoch/data/run%04i' % 14 38 | D5 = np.load(runpath5+'/analysis/mean.npy').all() 39 | param5 = np.load(runpath5+'/param.npy').all() 40 | 41 | um,vm,hm = grid_interpolation(D2['um'],D2['vm'],D2['hm'],param2,param1) 42 | 43 | ## 44 | # low resolution 45 | stitle = r'Taylor Diagram: $\overline{u}$, $\overline{v}$, $\overline{h}$' 46 | 47 | fig,ax = taylor_diag(hm, D1['hm'], norm=True,label=r'$h$',color='C0',marker='o') 48 | taylor_diag(um, D1['um'], norm=True,label=r'$u$',add=True,ax=ax,color='C0',marker='o') 49 | taylor_diag(vm, D1['vm'], norm=True,label=r'$v$',add=True,ax=ax,color='C0',marker='o') 50 | 51 | # plus backscatter 52 | taylor_diag(hm, D3['hm'], norm=True,label=r'$h$',add=True,ax=ax,color='C3') 53 | taylor_diag(um, D3['um'], norm=True,label=r'$u$',add=True,ax=ax,color='C3') 54 | taylor_diag(vm, D3['vm'], norm=True,label=r'$v$',add=True,ax=ax,color='C3') 55 | 56 | # plus backscatter 57 | taylor_diag(hm, D4['hm'], norm=True,label=r'$h$',add=True,ax=ax,color='C1') 58 | taylor_diag(um, D4['um'], norm=True,label=r'$u$',add=True,ax=ax,color='C1') 59 | taylor_diag(vm, D4['vm'], norm=True,label=r'$v$',add=True,ax=ax,color='C1') 60 | 61 | # plus backscatter 62 | taylor_diag(hm, D5['hm'], norm=True,label=r'$h$',add=True,ax=ax,color='C4') 63 | taylor_diag(um, D5['um'], norm=True,label=r'$u$',add=True,ax=ax,color='C4') 64 | taylor_diag(vm, D5['vm'], norm=True,label=r'$v$',add=True,ax=ax,color='C4',title=stitle) 65 | 66 | ax.scatter(-np.ones(3),-np.ones(3),5,'C0',marker='o',label=r'Low resolution, $\Delta x = 30$km') 67 | ax.scatter(-np.ones(3),-np.ones(3),5,'C2',marker='o',label=r'High resolution, $\Delta x = 7.5$km') 68 | ax.scatter(-np.ones(3),-np.ones(3),5,'C3',marker='^',label=r'$\Delta x = 30$km + backscatter, $n_{diss} = %.2f$' % param3['n_diss']) 69 | ax.scatter(-np.ones(3),-np.ones(3),5,'C1',marker='^',label=r'$\Delta x = 30$km + backscatter, $n_{diss} = %.2f$' % param4['n_diss']) 70 | ax.scatter(-np.ones(3),-np.ones(3),5,'C4',marker='^',label=r'$\Delta x = 30$km + backscatter, $n_{diss} = %.2f$' % param5['n_diss']) 71 | 72 | plt.legend(loc=1,scatterpoints=3) 73 | 74 | plt.tight_layout() 75 | plt.savefig(path+'compare/Taylor_uvh_mean.png',dpi=150) 76 | plt.close(fig) -------------------------------------------------------------------------------- /calc/misc/taylor_convergence.py: -------------------------------------------------------------------------------- 1 | ## TAYLOR DIAGRAM PLOT 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import time as tictoc 8 | from netCDF4 import Dataset 9 | import glob 10 | import matplotlib.pyplot as plt 11 | from cmocean import cm 12 | 13 | exec(open(path+'analyses/taylor_diagram.py').read()) 14 | 15 | # OPTIONS 16 | runfolder = [3,10,11,12,13] 17 | print('Compare mean plots from run ' + str(runfolder)) 18 | 19 | ## read data 20 | 21 | runpath1 = path+'data/run%04i' % runfolder[0] 22 | D1 = np.load(runpath1+'/analysis/mean.npy').all() 23 | param1 = np.load(runpath1+'/param.npy').all() 24 | 25 | runpath2 = path+'data/run%04i' % runfolder[1] 26 | D2 = np.load(runpath2+'/analysis/mean.npy').all() 27 | param2 = np.load(runpath2+'/param.npy').all() 28 | 29 | runpath3 = path+'data/run%04i' % runfolder[2] 30 | D3 = np.load(runpath3+'/analysis/mean.npy').all() 31 | param3 = np.load(runpath3+'/param.npy').all() 32 | 33 | runpath4 = path+'data/run%04i' % runfolder[3] 34 | D4 = np.load(runpath4+'/analysis/mean.npy').all() 35 | param4 = np.load(runpath4+'/param.npy').all() 36 | 37 | runpath5 = path+'data/run%04i' % runfolder[4] 38 | D5 = np.load(runpath5+'/analysis/mean.npy').all() 39 | param5 = np.load(runpath5+'/param.npy').all() 40 | 41 | um128,vm128,hm128 = grid_interpolation(D2['um'],D2['vm'],D2['hm'],param2,param1) 42 | um32,vm32,hm32 = grid_interpolation(D2['um'],D2['vm'],D2['hm'],param2,param3) 43 | um64,vm64,hm64 = grid_interpolation(D2['um'],D2['vm'],D2['hm'],param2,param4) 44 | um256,vm256,hm256 = grid_interpolation(D2['um'],D2['vm'],D2['hm'],param2,param5) 45 | 46 | ## 47 | # low resolution 48 | stitle = r'Taylor Diagram: $\overline{u}$, $\overline{v}$, $\overline{h}$' 49 | 50 | fig,ax = taylor_diag(hm128, D1['hm'], norm=True,label=r'$h$',color='C0',marker='o') 51 | taylor_diag(um128, D1['um'], norm=True,label=r'$u$',add=True,ax=ax,color='C0',marker='o') 52 | taylor_diag(vm128, D1['vm'], norm=True,label=r'$v$',add=True,ax=ax,color='C0',marker='o') 53 | 54 | # plus backscatter 55 | taylor_diag(hm32, D3['hm'], norm=True,label=r'$h$',add=True,ax=ax,color='C3') 56 | taylor_diag(um32, D3['um'], norm=True,label=r'$u$',add=True,ax=ax,color='C3') 57 | taylor_diag(vm32, D3['vm'], norm=True,label=r'$v$',add=True,ax=ax,color='C3') 58 | 59 | # plus backscatter 60 | taylor_diag(hm64, D4['hm'], norm=True,label=r'$h$',add=True,ax=ax,color='C1') 61 | taylor_diag(um64, D4['um'], norm=True,label=r'$u$',add=True,ax=ax,color='C1') 62 | taylor_diag(vm64, D4['vm'], norm=True,label=r'$v$',add=True,ax=ax,color='C1') 63 | 64 | # plus backscatter 65 | taylor_diag(hm256, D5['hm'], norm=True,label=r'$h$',add=True,ax=ax,color='C4') 66 | taylor_diag(um256, D5['um'], norm=True,label=r'$u$',add=True,ax=ax,color='C4') 67 | taylor_diag(vm256, D5['vm'], norm=True,label=r'$v$',add=True,ax=ax,color='C4',title=stitle) 68 | 69 | ax.scatter(-np.ones(3),-np.ones(3),5,'C3',marker='^',label=r'$\Delta x = 120$km') 70 | ax.scatter(-np.ones(3),-np.ones(3),5,'C1',marker='^',label=r'$\Delta x = 60$km') 71 | ax.scatter(-np.ones(3),-np.ones(3),5,'C0',marker='o',label=r'$\Delta x = 30$km') 72 | ax.scatter(-np.ones(3),-np.ones(3),5,'C4',marker='^',label=r'$\Delta x = 15$km') 73 | ax.scatter(-np.ones(3),-np.ones(3),5,'C2',marker='o',label=r'$\Delta x = 7.5$km') 74 | 75 | plt.legend(loc=1,scatterpoints=3) 76 | 77 | plt.tight_layout() 78 | plt.savefig(path+'compare/Taylor_uvh_convergence.png',dpi=150) 79 | plt.close(fig) -------------------------------------------------------------------------------- /plot/last_timestep_plot.py: -------------------------------------------------------------------------------- 1 | ## PRODUCE FINAL PLOTS 2 | from __future__ import print_function 3 | 4 | path1 = '/network/aopp/cirrus/pred/kloewer/swm_bf_cntrl/data/' 5 | path2 = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 6 | outpath = '/network/home/aopp/kloewer/swm/paperplot/' 7 | 8 | import os; os.chdir(path2) # change working directory 9 | import numpy as np 10 | from scipy import sparse 11 | from scipy.integrate import cumtrapz 12 | import matplotlib.pyplot as plt 13 | import time as tictoc 14 | from netCDF4 import Dataset 15 | import glob 16 | from cmocean import cm 17 | 18 | plt.rcParams['mathtext.fontset'] = 'cm' 19 | plt.rcParams['mathtext.rm'] = 'serif' 20 | 21 | ## OPTIONS 22 | runfolders = [0,3,6] 23 | print('Creating final plots from run ' + str(runfolders)) 24 | 25 | ## read data 26 | p = [] 27 | z = [] 28 | 29 | # import functions 30 | funpath = '/network/home/aopp/kloewer/git/swm/' 31 | exec(open(funpath+'swm_param.py').read()) 32 | exec(open(funpath+'swm_operators.py').read()) 33 | 34 | for i,r in enumerate(runfolders): 35 | 36 | path = path2 if i==1 else path1 37 | runpath = path+'run%04i' % r 38 | 39 | u = np.load(runpath+'/u_last.npy').flatten() 40 | v = np.load(runpath+'/v_last.npy').flatten() 41 | p.append(np.load(runpath+'/param.npy').all()) 42 | 43 | # set param the current param dictionnary 44 | param = p[-1] 45 | param['output'] = 0 46 | 47 | # get operators 48 | set_grad_mat() 49 | set_interp_mat() 50 | set_coriolis() 51 | 52 | # rel vort calculation 53 | z.append(q2mat(Gvx.dot(v) - Guy.dot(u))) 54 | print((z[-1]**2).mean()) 55 | expo = 0.5 56 | z[-1] = (np.sign(z[-1])*abs(z[-1]*1e5)**expo) 57 | 58 | z_max = np.percentile(abs(z[-1]),98.5) 59 | levs = np.linspace(-z_max,z_max,32) 60 | 61 | ## 62 | 63 | fig,axs = plt.subplots(1,3,figsize=(10,4.8),sharex=True,sharey=True) 64 | fig.tight_layout(rect=[0.03,.15,1,0.9]) 65 | fig.subplots_adjust(wspace=0.03,hspace=0.03) 66 | 67 | pos = axs[0].get_position() 68 | pos2 = axs[-1].get_position() 69 | cax = fig.add_axes([pos.x0,0.1,pos2.x1-pos.x0,0.03]) 70 | 71 | axs[0].contourf(p[0]['x_q']/1e3,p[0]['y_q']/1e3,z[0],levs,cmap=cm.balance,extend='both') 72 | axs[1].contourf(p[1]['x_q']/1e3,p[1]['y_q']/1e3,z[1],levs,cmap=cm.balance,extend='both') 73 | q0 = axs[2].contourf(p[2]['x_q']/1e3,p[2]['y_q']/1e3,z[2],levs,cmap=cm.balance,extend='both') 74 | 75 | tik0 = np.array([-3,-1.9,-1,-0.4,-0.1,0,0.1,0.4,1,1.9,3]) 76 | 77 | cbar0 = fig.colorbar(q0,cax=cax,orientation='horizontal',ticks=np.sign(tik0)*abs(tik0)**expo) 78 | cbar0.set_label(r'[10$^{-5}$ s$^{-1}$]') 79 | cbar0.set_ticklabels(tik0) 80 | 81 | plt.suptitle(r'Snapshots of relative vorticity',x=0.201) 82 | 83 | axs[0].set_xlim(0,param['Lx']/1e3) 84 | axs[0].set_ylim(0,param['Ly']/1e3) 85 | 86 | axs[0].set_xticks([0,1000,2000,3000]) 87 | axs[0].set_yticks([0,1000,2000,3000]) 88 | 89 | axs[0].set_ylabel(r'$y$ [km]') 90 | axs[1].set_xlabel(r'$x$ [km]') 91 | 92 | 93 | axs[0].set_title(r'Low resolution, $\Delta x = $30km') 94 | axs[1].set_title(r'LR + moderate backscatter') 95 | axs[2].set_title(r'High resolution, $\Delta x = $7.5km') 96 | 97 | axs[0].set_title('a',loc='left',fontweight='bold') 98 | axs[1].set_title('b',loc='left',fontweight='bold') 99 | axs[2].set_title('c',loc='left',fontweight='bold') 100 | 101 | plt.savefig(outpath+'plots/relvort_snapshot.png',dpi=300) 102 | plt.close(fig) 103 | -------------------------------------------------------------------------------- /calc/misc/trispec_plot.py: -------------------------------------------------------------------------------- 1 | ## TRISPEC PLOT 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import time as tictoc 8 | from netCDF4 import Dataset 9 | import glob 10 | import matplotlib.pyplot as plt 11 | from cmocean import cm 12 | 13 | # OPTIONS 14 | runfolder = [3,10] 15 | var = 'h' 16 | print('Compare trispec plots from run ' + str(runfolder)) 17 | 18 | runpath1 = path+'data/run%04i' % runfolder[0] 19 | D1 = np.load(runpath1+'/analysis/trispec_'+var+'.npy').all() 20 | param1 = np.load(runpath1+'/param.npy').all() 21 | 22 | runpath2 = path+'data/run%04i' % runfolder[1] 23 | D2 = np.load(runpath2+'/analysis/trispec_'+var+'.npy').all() 24 | param2 = np.load(runpath2+'/param.npy').all() 25 | 26 | ## 27 | Ro_max = param1['c_phase']/(param1['f_0'] - param1['beta']*param1['Ly']/2.) 28 | Ro_min = param1['c_phase']/(param1['f_0'] + param1['beta']*param1['Ly']/2.) 29 | 30 | # dispersion relation, divide omega and k by 2pi 31 | wrossby_max = lambda k: param1['beta']*k/(2*np.pi)/(2*(k/(2*np.pi))**2 + 1./(Ro_max)**2)/2./np.pi 32 | wrossby_min = lambda k: param1['beta']*k/(2*np.pi)/(2*(k/(2*np.pi))**2 + 1./(Ro_min)**2)/2./np.pi 33 | 34 | ## PLOTTING 35 | sd = 3600.*24. # from seconds to days for frequency axis 36 | kf = 1e3 # wavenumber factor for plotting 37 | 38 | fig,(ax1,ax2) = plt.subplots(1,2,sharex=True,sharey=True,figsize=(14,7)) 39 | c1 = ax1.contourf(D1['k']*kf,D1['f']*sd,np.log10(D1['p']),np.linspace(0,9,51),cmap=cm.thermal,extend='both') 40 | c2 = ax2.contourf(D2['k']*kf,D2['f']*sd,np.log10(D2['p']),np.linspace(0,9,51),cmap=cm.thermal,extend='both') 41 | 42 | for D,ax,greyvalue in zip([D1,D2],[ax1,ax2],['0.7','0.3']): 43 | 44 | ax.plot(np.zeros(2),[D['f'][0]*sd,D['f'][-1]*sd],'w',lw=22) 45 | 46 | ax.plot(D['k']*kf,wrossby_min(D['k'])*sd,'c',label=r'$\omega_{Ro,min}(k)$',lw=1.5) 47 | ax.plot(D['k']*kf,wrossby_max(D['k'])*sd,'c--',label=r'$\omega_{Ro,max}(k)$',lw=1.5) 48 | 49 | ax.plot(1./Ro_min*kf*np.ones(2),[D['f'][0]*sd,D['f'][-1]*sd],greyvalue,label=r'$Ro_{min}$',lw=1.5) 50 | ax.plot(1./Ro_max*kf*np.ones(2),[D2['f'][0]*sd,D['f'][-1]*sd],greyvalue,label=r'$Ro_{max}$',linestyle='dashed',lw=1.5) 51 | 52 | ax.plot(-1./Ro_min*kf*np.ones(2),[D['f'][0]*sd,D['f'][-1]*sd],greyvalue,lw=1.5) 53 | ax.plot(-1./Ro_max*kf*np.ones(2),[D2['f'][0]*sd,D['f'][-1]*sd],greyvalue,linestyle='dashed',lw=1.5) 54 | 55 | ytick = np.array([200,50,20,15,10,8,7,6,5,4,3]) 56 | ax.set_yticks(1./ytick) 57 | ax.set_yticklabels(ytick) 58 | 59 | xtick = np.array([40,10,5,3,2,1])*100 60 | ax.set_xticks(1./xtick) 61 | ax.set_xticklabels(xtick) 62 | 63 | ax.tick_params(axis='x', color='white') 64 | ax.tick_params(axis='y', color='white') 65 | 66 | ax.set_xticklabels(ax.xaxis.get_majorticklabels(), rotation=90) 67 | 68 | ax1.set_xlim(0,0.01) 69 | ax1.set_ylim(0,.5) 70 | 71 | ax1.legend(loc=1) 72 | 73 | ax1.set_xlabel(r'wavelength $\lambda = 1/\sqrt{k_x^2 + k_y^2}$ [km]') 74 | ax2.set_xlabel(r'$\lambda$ [km]') 75 | ax1.set_ylabel('period [days]') 76 | 77 | if var == 'h': 78 | varname = '$\eta$' 79 | elif var == 'u': 80 | varname = '$u$' 81 | elif var == 'v': 82 | varname = '$v$' 83 | 84 | ax1.set_title('3D power spectrum of '+varname+': Low resolution $\Delta x = 30$km') 85 | ax2.set_title('High resolution $\Delta x = 7.5$km') 86 | plt.tight_layout() 87 | plt.savefig(path+'/compare/trispec_'+var+'.png') 88 | plt.close(fig) -------------------------------------------------------------------------------- /swm_rhs.py: -------------------------------------------------------------------------------- 1 | ## RIGHT HAND SIDE OF THE EQUATIONS 2 | def rhs(u,v,eta): 3 | """ Set of equations: 4 | 5 | u_t = qhv - p_x + Fx + Mx(u,v) - bottom_friction 6 | v_t = -qhu - p_y + My(u,v) - bottom_friction 7 | eta_t = -(uh)_x - (vh)_y 8 | 9 | with p = .5*(u**2 + v**2) + gh, the bernoulli potential 10 | and q = (v_x - u_y + f)/h the potential vorticity 11 | 12 | using the enstrophy and energy conserving scheme (Arakawa and Lamb, 1981) and 13 | a biharmonic lateral mixing term based on Shchepetkin and O'Brien (1996). 14 | """ 15 | 16 | #TODO param[nu_B] is large, applying the biharmonic creates tiny values (as dx^4 is large) 17 | #TODO think about a way to avoid possibly involved rounding errors especially with single precision 18 | #TODO might be efficiently only possible for dx=dy 19 | 20 | h = eta + param['H'] 21 | 22 | h_u = ITu.dot(h) # h on u-grid 23 | h_v = ITv.dot(h) # h on v-grid 24 | h_q = ITq.dot(h) # h on q-grid 25 | 26 | U = u*h_u # volume fluxes: U on u-grid 27 | V = v*h_v # and V on v-grid 28 | 29 | KE = IuT.dot(u**2) + IvT.dot(v**2) # kinetic energy without .5-factor 30 | 31 | q = (f_q + Gvx.dot(v) - Guy.dot(u)) / h_q # potential vorticity q 32 | p = .5*KE + param['g']*h # Bernoulli potential p 33 | 34 | ## BOTTOM FRICTION: quadratic drag 35 | sqrtKE = np.sqrt(KE) 36 | bfric_u = param['c_D']*ITu.dot(sqrtKE)*u/h_u 37 | bfric_v = param['c_D']*ITv.dot(sqrtKE)*v/h_v 38 | 39 | ## ADVECTION 40 | # Sadourny, 1975 enstrophy conserving scheme. 41 | # adv_u = Iqu.dot(q)*Ivu.dot(V) 42 | # adv_v = -Iqv.dot(q)*Iuv.dot(U) 43 | 44 | # Arakawa and Lamb, 1981 45 | adv_u, adv_v = ALadvection(q,U,V) 46 | 47 | ## LATERAL MIXING OPERATOR 48 | # simple bi-harmonic mixing 49 | # bidiff_u = param['nu_B']*LLu.dot(u) 50 | # bidiff_v = param['nu_B']*LLv.dot(v) 51 | 52 | # symmetric stress tensor S = (S11, S12, S12, -S11), store only S11, S12 53 | S = (Gux.dot(u) - Gvy.dot(v),G2vx.dot(v) + G2uy.dot(u)) 54 | hS = (h*S[0],h_q*S[1]) 55 | 56 | diff_u = (GTx*hS[0] + Gqy*hS[1]) / h_u 57 | diff_v = (Gqx*hS[1] - GTy*hS[0]) / h_v 58 | 59 | # biharmonic stress tensor R = (R11, R12, R12, -R11), store only R11, R12 60 | R = (Gux.dot(diff_u) - Gvy.dot(diff_v), G2vx.dot(diff_v) + G2uy.dot(diff_u)) 61 | nuhR = (param['nu_B']*h*R[0],param['nu_B']*h_q*R[1]) 62 | 63 | bidiff_u = (GTx.dot(nuhR[0]) + Gqy.dot(nuhR[1])) / h_u 64 | bidiff_v = (Gqx.dot(nuhR[1]) - GTy.dot(nuhR[0])) / h_v 65 | 66 | ## RIGHT-HAND SIDE: ADD TERMS 67 | rhs_u = adv_u - GTx.dot(p) + Fx/h_u - bidiff_u - bfric_u 68 | rhs_v = adv_v - GTy.dot(p) - bidiff_v - bfric_v 69 | rhs_eta = -(Gux.dot(U) + Gvy.dot(V)) 70 | 71 | return rhs_u, rhs_v, rhs_eta 72 | 73 | def ALadvection(q,U,V): 74 | """ Arakawa and Lamb,1981 advection terms. See interpolation.py for further information. """ 75 | 76 | AL1q = AL1.dot(q) 77 | AL2q = AL2.dot(q) 78 | 79 | adv_u = Seur.dot(ALeur.dot(q)*U) + Seul.dot(ALeul.dot(q)*U) +\ 80 | Sau.dot(AL1q[indx_au]*V) + Sbu.dot(AL2q[indx_bu]*V) +\ 81 | Scu.dot(AL2q[indx_cu]*V) + Sdu.dot(AL1q[indx_du]*V) 82 | 83 | adv_v = Spvu.dot(ALpvu.dot(q)*V) + Spvd.dot(ALpvd.dot(q)*V) -\ 84 | Sav.dot(AL1q[indx_av]*U) - Sbv.dot(AL2q[indx_bv]*U) -\ 85 | Scv.dot(AL2q[indx_cv]*U) - Sdv.dot(AL1q[indx_dv]*U) 86 | 87 | return adv_u, adv_v 88 | 89 | -------------------------------------------------------------------------------- /calc/misc/cospec_plot.py: -------------------------------------------------------------------------------- 1 | ## COSPEC PLOT 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import time as tictoc 8 | from netCDF4 import Dataset 9 | import glob 10 | import matplotlib.pyplot as plt 11 | from cmocean import cm 12 | 13 | # OPTIONS 14 | runfolder = [3,10] 15 | var = 'eke' 16 | print('Compare cospec plots from run ' + str(runfolder)) 17 | 18 | #lat1 = '_1lat' 19 | lat1 = '' 20 | 21 | runpath1 = path+'data/run%04i' % runfolder[0] 22 | D1 = np.load(runpath1+'/analysis/cospec_'+var+lat1+'.npy').all() 23 | param1 = np.load(runpath1+'/param.npy').all() 24 | 25 | runpath2 = path+'data/run%04i' % runfolder[1] 26 | D2 = np.load(runpath2+'/analysis/cospec_'+var+lat1+'.npy').all() 27 | param2 = np.load(runpath2+'/param.npy').all() 28 | 29 | ## 30 | Ro_max = param1['c_phase']/(param1['f_0'] - param1['beta']*param1['Ly']/2.) 31 | Ro_min = param1['c_phase']/(param1['f_0'] + param1['beta']*param1['Ly']/2.) 32 | 33 | # dispersion relation, divide omega and k by 2pi 34 | wrossby_max = lambda k: -param1['beta']*k/(2*np.pi)/(2*(k/(2*np.pi))**2 + 1./(Ro_max)**2)/2./np.pi 35 | wrossby_min = lambda k: -param1['beta']*k/(2*np.pi)/(2*(k/(2*np.pi))**2 + 1./(Ro_min)**2)/2./np.pi 36 | 37 | ## PLOTTING 38 | sd = 3600.*24. # from seconds to days for frequency axis 39 | kf = 1e3 # wavenumber factor for plotting 40 | 41 | fig,(ax1,ax2) = plt.subplots(1,2,sharex=True,sharey=True,figsize=(14,7)) 42 | c1 = ax1.contourf(D1['k']*kf,D1['f']*sd,np.log10(D1['p']),np.linspace(4,10,51),cmap=cm.thermal,extend='both') 43 | c2 = ax2.contourf(D2['k']*kf,D2['f']*sd,np.log10(D2['p']),np.linspace(4,10,51),cmap=cm.thermal,extend='both') 44 | 45 | for D,ax,greyvalue in zip([D1,D2],[ax1,ax2],['0.7','0.3']): 46 | ax.plot(np.zeros(2),[D['f'][0]*sd,D['f'][-1]*sd],'w',lw=22) 47 | 48 | ax.plot(D['k']*kf,wrossby_min(D['k'])*sd,'c',label=r'$\frac{1}{2\pi}\omega_{Ro,min}(\frac{k}{2\pi})$',lw=1.5) 49 | ax.plot(D['k']*kf,wrossby_max(D['k'])*sd,'c--',label=r'$\frac{1}{2\pi}\omega_{Ro,max}(\frac{k}{2\pi})$',lw=1.5) 50 | 51 | ax.plot(1./Ro_min*kf*np.ones(2),[D['f'][0]*sd,D['f'][-1]*sd],greyvalue,label=r'$Ro_{min}$',lw=1.5) 52 | ax.plot(1./Ro_max*kf*np.ones(2),[D2['f'][0]*sd,D['f'][-1]*sd],greyvalue,label=r'$Ro_{max}$',linestyle='dashed',lw=1.5) 53 | 54 | ax.plot(-1./Ro_min*kf*np.ones(2),[D['f'][0]*sd,D['f'][-1]*sd],greyvalue,lw=1.5) 55 | ax.plot(-1./Ro_max*kf*np.ones(2),[D2['f'][0]*sd,D['f'][-1]*sd],greyvalue,linestyle='dashed',lw=1.5) 56 | 57 | ytick = np.array([200,50,20,15,10,8,7,6,5,4,3]) 58 | ax.set_yticks(1./ytick) 59 | ax.set_yticklabels(ytick) 60 | 61 | xtick = np.array([-2,-5,-10,-40,40,10,5,2])*100 62 | ax.set_xticks(1./xtick) 63 | ax.set_xticklabels(xtick) 64 | 65 | ax.tick_params(axis='x', color='white') 66 | ax.tick_params(axis='y', color='white') 67 | 68 | ax.set_xticklabels(ax.xaxis.get_majorticklabels(), rotation=90) 69 | 70 | ax1.set_xlim(-0.005,0.005) 71 | ax1.set_ylim(0,.34) 72 | 73 | ax1.legend(loc=1) 74 | 75 | ax1.set_xlabel(r'wavelength [km]') 76 | ax2.set_xlabel(r'wavelength [km]') 77 | ax1.set_ylabel('period [days]') 78 | 79 | if var == 'h': 80 | varname = '$\eta$' 81 | elif var == 'u': 82 | varname = '$u$' 83 | elif var == 'v': 84 | varname = '$v$' 85 | elif var == 'eke': 86 | varname = 'EKE' 87 | 88 | ax1.set_title('2D power spectrum of '+varname+': Low resolution $\Delta x = 30$km') 89 | ax2.set_title('High resolution $\Delta x = 7.5$km') 90 | plt.tight_layout() 91 | plt.savefig(path+'/compare/cospec_'+var+lat1+'.png') 92 | plt.close(fig) 93 | 94 | 95 | -------------------------------------------------------------------------------- /calc/misc/tempautocorr_plot_bf.py: -------------------------------------------------------------------------------- 1 | ## TEMPAUTOCORR PLOT 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | import matplotlib.pyplot as plt 7 | from scipy.integrate import cumtrapz 8 | 9 | ## read data 10 | 11 | runpath1 = path+'data/run%04i' % 0 12 | D1 = np.load(runpath1+'/analysis/acfs.npy').all() 13 | param1 = np.load(runpath1+'/param.npy').all() 14 | 15 | runpath2 = path+'data/run%04i' % 6 16 | D2 = np.load(runpath2+'/analysis/acfs.npy').all() 17 | param2 = np.load(runpath2+'/param.npy').all() 18 | 19 | runpath3 = path+'data/run%04i' % 10 20 | D3 = np.load(runpath3+'/analysis/acfs.npy').all() 21 | param3 = np.load(runpath3+'/param.npy').all() 22 | 23 | runpath4 = path+'data/run%04i' % 14 24 | D4 = np.load(runpath4+'/analysis/acfs.npy').all() 25 | param4 = np.load(runpath4+'/param.npy').all() 26 | 27 | runpath5 = path+'data/run%04i' % 15 28 | D5 = np.load(runpath5+'/analysis/acfs.npy').all() 29 | param5 = np.load(runpath5+'/param.npy').all() 30 | 31 | # read without bottom friction data 32 | 33 | # runpath1 = path+'data/newold/run%04i' % 3 34 | # D1 = np.load(runpath1+'/analysis/acfs.npy').all() 35 | # param1 = np.load(runpath1+'/param.npy').all() 36 | # 37 | # runpath2 = path+'data/newold/run%04i' % 10 38 | # D2 = np.load(runpath2+'/analysis/acfs.npy').all() 39 | # param2 = np.load(runpath2+'/param.npy').all() 40 | # 41 | # runpath3 = path+'stoch/data/run%04i' % 13 42 | # D3 = np.load(runpath3+'/analysis/acfs.npy').all() 43 | # param3 = np.load(runpath3+'/param.npy').all() 44 | # 45 | # runpath4 = path+'stoch/data/run%04i' % 12 46 | # D4 = np.load(runpath4+'/analysis/acfs.npy').all() 47 | # param4 = np.load(runpath4+'/param.npy').all() 48 | # 49 | # runpath5 = path+'stoch/data/run%04i' % 14 50 | # D5 = np.load(runpath5+'/analysis/acfs.npy').all() 51 | # param5 = np.load(runpath5+'/param.npy').all() 52 | 53 | ## Plotting 54 | 55 | fig,axs = plt.subplots(2,3,sharex=True,sharey=True,figsize=(9,6)) 56 | plt.tight_layout(rect=[0.05,0.02,1,0.96]) 57 | fig.subplots_adjust(wspace=0.05,hspace=0.26) 58 | 59 | for i in range(3): 60 | for j in range(2): 61 | axs[j,i].plot(D1['time'],D1['acfs'][:,i,j],'C0',label=r'Low resolution, $\Delta x = $30km',lw=2) 62 | axs[j,i].plot(D2['time'],D2['acfs'][:,i,j],'C2',label=r'High resolution, $\Delta x = $7.5km',lw=2) 63 | axs[j,i].plot(D3['time'],D3['acfs'][:,i,j],'C3',label=r'LR + weak backscatter',lw=1,ls='--') 64 | axs[j,i].plot(D4['time'],D4['acfs'][:,i,j],'C1',label=r'LR + moderate backscatter',lw=1,ls='--') 65 | axs[j,i].plot(D5['time'],D5['acfs'][:,i,j],'C5',label=r'LR + strong backscatter',lw=1,ls='--') 66 | axs[j,i].plot([0,50],[0,0],'C7',alpha=.5) 67 | 68 | axs[0,0].set_xlim(0,49) 69 | axs[0,0].set_ylim(-0.9,1) 70 | 71 | axs[1,1].legend(bbox_to_anchor=(-1, 1.02, 3., .102), loc=3, fontsize=9, ncol=3, mode="expand", borderaxespad=0.) 72 | 73 | axs[0,0].set_title(r'Zonal velocity $u$',loc='left') 74 | axs[0,1].set_title(r'Meridional velocity $v$',loc='left') 75 | axs[0,2].set_title(r'Surface displacement $\eta$',loc='left') 76 | 77 | axs[1,0].set_xlabel('lag [days]') 78 | axs[1,1].set_xlabel('lag [days]') 79 | axs[1,2].set_xlabel('lag [days]') 80 | 81 | axs[0,0].set_ylabel('Autocorrelation \n Point A') 82 | axs[1,0].set_ylabel('Autocorrelation \n Point B') 83 | 84 | axs[0,0].set_yticks([-0.5,0,0.5,1]) 85 | 86 | abc = 'abcdef' 87 | abci = 0 88 | for axcol in axs: 89 | for ax in axcol: 90 | plt.text(0.93,0.93,abc[abci],transform=ax.transAxes,fontweight='bold') 91 | abci += 1 92 | 93 | plt.savefig(path+'compare/autocorrelation_bf.pdf') 94 | plt.close(fig) 95 | #plt.show() -------------------------------------------------------------------------------- /calc/floats/floats_plot.py: -------------------------------------------------------------------------------- 1 | ## FLOATS PLOT 2 | import numpy as np 3 | from netCDF4 import Dataset 4 | from scipy.interpolate import RegularGridInterpolator as RGI 5 | import matplotlib.pyplot as plt 6 | from cmocean import cm 7 | 8 | plt.rcParams['mathtext.fontset'] = 'cm' 9 | plt.rcParams['mathtext.rm'] = 'serif' 10 | 11 | path = '/home/mkloewer/python/swm/' 12 | 13 | # OPTIONS# 14 | runfolder = [3,10] 15 | print('Plotting floats from run ' + str(runfolder)) 16 | 17 | ## LOAD DATA 18 | runpath1 = path+'data/newold/run%04i' % runfolder[0] 19 | param1 = np.load(runpath1+'/param.npy').all() 20 | D1 = np.load(runpath1+'/analysis/floats.npy').all() 21 | 22 | runpath2 = path+'data/newold/run%04i' % runfolder[1] 23 | param2 = np.load(runpath2+'/param.npy').all() 24 | D2 = np.load(runpath2+'/analysis/floats.npy').all() 25 | 26 | runpath3 = path+'stoch/data/run%04i' % 12 27 | param3 = np.load(runpath3+'/param.npy').all() 28 | D3 = np.load(runpath3+'/analysis/floats.npy').all() 29 | 30 | expo = 0.5 # non-linear colorbar exponent 31 | 32 | dx,dy = D1['xm'][1]-D1['xm'][0],D1['ym'][1]-D1['ym'][0] 33 | D1['H'] = (D1['H']/dx/dy*1e6)**expo 34 | 35 | dx,dy = D2['xm'][1]-D2['xm'][0],D2['ym'][1]-D2['ym'][0] 36 | D2['H'] = (D2['H']/dx/dy*1e6)**expo 37 | 38 | dx,dy = D1['xm'][1]-D1['xm'][0],D1['ym'][1]-D1['ym'][0] 39 | D3['H'] = (D3['H']/dx/dy*1e6)**expo 40 | 41 | tiks = np.array([0,1,5,10,20,30,40]) 42 | levs = np.linspace(0,np.percentile(D1['H'],99),64) 43 | 44 | ## Plotting 45 | fig,axs = plt.subplots(2,3,sharex=True,sharey=True,figsize=(10,8)) 46 | plt.tight_layout(rect=[0,.09,1,0.98]) 47 | fig.subplots_adjust(wspace=0.03,hspace=0.03) 48 | 49 | pos1 = axs[-1,0].get_position() 50 | pos2 = axs[-1,-1].get_position() 51 | cax = fig.add_axes([pos1.x0,0.07,pos2.x1-pos1.x0,0.03]) 52 | 53 | N = 30 # number of trajectories to plot 54 | 55 | for iD,D in enumerate([D1,D3,D2]): 56 | for i in range(min(D['X'].shape[1],N)): # max num of floats to display 57 | z = np.random.randint(0,250,1)[0] 58 | axs[0,iD].plot(D['X'][:,40+i],D['Y'][:,40+i],color=cm.haline(z)) 59 | 60 | for i,D in enumerate([D1,D3,D2]): 61 | sx,sy = D['seedx'],D['seedy'] # unpack 62 | xm,ym,H = D['xm'],D['ym'],D['H'] 63 | axs[1,i].add_patch(plt.Rectangle((sx[0],sy[0]),sx[1]-sx[0],sy[1]-sy[0],fc='none',alpha=1,ec='k',lw=1.5)) 64 | q = axs[1,i].contourf(xm,ym,H.T,levs,extend='max',cmap=cm.thermal) 65 | axs[1,i].contour(xm,ym,H.T,[0],colors='w') 66 | 67 | cbar = plt.colorbar(q,cax=cax,orientation='horizontal',ticks=tiks**expo) 68 | cbar.set_ticklabels(tiks) 69 | cbar.set_label('[1/km$^2$]') 70 | 71 | axs[0,0].set_ylabel('Example float trajectories') 72 | axs[1,0].set_ylabel('Accumulated float density') 73 | axs[0,0].set_xlim(0,param1['Lx']) 74 | axs[0,0].set_ylim(0,param1['Ly']) 75 | axs[0,0].set_xticks([]) 76 | axs[0,0].set_yticks([]) 77 | 78 | axs[0,0].set_title(r'Low resolution, $\Delta x = $30km') 79 | axs[0,2].set_title(r'High resolution, $\Delta x = $7.5km') 80 | axs[0,1].set_title(r'LR + moderate backscatter') 81 | 82 | abc = 'abcdef' 83 | abcc = 'kkkwww' 84 | abci = 0 85 | for axcol in axs: 86 | for ax in axcol: 87 | plt.text(0.93,0.93,abc[abci],transform=ax.transAxes,fontweight='bold',color=abcc[abci]) 88 | abci += 1 89 | 90 | 91 | axs[-1,0].set_xlabel(r'$x$') 92 | axs[-1,1].set_xlabel(r'$x$') 93 | axs[-1,2].set_xlabel(r'$x$') 94 | 95 | axs[0,2].set_ylabel(r'$y$') 96 | axs[0,2].yaxis.set_label_position('right') 97 | 98 | axs[1,2].set_ylabel(r'$y$') 99 | axs[1,2].yaxis.set_label_position('right') 100 | 101 | #plt.savefig(path+'compare/floats_3runs.png',dpi=150) 102 | #plt.close(fig) 103 | plt.show() -------------------------------------------------------------------------------- /calc/floats/floats_plot_bf.py: -------------------------------------------------------------------------------- 1 | ## FLOATS PLOT 2 | import numpy as np 3 | from netCDF4 import Dataset 4 | from scipy.interpolate import RegularGridInterpolator as RGI 5 | import matplotlib.pyplot as plt 6 | from cmocean import cm 7 | 8 | plt.rcParams['mathtext.fontset'] = 'cm' 9 | plt.rcParams['mathtext.rm'] = 'serif' 10 | 11 | path = '/home/mkloewer/python/swm/' 12 | 13 | # OPTIONS# 14 | runfolder = [0,6,14] 15 | print('Plotting floats from run ' + str(runfolder)) 16 | 17 | ## LOAD DATA 18 | runpath1 = path+'data/run%04i' % runfolder[0] 19 | param1 = np.load(runpath1+'/param.npy').all() 20 | D1 = np.load(runpath1+'/analysis/floats.npy').all() 21 | 22 | runpath2 = path+'data/run%04i' % runfolder[1] 23 | param2 = np.load(runpath2+'/param.npy').all() 24 | D2 = np.load(runpath2+'/analysis/floats.npy').all() 25 | 26 | runpath3 = path+'data/run%04i' % runfolder[2] 27 | param3 = np.load(runpath3+'/param.npy').all() 28 | D3 = np.load(runpath3+'/analysis/floats.npy').all() 29 | 30 | expo = 0.5 # non-linear colorbar exponent 31 | 32 | dx,dy = D1['xm'][1]-D1['xm'][0],D1['ym'][1]-D1['ym'][0] 33 | D1['H'] = (D1['H']/dx/dy*1e6)**expo 34 | 35 | dx,dy = D2['xm'][1]-D2['xm'][0],D2['ym'][1]-D2['ym'][0] 36 | D2['H'] = (D2['H']/dx/dy*1e6)**expo 37 | 38 | dx,dy = D1['xm'][1]-D1['xm'][0],D1['ym'][1]-D1['ym'][0] 39 | D3['H'] = (D3['H']/dx/dy*1e6)**expo 40 | 41 | tiks = np.array([0,1,5,10,20,30,40])#,50,60,70,80,100,120,140,160,180]) 42 | levs = np.linspace(0,np.percentile(D1['H'],99),64) 43 | 44 | ## Plotting 45 | fig,axs = plt.subplots(2,3,sharex=True,sharey=True,figsize=(10,8)) 46 | plt.tight_layout(rect=[0,.09,1,0.98]) 47 | fig.subplots_adjust(wspace=0.03,hspace=0.03) 48 | 49 | pos1 = axs[-1,0].get_position() 50 | pos2 = axs[-1,-1].get_position() 51 | cax = fig.add_axes([pos1.x0,0.07,pos2.x1-pos1.x0,0.03]) 52 | 53 | N = 30 # number of trajectories to plot 54 | 55 | for iD,D in enumerate([D1,D3,D2]): 56 | for i in range(min(D['X'].shape[1],N)): # max num of floats to display 57 | z = np.random.randint(0,250,1)[0] 58 | axs[0,iD].plot(D['X'][:,40+i],D['Y'][:,40+i],color=cm.haline(z)) 59 | 60 | for i,D in enumerate([D1,D3,D2]): 61 | sx,sy = D['seedx'],D['seedy'] # unpack 62 | xm,ym,H = D['xm'],D['ym'],D['H'] 63 | axs[1,i].add_patch(plt.Rectangle((sx[0],sy[0]),sx[1]-sx[0],sy[1]-sy[0],fc='none',alpha=1,ec='k',lw=1.5)) 64 | q = axs[1,i].contourf(xm,ym,H.T,levs,extend='max',cmap=cm.thermal) 65 | axs[1,i].contour(xm,ym,H.T,[0],colors='w') 66 | 67 | cbar = plt.colorbar(q,cax=cax,orientation='horizontal',ticks=tiks**expo) 68 | cbar.set_ticklabels(tiks) 69 | cbar.set_label('[1/km$^2$]') 70 | 71 | axs[0,0].set_ylabel('Example float trajectories') 72 | axs[1,0].set_ylabel('Accumulated float density') 73 | axs[0,0].set_xlim(0,param1['Lx']) 74 | axs[0,0].set_ylim(0,param1['Ly']) 75 | axs[0,0].set_xticks([]) 76 | axs[0,0].set_yticks([]) 77 | 78 | axs[0,0].set_title(r'Low resolution, $\Delta x = $30km') 79 | axs[0,2].set_title(r'High resolution, $\Delta x = $7.5km') 80 | axs[0,1].set_title(r'LR + moderate backscatter') 81 | 82 | abc = 'abcdef' 83 | abcc = 'kkkwww' 84 | abci = 0 85 | for axcol in axs: 86 | for ax in axcol: 87 | plt.text(0.93,0.05,abc[abci],transform=ax.transAxes,fontweight='bold',color=abcc[abci]) 88 | abci += 1 89 | 90 | 91 | axs[-1,0].set_xlabel(r'$x$') 92 | axs[-1,1].set_xlabel(r'$x$') 93 | axs[-1,2].set_xlabel(r'$x$') 94 | 95 | axs[0,2].set_ylabel(r'$y$') 96 | axs[0,2].yaxis.set_label_position('right') 97 | 98 | axs[1,2].set_ylabel(r'$y$') 99 | axs[1,2].yaxis.set_label_position('right') 100 | 101 | plt.savefig(path+'compare/floats_3runs_bf.png',dpi=150) 102 | plt.close(fig) -------------------------------------------------------------------------------- /plot/Ro_hist_plot.py: -------------------------------------------------------------------------------- 1 | ## HISTOGRAM PLOTTING FOR REYNOLDS AND ROSSBY NUMBERS 2 | from __future__ import print_function 3 | 4 | path = '/network/home/aopp/kloewer/swm/paperplot/' 5 | path2 = '/network/aopp/cirrus/pred/kloewer/swm_bf_cntrl/' 6 | path3 = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 7 | 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | 11 | plt.rcParams['mathtext.fontset'] = 'cm' 12 | plt.rcParams['mathtext.rm'] = 'serif' 13 | 14 | # OPTIONS 15 | runfolder = [0,6,0,2,4] 16 | print('Creating Ro histogram plot from run '+str(runfolder)) 17 | 18 | ## read data 19 | runpath = path2+'data/run%04i' % runfolder[0] 20 | D1 = np.load(runpath+'/analysis/Ro_defo_hist.npy').all() 21 | 22 | runpath = path2+'data/run%04i' % runfolder[1] 23 | D2 = np.load(runpath+'/analysis/Ro_defo_hist.npy').all() 24 | 25 | runpath = path3+'run%04i' % runfolder[2] 26 | D3 = np.load(runpath+'/analysis/Ro_defo_hist.npy').all() 27 | print(np.load(runpath+'/param.npy').all()['n_diss']) 28 | 29 | runpath = path3+'run%04i' % runfolder[3] 30 | D4 = np.load(runpath+'/analysis/Ro_defo_hist.npy').all() 31 | print(np.load(runpath+'/param.npy').all()['n_diss']) 32 | 33 | runpath = path3+'run%04i' % runfolder[4] 34 | D5 = np.load(runpath+'/analysis/Ro_defo_hist.npy').all() 35 | print(np.load(runpath+'/param.npy').all()['n_diss']) 36 | 37 | ## EXTEND HISTOGRAM WITH ZERO TO THE RIGHT 38 | 39 | for D in [D1,D2,D3,D4,D5]: 40 | D['Ro_mid'] = np.hstack((D['Ro_mid'],10**1.5)) 41 | D['RoH'] = np.hstack((D['RoH'],0.)) 42 | 43 | ## CDISS 44 | Ro = np.linspace(10**-3.5,10**1.5,10000) 45 | cd = lambda d: 1/(1+(Ro/d)) 46 | 47 | ## PLOT 48 | fig,(ax1,ax2) = plt.subplots(2,1,figsize=(8,4.5),sharex=True) 49 | 50 | s = 1e6 51 | 52 | ax1.plot(D1['Ro_mid'],D1['RoH']/s,'C0',label=r'Low resolution, $\Delta x = $30km',lw=3) 53 | ax1.plot(D2['Ro_mid'],D2['RoH']/16/s,'C2',label=r'High resolution, $\Delta x = $7.5km',lw=3) 54 | ax1.plot(D3['Ro_mid'],D3['RoH']/s,'C1',label=r'LR + weak backscatter',ls='--') 55 | ax1.plot(D4['Ro_mid'],D4['RoH']/s,'C3',label=r'LR + moderate backscatter',ls='--') 56 | ax1.plot(D5['Ro_mid'],D5['RoH']/s,'C5',label=r'LR + strong backscatter',ls='--') 57 | 58 | ytikmax = 0.25 59 | 60 | ax1.axvline(np.log10(D1['Ro_mean']),0,ytikmax,c='C0',ls='-',lw=2) 61 | ax1.axvline(np.log10(D2['Ro_mean']),0,ytikmax,c='C2',ls='-',lw=2) 62 | ax1.axvline(np.log10(D3['Ro_mean']),0,ytikmax,c='C1',ls='--') 63 | ax1.axvline(np.log10(D4['Ro_mean']),0,ytikmax,c='C3',ls='--') 64 | ax1.axvline(np.log10(D5['Ro_mean']),0,ytikmax,c='C5',ls='--') 65 | 66 | ax1.text(np.log10(D1['Ro_mean'])-0.01,1.3,'mean($R_o$)',rotation=90,ha='right',color='k') 67 | 68 | ax2.plot(np.log10(Ro),cd(1.),'C1--',label=r'$c_{diss}$ for $R_{diss} = 1$, weak backscatter') 69 | ax2.plot(np.log10(Ro),cd(6.),'C3--',label=r'$c_{diss}$ for $R_{diss} = 6$, moderate backscatter') 70 | ax2.plot(np.log10(Ro),np.ones_like(Ro),'C5--',label=r'$c_{diss}$ for $R_{diss} = \infty$, strong backscatter') 71 | 72 | ax2.plot(np.ones(2)*np.log10(1),[-1,0.5],'C1') 73 | ax2.plot(np.ones(2)*np.log10(6),[-1,0.5],'C3') 74 | ax2.text(np.log10(1)-0.03,0.3,r'$R_{diss} = 1$',rotation=90,ha='right',color='k') 75 | ax2.text(np.log10(6)-0.03,0.3,r'$R_{diss} = 6$',rotation=90,ha='right',color='k') 76 | ax2.text(-2.9,0.6,r'$c_{diss} = (1 + \frac{R_o}{R_{diss}})^{-1}$', fontsize=15) 77 | 78 | ax2.legend(loc=3) 79 | ax1.legend(loc=1) 80 | 81 | ax1.set_xlim(-3,1) 82 | ax1.set_ylim(-0.1,3.5) 83 | ax2.set_ylim(-0.05,1.05) 84 | 85 | ax1.set_title('a',loc='left',fontweight='bold') 86 | ax1.set_title('Rossby number histogram') 87 | 88 | ax2.set_title('b',loc='left',fontweight='bold') 89 | ax2.set_title('Rossby number dissipation scaling') 90 | 91 | ax2.set_xlabel('log$_{10}(R_o)$') 92 | ax1.set_ylabel(r'$N$ $[10^6]$') 93 | 94 | plt.tight_layout() 95 | plt.savefig(path+'plots/Ro_hist.pdf') 96 | plt.close(fig) 97 | -------------------------------------------------------------------------------- /calc/misc/spec_ens _calc.py: -------------------------------------------------------------------------------- 1 | ## COMPUTE ENSTROPHY SPECTRUM 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | import time as tictoc 8 | from netCDF4 import Dataset 9 | import glob 10 | import matplotlib.pyplot as plt 11 | 12 | exec(open(path+'swm_param.py').read()) 13 | exec(open(path+'swm_operators.py').read()) 14 | exec(open(path+'swm_rhs.py').read()) 15 | exec(open(path+'swm_integration.py').read()) 16 | exec(open(path+'swm_output.py').read()) 17 | 18 | # OPTIONS 19 | runfolder = [2,3] 20 | print('Calculating EKE spectrogramms from run ' + str(runfolder)) 21 | 22 | ## 23 | def ens_spec_avg(z,dx,dy): 24 | """ Computes a wavenumber-frequency plot for 3D (t,x,y) data via radial (k = sqrt(kx**2 + ky**2)) integration. TODO: correct normalisation, so that the integral in normal space corresponds to the integral in Fourier space. 25 | """ 26 | 27 | nt,ny,nx = np.shape(z) 28 | kx = (1/(dx))*np.hstack((np.arange(0,(nx+1)/2.),np.arange(-nx/2.+1,0)))/float(nx) 29 | ky = (1/(dy))*np.hstack((np.arange(0,(ny+1)/2.),np.arange(-ny/2.+1,0)))/float(ny) 30 | 31 | kxx,kyy = np.meshgrid(kx,ky) 32 | # radial distance from kx,ky = 0 33 | kk = np.sqrt(kxx**2 + kyy**2) 34 | 35 | if nx >= ny: #kill negative wavenumbers 36 | k = kx[:int(nx/2)+1] 37 | else: 38 | k = ky[:int(ny/2)+1] 39 | 40 | dk = k[1] - k[0] 41 | 42 | # create radial coordinates, associated with k[i] 43 | # nearest point interpolation to get points within the -.5,.5 annulus 44 | rcoords = [] 45 | for i in range(len(k)): 46 | rcoords.append(np.where((kk>(k[i]-.5*dk))*(kk<=(k[i]+.5*dk)))) 47 | 48 | # 2D FFT average 49 | 50 | pz = np.empty((nt,ny,nx)) 51 | 52 | for i in range(nt): 53 | pz[i,:,:] = abs(np.fft.fft2(z[i,:,:]))**2 54 | if i % 100 == 0: 55 | print(i) 56 | 57 | pz_avg = .5*pz.mean(axis=0) 58 | 59 | # mulitply by dk to have the corresponding integral 60 | ens_spec = np.zeros(len(k)) 61 | for i in range(len(k)): 62 | ens_spec[i] = np.sum(pz_avg[rcoords[i][0],rcoords[i][1]])*dk 63 | 64 | return k[1:],ens_spec[1:] # eliminate zero wavenumber 65 | 66 | 67 | ## read data 68 | for r,i in zip(runfolder,range(len(runfolder))): 69 | runpath = path+'data/run%04i' % r 70 | 71 | if i == 0: 72 | u = np.load(runpath+'/u_sub.npy') 73 | v = np.load(runpath+'/v_sub.npy') 74 | #h = np.load(runpath+'/h_sub.npy') 75 | time = np.load(runpath+'/t_sub.npy') 76 | print('run %i read.' % r) 77 | 78 | else: 79 | u = np.concatenate((u,np.load(runpath+'/u_sub.npy'))) 80 | v = np.concatenate((v,np.load(runpath+'/v_sub.npy'))) 81 | #h = np.concatenate((h,np.load(runpath+'/h_sub.npy'))) 82 | time = np.hstack((time,np.load(runpath+'/t_sub.npy'))) 83 | print('run %i read.' % r) 84 | 85 | t = time / 3600. / 24. # in days 86 | tlen = len(time) 87 | dt = time[1] - time[0] 88 | 89 | ## read param 90 | global param 91 | param = np.load(runpath+'/param.npy').all() 92 | param['output'] = 0 93 | 94 | set_grad_mat() 95 | set_interp_mat() 96 | 97 | #reshape u,v 98 | u = u.reshape((tlen,param['Nu'])).T 99 | v = v.reshape((tlen,param['Nv'])).T 100 | z = (Gvx.dot(v) - Guy.dot(u)).T.reshape((tlen,param['ny']+1,param['nx']+1)) 101 | del u,v 102 | ## 103 | k,p = ens_spec_avg(z,param['dx'],param['dy']) 104 | 105 | ## 106 | dic = dict() 107 | all_var2export = ['k','p'] 108 | 109 | for v in all_var2export: 110 | exec('dic[v] ='+v) 111 | 112 | np.save(runpath+'/analysis/spec_ens.npy',dic) 113 | 114 | print('Everything stored.') 115 | -------------------------------------------------------------------------------- /calc/power_inout_calc.py: -------------------------------------------------------------------------------- 1 | ## POWER INPUT EXIT CALCULATION 2 | from __future__ import print_function 3 | 4 | # path 5 | import os 6 | #path = os.path.dirname(os.getcwd()) + '/' # on level above 7 | path = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 8 | os.chdir(path) # change working directory 9 | 10 | import numpy as np 11 | from scipy import sparse 12 | 13 | # OPTIONS 14 | # several entries in the list concatenates the runs and stores the result in the last folder 15 | runfolder = [4] 16 | print('Calculating power in/out from run ' + str(runfolder)) 17 | 18 | InPower_T = [] 19 | ExPower_T = [] 20 | BfricPower_T = [] 21 | 22 | ## read data 23 | for r in runfolder: # calculate each run separately 24 | runpath = path+'run%04i' % r 25 | 26 | skip = 5*365 27 | u = np.load(runpath+'/u_sub.npy')[skip:,...] 28 | v = np.load(runpath+'/v_sub.npy')[skip:,...] 29 | eta = np.load(runpath+'/eta_sub.npy')[skip:,...] 30 | t = np.load(runpath+'/t_sub.npy')[skip:,...] 31 | print('run %i read.' % r) 32 | 33 | ## read param 34 | global param 35 | param = np.load(runpath+'/param.npy').all() 36 | 37 | # import functions 38 | funpath = '/network/home/aopp/kloewer/git/swm/' 39 | exec(open(funpath+'swm_param.py').read()) 40 | exec(open(funpath+'swm_operators.py').read()) 41 | 42 | set_grad_mat() 43 | set_interp_mat() 44 | set_coriolis() 45 | set_forcing() 46 | 47 | tlen = len(t) 48 | ## create ouputfolder 49 | try: 50 | os.mkdir(runpath+'/analysis') 51 | except: 52 | pass 53 | 54 | ## reshape u,v 55 | u = u.reshape((tlen,param['Nu'])).T 56 | v = v.reshape((tlen,param['Nv'])).T 57 | h = eta.reshape((tlen,param['NT'])).T + param['H'] 58 | print('Reshape done.') 59 | 60 | h_q = ITq.dot(h) 61 | h_u = ITu.dot(h) 62 | h_v = ITv.dot(h) 63 | print('h_u, h_v, h_q done.') 64 | 65 | ## input 66 | # Fx is actually Fx/rho 67 | InPower = param['rho']*(u.T*Fx).mean(axis=0) 68 | print('Input Power done.') 69 | 70 | # Shchepetkin and O'Brien divergence of a tensor formulation 71 | hS = ((Gux.dot(u)-Gvy.dot(v))*h,(G2vx.dot(v) + G2uy.dot(u))*h_q) 72 | diff_u = (GTx.dot(hS[0]) + Gqy.dot(hS[1])) / h_u 73 | diff_v = (Gqx.dot(hS[1]) - GTy.dot(hS[0])) / h_v 74 | 75 | del hS, h_u, h_v 76 | 77 | # biharmonic stress tensor R = (R11, R12, R12, -R11), store only R11, R12 78 | hR = ((Gux.dot(diff_u) - Gvy.dot(diff_v))*h, (G2vx.dot(diff_v) + G2uy.dot(diff_u))*h_q) 79 | 80 | del h_q, diff_u, diff_v 81 | 82 | bidiff_u = (GTx.dot(hR[0]) + Gqy.dot(hR[1])) 83 | bidiff_v = (Gqx.dot(hR[1]) - GTy.dot(hR[0])) 84 | 85 | del hR 86 | 87 | print('Biharmonic dissipation term done.') 88 | 89 | ExPower_u = -param['nu_B']*param['rho']*(u*bidiff_u).mean(axis=1) 90 | ExPower_v = -param['nu_B']*param['rho']*(v*bidiff_v).mean(axis=1) 91 | 92 | del bidiff_u, bidiff_v 93 | 94 | print('Exit Power done.') 95 | 96 | BfricPower = -param['rho']*param['c_D']*((IuT.dot(u**2) + IvT.dot(v**2))**(3./2.)).mean(axis=1) 97 | 98 | # Interpolation 99 | InPower_T.append(IuT.dot(InPower)) 100 | ExPower_T.append(IuT.dot(ExPower_u) + IvT.dot(ExPower_v)) 101 | BfricPower_T.append(BfricPower) 102 | 103 | # Averaging over runs 104 | InPower_T = np.array(InPower_T).mean(axis=0) 105 | ExPower_T = np.array(ExPower_T).mean(axis=0) 106 | BfricPower_T = np.array(BfricPower_T).mean(axis=0) 107 | 108 | ## STORING 109 | dic = dict() 110 | all_var2export = ['InPower_T','ExPower_T','BfricPower_T'] 111 | for v in all_var2export: 112 | exec('dic[v] ='+v) 113 | 114 | np.save(runpath+'/analysis/power_map.npy',dic) 115 | print('Everything stored.') 116 | -------------------------------------------------------------------------------- /calc/mean_calc.py: -------------------------------------------------------------------------------- 1 | ## PRODUCE MEAN CALCULATIONS AND EXPORT AS .NPY 2 | from __future__ import print_function 3 | 4 | # path 5 | import os 6 | funpath = '/network/home/aopp/kloewer/git/swm/' # path for functions swm_operators.py etc 7 | path = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' # path for data 8 | os.chdir(path) 9 | 10 | import numpy as np 11 | from scipy import sparse 12 | 13 | # OPTIONS 14 | runfolder = [5] 15 | print('Calculating means from run ' + str(runfolder)) 16 | 17 | ## read data 18 | for r,i in zip(runfolder,range(len(runfolder))): 19 | runpath = path+'run%04i' % r 20 | 21 | if i == 0: 22 | skip = 5*365 23 | #skip = 0 24 | u = np.load(runpath+'/u_sub.npy')[skip:,...] 25 | v = np.load(runpath+'/v_sub.npy')[skip:,...] 26 | eta = np.load(runpath+'/eta_sub.npy')[skip:,...] 27 | t = np.load(runpath+'/t_sub.npy')[skip:,...] 28 | print('run %i read.' % r) 29 | 30 | else: 31 | # use [1:,...] to not have one time step double 32 | u = np.concatenate((u,np.load(runpath+'/u_sub.npy')))[1:,...] 33 | v = np.concatenate((v,np.load(runpath+'/v_sub.npy')))[1:,...] 34 | eta = np.concatenate((eta,np.load(runpath+'/eta_sub.npy')))[1:,...] 35 | t = np.hstack((t,np.load(runpath+'/t_sub.npy')))[1:,...] 36 | print('run %i read.' % r) 37 | 38 | ## read param 39 | global param 40 | param = np.load(runpath+'/param.npy').all() 41 | 42 | # import functions 43 | 44 | exec(open(funpath+'swm_param.py').read()) 45 | exec(open(funpath+'swm_operators.py').read()) 46 | 47 | set_grad_mat() 48 | set_interp_mat() 49 | set_lapl_mat() 50 | set_coriolis() 51 | 52 | tlen = len(t) 53 | ## create ouputfolder 54 | try: 55 | os.mkdir(runpath+'/analysis') 56 | except: 57 | pass 58 | 59 | ## reshape u,v 60 | u = u.reshape((tlen,param['Nu'])).T 61 | v = v.reshape((tlen,param['Nv'])).T 62 | eta = eta.reshape((tlen,param['NT'])).T 63 | print('Reshape done.') 64 | 65 | ## U,V,H mean 66 | # thickness-weighted averaging for u,v (Aiki, 2016) 67 | etam = eta.mean(axis=1) # temporal average 68 | um = (ITu.dot(eta + param['H'])*u).mean(axis=1) / ITu.dot(etam + param['H']) 69 | vm = (ITv.dot(eta + param['H'])*v).mean(axis=1) / ITv.dot(etam + param['H']) 70 | print('u,v,eta mean done.') 71 | 72 | # TOTAL KINETIC ENERGY 73 | ke = .5*param['rho']*((eta+param['H'])*(IuT.dot(u**2) + IvT.dot(v**2))).mean(axis=1) 74 | # TOTAL (PERTURBATION) POTENTIAL ENERGY 75 | pe = .5*param['rho']*param['g']*(eta**2).mean(axis=1) 76 | print('KE, PE done.') 77 | 78 | # MEAN KINETIC ENERGY 79 | mke = .5*param['rho']*(etam+param['H'])*(IuT.dot(um**2) + IvT.dot(vm**2)) 80 | # Mean Potential Energy 81 | mpe = .5*param['g']*param['rho']*etam**2 82 | print('MKE, MPE done.') 83 | 84 | # Eddy potential energy 85 | epe = .5*param['rho']*param['g']*eta.var(axis=1) 86 | 87 | # Eddy kinetic energy 88 | uprime = ((u.T - um).T) 89 | vprime = ((v.T - vm).T) 90 | print('Prime anomalies done.') 91 | 92 | eke = .5*param['rho']*((eta+param['H'])*(IuT.dot(uprime**2) + IvT.dot(vprime**2))).mean(axis=1) 93 | print('EPE, EKE done.') 94 | del uprime,vprime 95 | 96 | # SPEED MEAN 97 | speedm = np.sqrt(IuT.dot(u**2) + IvT.dot(v**2)).mean(axis=1) 98 | print('Rel Vort, Speed done.') 99 | 100 | ## ENERGY TIME SERIES 101 | PEm = (.5*param['g']*param['rho']*eta**2).mean(axis=0) 102 | print('Potential Energy done.') 103 | 104 | KEm = .5*param['rho']*((eta+param['H'])*(IuT.dot(u**2) + IvT.dot(v**2))).mean(axis=0) 105 | print('Kinetic Energy done.') 106 | 107 | ## STORING 108 | dic = dict() 109 | all_var2export = ['um','vm','etam','ke','pe','mke','eke','mpe','epe','speedm'] 110 | #all_var2export = ['t','PEm','KEm'] 111 | 112 | for v in all_var2export: 113 | exec('dic[v] ='+v) 114 | 115 | np.save(runpath+'/analysis/mean.npy',dic) 116 | print('Everything stored.') 117 | -------------------------------------------------------------------------------- /calc/mean_timeseries_calc.py: -------------------------------------------------------------------------------- 1 | ## PRODUCE MEAN CALCULATIONS AND EXPORT AS .NPY 2 | from __future__ import print_function 3 | 4 | # path 5 | import os 6 | funpath = '/network/home/aopp/kloewer/git/swm/' 7 | path = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 8 | os.chdir(path) # change working directory 9 | 10 | import numpy as np 11 | from scipy import sparse 12 | 13 | # OPTIONS 14 | runfolder = [5] 15 | print('Calculating timeseries from run ' + str(runfolder)) 16 | 17 | ## read data 18 | for r,i in zip(runfolder,range(len(runfolder))): 19 | runpath = path+'run%04i' % r 20 | 21 | if i == 0: 22 | #skip = 5*365 23 | skip = 0 24 | u = np.load(runpath+'/u_sub.npy')[skip:,...] 25 | v = np.load(runpath+'/v_sub.npy')[skip:,...] 26 | eta = np.load(runpath+'/eta_sub.npy')[skip:,...] 27 | t = np.load(runpath+'/t_sub.npy')[skip:,...] 28 | print('run %i read.' % r) 29 | 30 | else: 31 | # use [1:,...] to not have one time step double 32 | u = np.concatenate((u,np.load(runpath+'/u_sub.npy')))[1:,...] 33 | v = np.concatenate((v,np.load(runpath+'/v_sub.npy')))[1:,...] 34 | eta = np.concatenate((eta,np.load(runpath+'/eta_sub.npy')))[1:,...] 35 | t = np.hstack((t,np.load(runpath+'/t_sub.npy')))[1:,...] 36 | print('run %i read.' % r) 37 | 38 | ## read param 39 | global param 40 | param = np.load(runpath+'/param.npy').all() 41 | 42 | # import functions 43 | exec(open(funpath+'swm_param.py').read()) 44 | exec(open(funpath+'swm_operators.py').read()) 45 | 46 | set_grad_mat() 47 | set_interp_mat() 48 | set_lapl_mat() 49 | set_coriolis() 50 | 51 | tlen = len(t) 52 | ## create ouputfolder 53 | try: 54 | os.mkdir(runpath+'/analysis') 55 | except: 56 | pass 57 | 58 | ## reshape u,v 59 | u = u.reshape((tlen,param['Nu'])).T 60 | v = v.reshape((tlen,param['Nv'])).T 61 | eta = eta.reshape((tlen,param['NT'])).T 62 | print('Reshape done.') 63 | 64 | ## U,V,H mean 65 | # thickness-weighted averaging for u,v (Aiki, 2016) 66 | #etam = eta.mean(axis=1) # temporal average 67 | #um = (ITu.dot(eta + param['H'])*u).mean(axis=1) / ITu.dot(etam + param['H']) 68 | #vm = (ITv.dot(eta + param['H'])*v).mean(axis=1) / ITv.dot(etam + param['H']) 69 | #print('u,v,eta mean done.') 70 | 71 | # TOTAL KINETIC ENERGY 72 | #ke = .5*param['rho']*((eta+param['H'])*(IuT.dot(u**2) + IvT.dot(v**2))).mean(axis=1) 73 | # TOTAL (PERTURBATION) POTENTIAL ENERGY 74 | #pe = .5*param['rho']*param['g']*(eta**2).mean(axis=1) 75 | #print('KE, PE done.') 76 | 77 | # MEAN KINETIC ENERGY 78 | #mke = .5*param['rho']*(etam+param['H'])*(IuT.dot(um**2) + IvT.dot(vm**2)) 79 | # Mean Potential Energy 80 | #mpe = .5*param['g']*param['rho']*etam**2 81 | #print('MKE, MPE done.') 82 | 83 | # Eddy potential energy 84 | #epe = .5*param['rho']*param['g']*eta.var(axis=1) 85 | 86 | # Eddy kinetic energy 87 | #uprime = ((u.T - um).T) 88 | #vprime = ((v.T - vm).T) 89 | #print('Prime anomalies done.') 90 | 91 | #eke = .5*param['rho']*((eta+param['H'])*(IuT.dot(uprime**2) + IvT.dot(vprime**2))).mean(axis=1) 92 | #print('EPE, EKE done.') 93 | #del uprime,vprime 94 | 95 | # SPEED MEAN 96 | #speedm = np.sqrt(IuT.dot(u**2) + IvT.dot(v**2)).mean(axis=1) 97 | #print('Rel Vort, Speed done.') 98 | 99 | ## ENERGY TIME SERIES 100 | PEm = (.5*param['g']*param['rho']*eta**2).mean(axis=0) 101 | print('Potential Energy done.') 102 | 103 | KEm = .5*param['rho']*((eta+param['H'])*(IuT.dot(u**2) + IvT.dot(v**2))).mean(axis=0) 104 | print('Kinetic Energy done.') 105 | 106 | ## STORING 107 | dic = dict() 108 | #all_var2export = ['um','vm','etam','ke','pe','mke','eke','mpe','epe','speedm'] 109 | all_var2export = ['t','PEm','KEm'] 110 | 111 | for v in all_var2export: 112 | exec('dic[v] ='+v) 113 | 114 | np.save(runpath+'/analysis/mean_timeseries.npy',dic) 115 | print('Everything stored.') 116 | -------------------------------------------------------------------------------- /calc/spec_calc.py: -------------------------------------------------------------------------------- 1 | ## COMPUTE EKE SPECTRUM 2 | from __future__ import print_function 3 | 4 | # path 5 | import os 6 | #path = os.path.dirname(os.getcwd()) + '/' # on level above 7 | path = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 8 | os.chdir(path) # change working directory 9 | 10 | import numpy as np 11 | from scipy import sparse 12 | 13 | # OPTIONS 14 | # several entries in the list concatenates the runs and stores the result in the last folder 15 | runfolder = [5] 16 | print('Calculating eke spectrum from run ' + str(runfolder)) 17 | 18 | ## 19 | def eke_spec_avg(u,v,dx,dy): 20 | """ Computes a wavenumber-frequency plot for 3D (t,x,y) data via radial (k = sqrt(kx**2 + ky**2)) integration. TODO: correct normalisation, so that the integral in normal space corresponds to the integral in Fourier space. 21 | """ 22 | 23 | nt,ny,nx = np.shape(u) 24 | kx = (1/(dx))*np.hstack((np.arange(0,(nx+1)/2.),np.arange(-nx/2.+1,0)))/float(nx) 25 | ky = (1/(dy))*np.hstack((np.arange(0,(ny+1)/2.),np.arange(-ny/2.+1,0)))/float(ny) 26 | 27 | kxx,kyy = np.meshgrid(kx,ky) 28 | # radial distance from kx,ky = 0 29 | kk = np.sqrt(kxx**2 + kyy**2) 30 | 31 | if nx >= ny: #kill negative wavenumbers 32 | k = kx[:int(nx/2)+1] 33 | else: 34 | k = ky[:int(ny/2)+1] 35 | 36 | dk = k[1] - k[0] 37 | 38 | # 2D FFT average 39 | p_eke = np.empty((nt,ny,nx)) 40 | nxy2 = nx**2*ny**2 41 | 42 | for i in range(nt): 43 | pu = abs(np.fft.fft2(u[i,:,:]))**2/nxy2 44 | pv = abs(np.fft.fft2(v[i,:,:]))**2/nxy2 45 | p_eke[i,:,:] = pu+pv 46 | if ((i+1)/nt*100 % 5) < (i/nt*100 % 5): 47 | print(str(int((i+1)/nt*100.))+'%') 48 | 49 | p_eke_avg = .5*p_eke.mean(axis=0) 50 | 51 | # create radial coordinates, associated with k[i] 52 | rcoords = [] 53 | for i in range(len(k)): 54 | rcoords.append(np.where(kk= ny: #kill negative wavenumbers 31 | k = kx[:int(nx/2)+1] 32 | else: 33 | k = ky[:int(ny/2)+1] 34 | 35 | f = f[:int(nt/2)+1] #kill negative frequencies 36 | dk = k[1] - k[0] 37 | 38 | # create radial coordinates, associated with k[i] 39 | # nearest point interpolation to get points within the -.5,.5 annulus 40 | rcoords = [] 41 | for i in range(len(k)): 42 | rcoords.append(np.where((kk>(k[i]-.5*dk))*(kk<=(k[i]+.5*dk)))) 43 | 44 | # 3D FFT 45 | p = np.fft.fftn(a) 46 | p = np.real(p * np.conj(p)) 47 | 48 | # mulitply by dk to have the corresponding integral 49 | spec = np.zeros((len(k),len(f))) 50 | for i in range(len(k)): 51 | spec[i,:] = np.sum(p[:int(nt/2)+1,rcoords[i][0],rcoords[i][1]],axis=1)*dk 52 | 53 | return k,f,spec 54 | 55 | ## read data 56 | for r,i in zip(runfolder,range(len(runfolder))): 57 | runpath = path+'data/run%04i' % r 58 | 59 | if i == 0: 60 | #u = np.load(runpath+'/u_sub.npy') 61 | #v = np.load(runpath+'/v_sub.npy') 62 | h = np.load(runpath+'/h_sub.npy') 63 | time = np.load(runpath+'/t_sub.npy') 64 | print('run %i read.' % r) 65 | 66 | else: 67 | #u = np.concatenate((u,np.load(runpath+'/u_sub.npy'))) 68 | #v = np.concatenate((v,np.load(runpath+'/v_sub.npy'))) 69 | h = np.concatenate((h,np.load(runpath+'/h_sub.npy'))) 70 | time = np.hstack((time,np.load(runpath+'/t_sub.npy'))) 71 | print('run %i read.' % r) 72 | 73 | t = time / 3600. / 24. # in days 74 | tlen = len(time) 75 | dt = time[1] - time[0] 76 | 77 | ## read param 78 | global param 79 | param = np.load(runpath+'/param.npy').all() 80 | 81 | ## 82 | k,f,spec3d = trispec(h,dt,param['dx'],param['dy']) 83 | 84 | 85 | ## rossby radius 86 | Ro_min = param['c_phase']/f_T.max() 87 | Ro_max = param['c_phase']/f_T.min() 88 | # dispersion relation 89 | Ro_disp_min = param['beta']*k/(k**2 + 1./Ro_min**2) 90 | Ro_disp_max = param['beta']*k/(k**2 + 1./Ro_max**2) 91 | 92 | 93 | ## plotting 3D 94 | sd = 3600.*24. 95 | 96 | fig,ax = plt.subplots(1,1) 97 | c1 = ax.contourf(k[1:]*1e3,f[1:]*sd,np.log10(spec3d[1:,1:].T),64,cmap='viridis') 98 | ax.loglog() 99 | 100 | plt.colorbar(c1,ax=ax) 101 | 102 | ax.plot(Ro_min*np.ones(2)*1e3,[1./f[-1]/sd,1/f[1]/sd],'w') 103 | ax.plot(Ro_max*np.ones(2)*1e3,[1./f[-1]/sd,1/f[1]/sd],'w') 104 | 105 | ax.plot(1./k[-1]*np.ones(2)/1e3,[1./f_T.min()/3600./24.,1./f_T.min()/3600./24.],'k') 106 | ax.plot(1./k[-1]*np.ones(2)/1e3,[1./f_T.max()/3600./24.,1./f_T.max()/3600./24.],'k') 107 | 108 | 109 | ax.plot(1./k[1:]/1e3,1./Ro_disp_min[1:]/3600./24.,'k') 110 | ax.plot(1./k[1:]/1e3,1./Ro_disp_max[1:]/3600./24.,'k') 111 | 112 | ax.set_xlim(1./k[-1]/1e3,1./k[1]/1e3) 113 | ax.set_ylim(1./f[-1],1./f[1]) 114 | 115 | ax.set_xlabel('wavelength [km]') 116 | ax.set_ylabel('period [days]') 117 | ax.set_title('3D power spectrum of $\eta$') 118 | plt.tight_layout() 119 | plt.show() -------------------------------------------------------------------------------- /calc/misc/Re_hist_calc.py: -------------------------------------------------------------------------------- 1 | ## HISTOGRAM COMPUTATIONS FOR REYNOLDS AND ROSSBY NUMBERS 2 | from __future__ import print_function 3 | 4 | # path 5 | import os 6 | path = os.path.dirname(os.getcwd()) + '/' # on level above 7 | os.chdir(path) # change working directory 8 | 9 | import numpy as np 10 | from scipy import sparse 11 | 12 | # OPTIONS 13 | runfolder = [0] 14 | print('Calculating Reynolds histograms from run ' + str(runfolder)) 15 | 16 | ReH = [] 17 | Re_mean = [] 18 | Re_median = [] 19 | 20 | ## read data - calculate each run separately 21 | for r,i in zip(runfolder,range(len(runfolder))): 22 | runpath = path+'data/run%04i' % r 23 | 24 | skip = 5*365 25 | u = np.load(runpath+'/u_sub.npy')[skip:,...] 26 | v = np.load(runpath+'/v_sub.npy')[skip:,...] 27 | eta = np.load(runpath+'/eta_sub.npy')[skip:,...] 28 | t = np.load(runpath+'/t_sub.npy')[skip:,...] 29 | print('run %i read.' % r) 30 | 31 | ## read param 32 | global param 33 | param = np.load(runpath+'/param.npy').all() 34 | 35 | # import functions 36 | exec(open(path+'swm_param.py').read()) 37 | exec(open(path+'swm_operators.py').read()) 38 | 39 | set_grad_mat() 40 | set_interp_mat() 41 | set_coriolis() 42 | 43 | tlen = len(t) 44 | ## create ouputfolder 45 | try: 46 | os.mkdir(runpath+'/analysis') 47 | except: 48 | pass 49 | 50 | ## reshape u,v 51 | u = u.reshape((tlen,param['Nu'])).T 52 | v = v.reshape((tlen,param['Nv'])).T 53 | h = eta.reshape((tlen,param['NT'])).T + param['H'] 54 | print('Reshape done.') 55 | 56 | ## COMPUTE REYNOLDS, ROSSBY 57 | u_T = IuT.dot(u) 58 | v_T = IvT.dot(v) 59 | print('u,v interpolation done.') 60 | 61 | #advective term 62 | adv_u = u_T*Gux.dot(u) + v_T*IqT.dot(Guy.dot(u)) 63 | adv_v = u_T*IqT.dot(Gvx.dot(v)) + v_T*Gvy.dot(v) 64 | del u_T,v_T 65 | adv_term = np.sqrt(adv_u**2 + adv_v**2) 66 | del adv_u, adv_v 67 | print('Advection term done.') 68 | 69 | #diffusive term 70 | S = (Gux.dot(u)-Gvy.dot(v),G2vx.dot(v) + G2uy.dot(u)) 71 | del u,v 72 | hS = (h*S[0],ITq.dot(h)*S[1]) 73 | del S 74 | print('Stress tensor S done.') 75 | 76 | diff_u = (GTx.dot(hS[0]) + Gqy.dot(hS[1])) / ITu.dot(h) 77 | diff_v = (Gqx.dot(hS[1]) - GTy.dot(hS[0])) / ITv.dot(h) 78 | del hS 79 | print('Harmonic part done.') 80 | 81 | # biharmonic stress tensor R = (R11, R12, R12, -R11), store only R11, R12 82 | R = (Gux.dot(diff_u) - Gvy.dot(diff_v), G2vx.dot(diff_v) + G2uy.dot(diff_u)) 83 | del diff_u, diff_v 84 | hR = (h*R[0],ITq.dot(h)*R[1]) 85 | del R 86 | print('Stress tensor R done.') 87 | 88 | bidiff_u = param['nu_B']*(GTx.dot(hR[0]) + Gqy.dot(hR[1])) / ITu.dot(h) 89 | bidiff_v = param['nu_B']*(Gqx.dot(hR[1]) - GTy.dot(hR[0])) / ITv.dot(h) 90 | del h,hR 91 | print('Biharmonic part done.') 92 | 93 | diff_term = np.sqrt(IuT.dot(bidiff_u**2) + IvT.dot(bidiff_v**2)) 94 | print('Diff term done.') 95 | del bidiff_u,bidiff_v 96 | 97 | # actual number 98 | Re = (adv_term / diff_term).flatten() 99 | print('Re computed.') 100 | del adv_term, diff_term 101 | 102 | Re_mean.append(Re.mean()) 103 | Re_median.append(np.median(Re)) 104 | Re = np.log10(Re) 105 | 106 | # histogram 107 | Re_min = -3. # in log scale 108 | Re_max = 5. 109 | N = 300 110 | 111 | ReH_temp,Re_edges = np.histogram(Re,np.linspace(Re_min,Re_max,N)) 112 | print('Re histogram done.') 113 | del Re 114 | 115 | # store each run in a list 116 | ReH.append(ReH_temp) 117 | 118 | Re_mid = Re_edges[:-1] + np.diff(Re_edges)/2. 119 | 120 | 121 | ReH = np.array(ReH).sum(axis=0) 122 | Re_mean = np.array(Re_mean).mean() 123 | Re_median = np.median(np.array(Re_median)) #actually median of medians though... 124 | 125 | ## STORING in last 126 | dic = dict() 127 | all_var2export = ['ReH','Re_mid','Re_edges','Re_mean','Re_median'] 128 | 129 | for vars in all_var2export: 130 | exec('dic[vars] ='+vars) 131 | 132 | np.save(runpath+'/analysis/Re_hist.npy',dic) 133 | -------------------------------------------------------------------------------- /calc/misc/diss_vis.py: -------------------------------------------------------------------------------- 1 | ## UNDERSTANDING DISSIPATION 2 | from __future__ import print_function 3 | path = '/home/mkloewer/python/swm/' 4 | import os; os.chdir(path) # change working directory 5 | import numpy as np 6 | from scipy import sparse 7 | from scipy.integrate import cumtrapz 8 | import matplotlib.pyplot as plt 9 | import time as tictoc 10 | from netCDF4 import Dataset 11 | import glob 12 | from cmocean import cm 13 | 14 | # import functions 15 | exec(open(path+'swm_param.py').read()) 16 | exec(open(path+'swm_operators.py').read()) 17 | exec(open(path+'swm_output.py').read()) 18 | exec(open(path+'stoch/swm_rhs.py').read()) 19 | 20 | ## OPTIONS 21 | runfolder = [3,10] 22 | 23 | ## read data 24 | runpath = path+'data/run%04i' % runfolder[0] 25 | ncu = Dataset(runpath+'/u.nc') 26 | ncv = Dataset(runpath+'/v.nc') 27 | nch = Dataset(runpath+'/h.nc') 28 | 29 | u1 = ncu['u'][-1000,:,:].flatten() 30 | v1 = ncv['v'][-1000,:,:].flatten() 31 | h1 = nch['h'][-1000,:,:].flatten() 32 | print('netCDF data read.') 33 | 34 | # close netcdfs 35 | ncu.close() 36 | ncv.close() 37 | nch.close() 38 | 39 | param1 = np.load(runpath+'/param.npy').all() 40 | param1['output'] = 0 41 | 42 | ## 43 | runpath = path+'data/run%04i' % runfolder[1] 44 | ncu = Dataset(runpath+'/u.nc') 45 | ncv = Dataset(runpath+'/v.nc') 46 | nch = Dataset(runpath+'/h.nc') 47 | 48 | u2 = ncu['u'][-1,:,:].flatten() 49 | v2 = ncv['v'][-1,:,:].flatten() 50 | h2 = nch['h'][-1,:,:].flatten() 51 | print('netCDF data read.') 52 | 53 | # close netcdfs 54 | ncu.close() 55 | ncv.close() 56 | nch.close() 57 | 58 | param2 = np.load(runpath+'/param.npy').all() 59 | param2['output'] = 0 60 | 61 | ## 62 | global param 63 | 64 | def Q1(u,v,h): 65 | 66 | set_grad_mat() 67 | set_interp_mat() 68 | set_lapl_mat() 69 | set_coriolis() 70 | 71 | h_u = ITu.dot(h) # h on u-grid 72 | h_v = ITv.dot(h) # h on v-grid 73 | h_q = ITq.dot(h) # h on q-grid 74 | 75 | dudx = Gux.dot(u) 76 | dudy = Guy.dot(u) 77 | dvdx = Gvx.dot(v) 78 | dvdy = Gvy.dot(v) 79 | 80 | #diff_u, diff_v = mixing(u,v,h,h_q,h_u,h_v) # harmonic 81 | #bidiff_u, bidiff_v = mixing(diff_u,diff_v,h,h_q,h_u,h_v) # apply twice = biharmonic 82 | 83 | diss_e = (dudx*Gux.dot(Lu.dot(u)) + dvdy*Gvy.dot(Lv.dot(v))) 84 | 85 | return diss_e 86 | 87 | def Q2(u,v,h): 88 | 89 | set_grad_mat() 90 | set_interp_mat() 91 | set_lapl_mat() 92 | set_coriolis() 93 | 94 | h_u = ITu.dot(h) # h on u-grid 95 | h_v = ITv.dot(h) # h on v-grid 96 | h_q = ITq.dot(h) # h on q-grid 97 | 98 | dudx = Gux.dot(u) 99 | dudy = Guy.dot(u) 100 | dvdx = Gvx.dot(v) 101 | dvdy = Gvy.dot(v) 102 | 103 | diff_u, diff_v = mixing(u,v,h,h_q,h_u,h_v) # harmonic 104 | bidiff_u, bidiff_v = mixing(diff_u,diff_v,h,h_q,h_u,h_v) # apply twice = biharmonic 105 | 106 | #bidiff_u = LLu.dot(u) 107 | #bidiff_v = LLv.dot(v) 108 | 109 | #diss_e = param['B']*(dudx*Gux.dot(Lu.dot(u)) + dvdy*Gvy.dot(Lv.dot(v))) 110 | 111 | return IuT.dot(u*bidiff_u) + IvT.dot(v*bidiff_v) 112 | 113 | param = param2 114 | q = Q1(u2,v2,h2+param['H']) 115 | q2 = Q2(u2,v2,h2+param['H']) 116 | 117 | ## plotting 118 | fig,(ax1,ax2) = plt.subplots(1,2,sharex=True,sharey=True,figsize=(12,6)) 119 | plt.tight_layout(rect=[0,0,1,0.95]) 120 | 121 | pq = q*2e16*100 122 | pq2 = q2*2e16 123 | 124 | levs = np.linspace(-abs(pq2).max()*0.02,abs(pq2).max()*0.02,64) 125 | 126 | param = param2 127 | c = ax1.contourf(param2['x_T'],param2['y_T'],h2mat(pq),levs,extend='both',cmap='RdBu_r') 128 | c = ax2.contourf(param2['x_T'],param2['y_T'],h2mat(pq2),levs,extend='both',cmap='RdBu_r') 129 | 130 | ax1.set_xticks([]) 131 | ax1.set_yticks([]) 132 | ax1.set_xlabel('x') 133 | ax2.set_xlabel('x') 134 | ax1.set_ylabel('y') 135 | 136 | ax1.set_xlim(571e3,1824e3) 137 | ax1.set_ylim(1051e3,2131e3) 138 | 139 | ax1.set_title(r'$100*\nabla\mathbf{u} \cdot \nabla(\nabla^2\mathbf{u})$') 140 | ax2.set_title(r'$\mathbf{u} \cdot \nabla^4\mathbf{u}$') 141 | 142 | cbar = plt.colorbar(c,ax=(ax1,ax2),ticks=[-1,-0.5,0,0.5,1]) 143 | cbar.set_label(r'[$2 \cdot 10^{-16}m^{-2}s^{-2}$]') 144 | plt.show() -------------------------------------------------------------------------------- /calc/floats/floats_calc_meanflow.py: -------------------------------------------------------------------------------- 1 | ## LAGRANGIAN FLOATS 2 | import numpy as np 3 | from netCDF4 import Dataset 4 | from scipy.interpolate import RegularGridInterpolator as RGI 5 | 6 | path = '/home/mkloewer/python/swm/' 7 | 8 | # OPTIONS 9 | runfolder = [14] 10 | print('Calculating floats from run ' + str(runfolder)) 11 | 12 | ## pad function for u,v 13 | def uv_pad(u,v): 14 | """ Pads u,v with kinematic and lateral boundary conditions. """ 15 | bs = 0 # boundary speed (positive inwards) 16 | u = np.pad(u,((1,1),(1,1)),'constant',constant_values=((bs,-bs),(bs,-bs))) # kinematic bc 17 | v = np.pad(v,((1,1),(1,1)),'constant',constant_values=((bs,-bs),(bs,-bs))) 18 | 19 | return u,v 20 | 21 | runpath = path+'data/run%04i' % runfolder[0] 22 | 23 | D = np.load(runpath+'/analysis/mean.npy').all() 24 | param = np.load(runpath+'/param.npy').all() 25 | 26 | u = D['um'].reshape((param['ny'],param['nx']-1)) 27 | v = D['vm'].reshape((param['ny']-1,param['nx'])) 28 | 29 | dt = 6*3600. 30 | 31 | # renaming for convenience 32 | x_u = param['x_u'] 33 | y_u = param['y_u'] 34 | 35 | x_v = param['x_v'] 36 | y_v = param['y_v'] 37 | 38 | # pad x,y to include the boundary conditions 39 | # grid is not equidistant at the boundary however ... 40 | x_u = np.hstack((0.,x_u,param['Lx'])) 41 | y_u = np.hstack((0.,y_u,param['Ly'])) 42 | 43 | y_v = np.hstack((0,y_v,param['Ly'])) 44 | x_v = np.hstack((0,x_v,param['Lx'])) 45 | 46 | print('Grid read.') 47 | 48 | ## OPTIONS 49 | N = 10000 # number of floats 50 | ntime = 1460 # number of timesteps to integrate forward: equals one year 51 | R_chunk = 10 52 | 53 | # preallocate 54 | nbins = 254 55 | H = np.zeros((nbins,nbins)) 56 | 57 | #exclude up to 30km from boundary 58 | Hrange = [[30e3,3810e3],[30e3,3810e3]] 59 | 60 | # edges of inital seeding region 61 | seedx = np.array([100,200])*1e3 62 | seedy = np.array([100,1920])*1e3 63 | def u2mat(u): 64 | return u.reshape((param['ny'],param['nx']-1)) 65 | 66 | def v2mat(v): 67 | return v.reshape((param['ny']-1,param['nx'])) 68 | 69 | # padding with boundary conditions 70 | u,v = uv_pad(u,v) 71 | print('Padding boundary conditions: done.') 72 | 73 | # Advect the floats 74 | Xa = np.empty((ntime,N,R_chunk)).astype(np.float64) 75 | Ya = np.empty_like(Xa) 76 | 77 | # preallocate 78 | X = np.empty((ntime,N)).astype(np.float64) 79 | Y = np.empty_like(X).astype(np.float64) 80 | 81 | for r in range(R_chunk): 82 | print(r) 83 | 84 | # set initial conditions 85 | X[0,:] = np.random.rand(N)*np.diff(seedx) + seedx[0] 86 | Y[0,:] = np.random.rand(N)*np.diff(seedy) + seedy[0] 87 | 88 | # interpolation function 89 | Iu = RGI((x_u,y_u),u.T,bounds_error=False,fill_value=0) 90 | Iv = RGI((x_v,y_v),v.T,bounds_error=False,fill_value=0) 91 | 92 | for i in range(ntime-1): 93 | # Following the ideas of the Crank-Nicolson method 94 | # However, as the RHS is discrete, Euler forward is used to estimate 95 | # the RHS of the next time step 96 | 97 | # old RHS 98 | dXdt1 = Iu((X[i,:],Y[i,:])) 99 | dYdt1 = Iv((X[i,:],Y[i,:])) 100 | 101 | # new RHS 102 | dXdt2 = Iu((X[i,:] + dt*dXdt1,Y[i,:] + dt*dYdt1)) 103 | dYdt2 = Iv((X[i,:] + dt*dXdt1,Y[i,:] + dt*dYdt1)) 104 | 105 | # average of old and new RHS 106 | X[i+1,:] = X[i,:] + 0.5*dt*(dXdt1+dXdt2) 107 | Y[i+1,:] = Y[i,:] + 0.5*dt*(dYdt1+dYdt2) 108 | 109 | Xa[:,:,r] = X 110 | Ya[:,:,r] = Y 111 | 112 | print('Advecting floats done.') 113 | 114 | # free memory 115 | del u,v 116 | 117 | # histogram do not count the grid cell at the boundary 118 | Hi,xe,ye = np.histogram2d(Xa.flatten(),Ya.flatten(),bins=nbins,range=Hrange) 119 | H += Hi 120 | print('Histogram computed.') 121 | 122 | # free memory 123 | del Xa,Ya 124 | 125 | 126 | print(H.sum()) 127 | 128 | # mid points 129 | xm = xe[:-1] + (xe[1]-xe[0])/2. 130 | ym = ye[:-1] + (ye[1]-ye[0])/2. 131 | 132 | ## STORING 133 | dic = dict() 134 | all_var2export = ['X','Y','seedx','seedy','H','xe','ye','xm','ym'] 135 | 136 | for vars in all_var2export: 137 | exec('dic[vars] ='+vars) 138 | 139 | np.save(runpath+'/analysis/floats_meanflow.npy',dic) 140 | print('Everything stored.') 141 | -------------------------------------------------------------------------------- /plot/powermap_plot.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | path = '/network/home/aopp/kloewer/strix/' 4 | dpath = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 5 | outpath = '/network/home/aopp/kloewer/swm/paperplot/' 6 | 7 | import os; os.chdir(path) # change working directory 8 | import numpy as np 9 | from scipy import sparse 10 | import matplotlib.pyplot as plt 11 | import time as tictoc 12 | from netCDF4 import Dataset 13 | import glob 14 | from matplotlib.colors import BoundaryNorm,LogNorm 15 | import cmocean 16 | 17 | plt.rcParams['mathtext.fontset'] = 'cm' 18 | plt.rcParams['mathtext.rm'] = 'serif' 19 | 20 | # OPTIONS 21 | runfolder = [0,6] 22 | print('Plots for run ' + str(runfolder)) 23 | 24 | ## read data 25 | 26 | runpath1 = path+'run%04i' % runfolder[0] 27 | D1 = np.load(runpath1+'/analysis/power_map.npy').all() 28 | param1 = np.load(runpath1+'/param.npy').all() 29 | 30 | runpath2 = path+'run%04i' % runfolder[1] 31 | D2 = np.load(runpath2+'/analysis/power_map.npy').all() 32 | param2 = np.load(runpath2+'/param.npy').all() 33 | 34 | # functions 35 | def h2mat(h,param): 36 | return h.reshape((param['ny'],param['nx'])) 37 | 38 | def u2mat(u,param): 39 | return u.reshape((param['ny'],param['nx']-1)) 40 | 41 | def v2mat(v,param): 42 | return v.reshape((param['ny']-1,param['nx'])) 43 | 44 | def q2mat(q,param): 45 | return q.reshape((param['ny']+1,param['nx']+1)) 46 | ## 47 | 48 | m = [0]*6 49 | s = 1e3 50 | 51 | in1 = h2mat(D1['InPower_T'],param1)*s 52 | m[0] = in1.mean() 53 | in1 = np.sign(in1)*np.sqrt(abs(in1)) 54 | 55 | ex1 = h2mat(D1['ExPower_T'],param1)*s 56 | m[2] = ex1.mean() 57 | ex1 = np.sign(ex1)*np.sqrt(abs(ex1)) 58 | 59 | bf1 = h2mat(D1['BfricPower_T'],param1)*s 60 | m[1] = bf1.mean() 61 | bf1 = np.sign(bf1)*np.sqrt(abs(bf1)) 62 | 63 | in2 = h2mat(D2['InPower_T'],param2)*s 64 | m[3] = in2.mean() 65 | in2 = np.sign(in2)*np.sqrt(abs(in2)) 66 | 67 | ex2 = h2mat(D2['ExPower_T'],param2)*s 68 | m[5] = ex2.mean() 69 | ex2 = np.sign(ex2)*np.sqrt(abs(ex2)) 70 | 71 | bf2 = h2mat(D2['BfricPower_T'],param2)*s 72 | m[4] = bf2.mean() 73 | bf2 = np.sign(bf2)*np.sqrt(abs(bf2)) 74 | 75 | m = [np.round(mi,2) for mi in m] 76 | 77 | ## PLOTTING 78 | 79 | fig,axs = plt.subplots(2,3,figsize=(10,7),sharex=True,sharey=True) 80 | 81 | plt.tight_layout(rect=[0,.08,1,0.98]) 82 | fig.subplots_adjust(wspace=0.03,hspace=0.03) 83 | 84 | pos = axs[-1,0].get_position() 85 | pos2 = axs[-1,-1].get_position() 86 | cax = fig.add_axes([pos.x0,0.08,pos2.x1-pos.x0,0.02]) 87 | 88 | levs = np.linspace(-np.sqrt(90),np.sqrt(90),64) 89 | tik = np.array([-90,-60,-30,-10,-3,0,3,10,30,60,90]) 90 | tik = np.sign(tik)*np.sqrt(abs(tik)) 91 | 92 | q1 = axs[0,0].contourf(param1['x_T'],param1['y_T'],in1,levs,cmap=cmocean.cm.balance,extend='both') 93 | axs[0,2].contourf(param1['x_T'],param1['y_T'],ex1,levs,cmap=cmocean.cm.balance,extend='both') 94 | cbar = fig.colorbar(q1,cax=cax,orientation='horizontal',ticks=tik) 95 | cbar.set_label(r'Power [Wm$^{-2} \cdot 10^{-3}$]') 96 | cbar.set_ticklabels(np.round(tik**2*np.sign(tik)).astype(int)) 97 | 98 | 99 | axs[1,0].contourf(param2['x_T'],param2['y_T'],in2,levs,cmap=cmocean.cm.balance,extend='both') 100 | axs[1,2].contourf(param2['x_T'],param2['y_T'],ex2,levs,cmap=cmocean.cm.balance,extend='both') 101 | 102 | axs[0,1].contourf(param1['x_T'],param1['y_T'],bf1,levs,cmap=cmocean.cm.balance,extend='both') 103 | axs[1,1].contourf(param2['x_T'],param2['y_T'],bf2,levs,cmap=cmocean.cm.balance,extend='both') 104 | 105 | axs[0,0].set_title('Wind forcing power',loc='left') 106 | axs[0,2].set_title('Biharmonic viscosity power',loc='left') 107 | axs[0,1].set_title('Bottom friction power',loc='left') 108 | 109 | abc = 'abcdef' 110 | abci = 0 111 | for axcol in axs: 112 | for ax in axcol: 113 | plt.text(0.93,0.93,abc[abci],transform=ax.transAxes,fontweight='bold') 114 | plt.text(0.97,0.88,"%.2f" % m[abci],transform=ax.transAxes,ha='right') 115 | abci += 1 116 | 117 | axs[0,0].set_xticks([]) 118 | axs[0,0].set_yticks([]) 119 | 120 | axs[0,0].set_ylabel(r'Low resolution, $\Delta x = $30km') 121 | axs[1,0].set_ylabel(r'High resolution, $\Delta x = $7.5km') 122 | 123 | axs[-1,0].set_xlabel(r'$x$') 124 | axs[-1,1].set_xlabel(r'$x$') 125 | axs[-1,2].set_xlabel(r'$x$') 126 | 127 | axs[0,2].set_ylabel(r'$y$') 128 | axs[0,2].yaxis.set_label_position('right') 129 | 130 | axs[1,2].set_ylabel(r'$y$') 131 | axs[1,2].yaxis.set_label_position('right') 132 | 133 | plt.savefig(outpath+'plots/power_maps.png',dpi=150) 134 | plt.close(fig) 135 | -------------------------------------------------------------------------------- /plot/pv_gradient.py: -------------------------------------------------------------------------------- 1 | ## PLOT STREAMFUNCTION 2 | from __future__ import print_function 3 | #path = '/home/mkloewer/python/swm/' 4 | path = '/network/aopp/cirrus/pred/kloewer/swm_bf_cntrl/data/' 5 | path2 = '/home/kloewer/git/swm/' 6 | outpath = '/network/home/aopp/kloewer/swm/paperplot/' 7 | 8 | import numpy as np 9 | from scipy import sparse 10 | import matplotlib.pyplot as plt 11 | from cmocean import cm 12 | 13 | plt.rcParams['mathtext.fontset'] = 'cm' 14 | plt.rcParams['mathtext.rm'] = 'serif' 15 | 16 | 17 | # OPTIONS 18 | runfolder = [0,6,8] 19 | print('Compare mean plots from run ' + str(runfolder)) 20 | 21 | ## read data 22 | 23 | runpath1 = path+'run%04i' % runfolder[0] 24 | D1 = np.load(runpath1+'/analysis/mean_pv.npy').all() 25 | param1 = np.load(runpath1+'/param.npy').all() 26 | 27 | runpath2 = path+'run%04i' % runfolder[1] 28 | D2 = np.load(runpath2+'/analysis/mean_pv.npy').all() 29 | param2 = np.load(runpath2+'/param.npy').all() 30 | 31 | runpath3 = path+'run%04i' % runfolder[2] 32 | D3 = np.load(runpath3+'/analysis/mean_pv.npy').all() 33 | param3 = np.load(runpath3+'/param.npy').all() 34 | 35 | def q2mat(q,param): 36 | return q.reshape((param['ny']+1,param['nx']+1)) 37 | 38 | def u2mat(u,param): 39 | return u.reshape((param['ny'],param['nx']-1)) 40 | 41 | def v2mat(v,param): 42 | return v.reshape((param['ny']-1,param['nx'])) 43 | 44 | def fq(param): 45 | y_q = param['y_q'] 46 | Ly = param['Ly'] 47 | 48 | # subtract the regions mid-y so that phi_0 corresponds to a central latitude 49 | yy_q = np.array([y_q - Ly/2.]*(param['nx']+1)).T 50 | 51 | # globally available coriolis parameters (only f_q is actually needed though) 52 | f_q = param['f_0'] + param['beta']*yy_q.flatten() 53 | 54 | return f_q 55 | 56 | 57 | ## Plotting 58 | fig,axs = plt.subplots(2,3,sharex=True,sharey=True,figsize=(12,9)) 59 | fig.tight_layout(rect=[0.02,.15,1.,0.98]) 60 | fig.subplots_adjust(wspace=0.03,hspace=0.1) 61 | 62 | pos = axs[0,0].get_position() 63 | pos2 = axs[0,2].get_position() 64 | cax = fig.add_axes([pos.x0,0.12,pos2.x1-pos.x0,0.02]) 65 | cax2 = fig.add_axes([pos.x0,0.05,pos2.x1-pos.x0,0.02]) 66 | 67 | s = 1e3 # scaling factor m -> km 68 | n = 10 69 | 70 | levs = np.linspace(6e-8,2.2e-7,17) 71 | levs2 = np.linspace(-2e-8,2e-8,17) 72 | 73 | # PV mean 74 | q1 = axs[0,0].contourf(param1['x_q']/s,param1['y_q']/s,q2mat(D1['qm'],param1),levs,extend='both') 75 | axs[0,1].contourf(param3['x_q']/s,param3['y_q']/s,q2mat(D3['qm'],param3),levs,extend='both') 76 | axs[0,2].contourf(param2['x_q']/s,param2['y_q']/s,q2mat(D2['qm'],param2),levs,extend='both') 77 | 78 | q2 = axs[1,0].contourf(param1['x_q']/s,param1['y_q']/s,q2mat(D1['qm']-fq(param1)/param1['H'],param1),levs2,extend='both',cmap=cm.balance) 79 | axs[1,1].contourf(param3['x_q']/s,param3['y_q']/s,q2mat(D3['qm']-fq(param3)/param3['H'],param3),levs2,extend='both',cmap=cm.balance) 80 | axs[1,2].contourf(param2['x_q']/s,param2['y_q']/s,q2mat(D2['qm']-fq(param2)/param2['H'],param2),levs2,extend='both',cmap=cm.balance) 81 | 82 | # PV gradient 83 | #axs[1].quiver(param3['x_q'][::n]/s,param3['y_q'][::n]/s,v2mat(D3['dqm_dx'],param3)[::n,::n],u2mat(D3['dqm_dy'],param3)[::n,::n]) 84 | 85 | 86 | fig.colorbar(q1,cax=cax,orientation='horizontal') 87 | cbar = fig.colorbar(q2,cax=cax2,orientation='horizontal') 88 | cbar.set_label(r'Potential Vorticity [m$^{-1}$s$^{-1}$]') 89 | axs[0,0].set_xticks([0,1000,2000,3000]) 90 | axs[0,0].set_yticks([0,1000,2000,3000]) 91 | 92 | axs[0,0].set_xlim(0,param1['Lx']/s) 93 | axs[0,0].set_ylim(0,param1['Ly']/s) 94 | axs[0,0].set_ylabel(r'$y$ [km]') 95 | axs[1,0].set_ylabel(r'$y$ [km]') 96 | axs[1,0].set_xlabel(r'$x$ [km]') 97 | axs[1,1].set_xlabel(r'$x$ [km]')# 98 | axs[1,2].set_xlabel(r'$x$ [km]') 99 | 100 | axs[0,0].set_title(r'PV, $\Delta x = $30km, no-slip') 101 | axs[0,1].set_title(r'PV, $\Delta x = $15km, free-slip') 102 | axs[0,2].set_title(r'PV, $\Delta x = $7.5km, no-slip') 103 | 104 | axs[1,0].set_title(r'PV - f/H, $\Delta x = $30km, no-slip') 105 | axs[1,1].set_title(r'PV - f/H, $\Delta x = $15km, free-slip') 106 | axs[1,2].set_title(r'PV - f/H, $\Delta x = $7.5km, no-slip') 107 | 108 | axs[0,0].set_title('a',fontweight='bold',loc='left') 109 | axs[0,1].set_title('b',fontweight='bold',loc='left') 110 | axs[0,2].set_title('c',fontweight='bold',loc='left') 111 | 112 | axs[1,0].set_title('d',fontweight='bold',loc='left') 113 | axs[1,1].set_title('e',fontweight='bold',loc='left') 114 | axs[1,2].set_title('f',fontweight='bold',loc='left') 115 | 116 | plt.savefig(outpath+'plots/pv_gradient.pdf') 117 | plt.close(fig) 118 | -------------------------------------------------------------------------------- /plot/powermap_bs_crosssection.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | path = '/network/home/aopp/kloewer/strix/' 4 | dpath = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 5 | outpath = '/network/home/aopp/kloewer/swm/paperplot/' 6 | 7 | import os; os.chdir(path) # change working directory 8 | import numpy as np 9 | from scipy import sparse 10 | import matplotlib.pyplot as plt 11 | import time as tictoc 12 | from netCDF4 import Dataset 13 | import glob 14 | from matplotlib.colors import BoundaryNorm,LogNorm 15 | import cmocean 16 | 17 | plt.rcParams['mathtext.fontset'] = 'cm' 18 | plt.rcParams['mathtext.rm'] = 'serif' 19 | 20 | # OPTIONS 21 | runfolder = [0,6,2] 22 | print('Plots for run ' + str(runfolder)) 23 | 24 | ## read data 25 | 26 | runpath1 = path+'run%04i' % runfolder[0] 27 | D1 = np.load(runpath1+'/analysis/power_map.npy').all() 28 | param1 = np.load(runpath1+'/param.npy').all() 29 | 30 | runpath2 = path+'run%04i' % runfolder[1] 31 | D2 = np.load(runpath2+'/analysis/power_map.npy').all() 32 | param2 = np.load(runpath2+'/param.npy').all() 33 | 34 | runpath3 = dpath+'run%04i' % runfolder[2] 35 | D3 = np.load(runpath3+'/analysis/power_map.npy').all() 36 | param3 = np.load(runpath3+'/param.npy').all() 37 | print(param3['n_diss']) 38 | 39 | # functions 40 | def h2mat(h,param): 41 | return h.reshape((param['ny'],param['nx'])) 42 | 43 | def u2mat(u,param): 44 | return u.reshape((param['ny'],param['nx']-1)) 45 | 46 | def v2mat(v,param): 47 | return v.reshape((param['ny']-1,param['nx'])) 48 | 49 | def q2mat(q,param): 50 | return q.reshape((param['ny']+1,param['nx']+1)) 51 | ## 52 | 53 | m = [0]*(len(runfolder)*3) 54 | s = 1e3 55 | 56 | # LOW RESOLUTION RUN 57 | in1 = h2mat(D1['InPower_T'],param1)*s 58 | m[0] = in1.mean() 59 | in1 = np.sign(in1)*np.sqrt(abs(in1)) 60 | 61 | bf1 = h2mat(D1['BfricPower_T'],param1)*s 62 | m[1] = bf1.mean() 63 | bf1 = np.sign(bf1)*np.sqrt(abs(bf1)) 64 | 65 | ex1 = h2mat(D1['ExPower_T'],param1)*s 66 | m[2] = ex1.mean() 67 | #ex1 = np.sign(ex1)*np.sqrt(abs(ex1)) 68 | 69 | # BACKSCATTER RUN 70 | in3 = h2mat(D3['InPower_T'],param3)*s 71 | m[3] = in3.mean() 72 | in3 = np.sign(in3)*np.sqrt(abs(in3)) 73 | 74 | bf3 = h2mat(D3['BfricPower_T'],param3)*s 75 | m[4] = bf3.mean() 76 | bf3 = np.sign(bf3)*np.sqrt(abs(bf3)) 77 | 78 | D3['ExPower_T'] += D3['BackPower_T'] 79 | 80 | ex3 = h2mat(D3['ExPower_T'],param3)*s 81 | m[5] = ex3.mean() 82 | #ex3 = np.sign(ex3)*np.sqrt(abs(ex3)) 83 | 84 | # bs = h2mat(D3['BackPower_T'],param3)*s 85 | # m[6] = bs.mean() 86 | # bs = np.sign(bs)*np.sqrt(abs(bs)) 87 | 88 | # HIGH RESOLUTION RUN 89 | in2 = h2mat(D2['InPower_T'],param2)*s 90 | m[6] = in2.mean() 91 | in2 = np.sign(in2)*np.sqrt(abs(in2)) 92 | 93 | bf2 = h2mat(D2['BfricPower_T'],param2)*s 94 | m[7] = bf2.mean() 95 | bf2 = np.sign(bf2)*np.sqrt(abs(bf2)) 96 | 97 | ex2 = h2mat(D2['ExPower_T'],param2)*s 98 | m[8] = ex2.mean() 99 | #ex2 = np.sign(ex2)*np.sqrt(abs(ex2)) 100 | 101 | mround = [np.round(mi,2) for mi in m] 102 | 103 | ## PLOTTING 104 | 105 | fig,(ax,ax2) = plt.subplots(2,1) 106 | 107 | s1 = slice(32,96,1) # for low resolution from y/4 to 3y/4 108 | s2 = slice(128,384,1) # for high resolution 109 | 110 | ax.plot((param1['x_T']-param1['dx']/2.)/1e3,ex1[s1,:].mean(axis=0),'C0',drawstyle='steps-post') 111 | ax.plot((param2['x_T']-param2['dx']/2.)/1e3,ex2[s2,:].mean(axis=0),'C2',drawstyle='steps-post') 112 | ax.plot((param3['x_T']-param3['dx']/2.)/1e3,ex3[s1,:].mean(axis=0),'C3',drawstyle='steps-post') 113 | 114 | ax2.plot((param1['x_T']-param1['dx']/2.)/1e3,ex1[s1,:].mean(axis=0),'C0',label='Low resolution, $\Delta x = 30$km',drawstyle='steps-post') 115 | ax2.plot((param2['x_T']-param2['dx']/2.)/1e3,ex2[s2,:].mean(axis=0),'C2',label='High resolution, $\Delta x = 7.5$km',drawstyle='steps-post') 116 | ax2.plot((param3['x_T']-param3['dx']/2.)/1e3,ex3[s1,:].mean(axis=0),'C3',label='LR + moderate backscatter',drawstyle='steps-post') 117 | 118 | ax.set_ylim(-20,20) 119 | ax.set_xlim(0,param1['Lx']/1e3) 120 | 121 | #ax2.set_ylim(-20,20) 122 | ax2.set_xlim(0,param1['Lx']/1e3/6) 123 | 124 | 125 | ax.set_title(r'Biharm. viscosity + backscatter power, $y=\frac{L_y}{4} \colon \frac{3L_y}{4}$@average') 126 | ax2.set_title('Zoom in in $x$, zoom out in y-axis') 127 | ax.set_title('(a)',loc='left') 128 | ax2.set_title('(b)',loc='left') 129 | 130 | 131 | ax.set_ylabel(r'mW/m$^2$') 132 | ax2.set_ylabel(r'mW/m$^2$') 133 | ax.set_xlabel('$x$ [km]') 134 | ax2.set_xlabel('$x$ [km]') 135 | 136 | ax2.legend(loc=4) 137 | 138 | plt.tight_layout() 139 | plt.savefig(outpath+'plots/power_maps_bs_crosssection.png',dpi=150) 140 | plt.close(fig) 141 | -------------------------------------------------------------------------------- /calc/misc/c_diss_plot.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | path = '/home/mkloewer/python/swm/' 3 | import os; os.chdir(path) # change working directory 4 | import numpy as np 5 | from scipy import sparse 6 | import time as tictoc 7 | from netCDF4 import Dataset 8 | import glob 9 | import matplotlib.pyplot as plt 10 | 11 | # OPTIONS 12 | runfolder = [2,3] 13 | 14 | ## read data 15 | for r,i in zip(runfolder,range(len(runfolder))): 16 | runpath = path+'data/run%04i' % r 17 | 18 | if i == 0: 19 | u = np.load(runpath+'/u_sub.npy') 20 | v = np.load(runpath+'/v_sub.npy') 21 | h = np.load(runpath+'/h_sub.npy') 22 | time = np.load(runpath+'/t_sub.npy') 23 | print('run %i read.' % r) 24 | 25 | else: 26 | u = np.concatenate((u,np.load(runpath+'/u_sub.npy'))) 27 | v = np.concatenate((v,np.load(runpath+'/v_sub.npy'))) 28 | h = np.concatenate((h,np.load(runpath+'/h_sub.npy'))) 29 | time = np.hstack((time,np.load(runpath+'/t_sub.npy'))) 30 | print('run %i read.' % r) 31 | 32 | t = time / 3600. / 24. # in days 33 | ## read param 34 | global param 35 | param = np.load(runpath+'/param.npy').all() 36 | param['dat_type'] = np.float32 37 | 38 | # import functions 39 | exec(open(path+'swm_param.py').read()) 40 | exec(open(path+'swm_operators.py').read()) 41 | exec(open(path+'swm_output.py').read()) 42 | param['output'] = 0 43 | 44 | set_grad_mat() 45 | set_interp_mat() 46 | set_lapl_mat() 47 | set_coriolis() 48 | 49 | tlen = len(time) 50 | ## create ouputfolder 51 | try: 52 | os.mkdir(runpath+'/analysis') 53 | except: 54 | pass 55 | 56 | ## reshape u,v 57 | u = u.reshape((tlen,param['Nu'])).T 58 | v = v.reshape((tlen,param['Nv'])).T 59 | h = h.reshape((tlen,param['NT'])).T 60 | print('Reshape done.') 61 | 62 | ## 63 | dudx = Gux.dot(u) 64 | dudy = Guy.dot(u) 65 | dvdx = Gvx.dot(v) 66 | dvdy = Gvy.dot(v) 67 | 68 | n = 2 69 | 70 | D = np.sqrt((dudx - dvdy)**2 + IqT.dot((dudy + dvdx)**2)) 71 | Ro = (D.T/f_T) 72 | Rom = Ro.mean(axis=0) 73 | c = (1/(1+Ro)**n).mean(axis=0) 74 | 75 | # REYNOLDS, ROSSBY, EKMAN NUMBER MEAN 76 | u_T = IuT.dot(u) 77 | v_T = IvT.dot(v) 78 | print('u,v interpolation done.') 79 | 80 | #advective term 81 | adv_u = u_T*Gux.dot(u) + v_T*IqT.dot(Guy.dot(u)) 82 | adv_v = u_T*IqT.dot(Gvx.dot(v)) + v_T*Gvy.dot(v) 83 | del u_T,v_T 84 | adv_term = np.sqrt(adv_u**2 + adv_v**2) 85 | del adv_u, adv_v 86 | print('Advection term done.') 87 | 88 | #coriolis term 89 | cor_term = (f_T*np.sqrt(IuT.dot(u**2) + IvT.dot(v**2)).T).T 90 | print('Coriolis term done.') 91 | 92 | Ro2 = adv_term / cor_term 93 | c2 = (1/(1+Ro2)**n).mean(axis=1) 94 | Ro2m = Ro2.mean(axis=1) 95 | 96 | ## 97 | levs1 = np.linspace(0,.2,21) 98 | levs2 = np.linspace(0.5,1,21) 99 | 100 | fig,axs = plt.subplots(2,3,sharex=True,sharey=True,figsize=(9,5.5)) 101 | plt.tight_layout(rect=[-.02,-.03,1.12,.97],w_pad=0.1) 102 | 103 | axs[0,0].contourf(param['x_T'],param['y_T'],h2mat(Ro2m),levs1) 104 | axs[0,1].contourf(param['x_T'],param['y_T'],h2mat(Rom),levs1,extend='max') 105 | m1 = axs[0,2].contourf(param['x_T'],param['y_T'],h2mat(Ro[-1,:]),levs1,extend='max') 106 | plt.colorbar(m1,ax=(axs[0,0],axs[0,1],axs[0,2]),ticks=np.arange(0,.22,.04)) 107 | 108 | axs[1,0].contourf(param['x_T'],param['y_T'],h2mat(c2),levs2) 109 | m21 = axs[1,0].contour(param['x_T'],param['y_T'],h2mat(c2),[0.8],linewidths=0.7) 110 | axs[1,1].contourf(param['x_T'],param['y_T'],h2mat(c),levs2) 111 | m2 = axs[1,2].contourf(param['x_T'],param['y_T'],h2mat(1/(1+Ro[-1,:])**n),levs2,extend='min') 112 | axs[1,2].contour(param['x_T'],param['y_T'],h2mat(1/(1+Ro[-1,:])**n),[0.8],linewidths=0.7) 113 | m22 = axs[1,1].contour(param['x_T'],param['y_T'],h2mat(c),[0.8],linewidths=0.7) 114 | plt.colorbar(m2,ax=(axs[1,0],axs[1,1],axs[1,2]),ticks=np.arange(0.5,1.05,.05)) 115 | plt.clabel(m22, inline=1, fontsize=5,fmt='%.1f') 116 | plt.clabel(m21, inline=1, fontsize=5,fmt='%.1f') 117 | 118 | axs[0,0].set_xticks([]) 119 | axs[0,0].set_yticks([]) 120 | 121 | axs[0,0].set_title(r'$\overline{R_o} = \overline{\frac{|(\mathbf{u} \cdot \nabla)\mathbf{u}|}{|f\mathbf{u}|}}$') 122 | axs[0,1].set_title(r'$\overline{R_o^*} = \overline{\frac{|D|}{f}}$') 123 | axs[0,2].set_title(r'snapshot: $R_o^*$') 124 | 125 | axs[1,0].set_title(r'$(1+\overline{R_o})^{-2}$') 126 | axs[1,1].set_title(r'$(1+\overline{R_o}^*)^{-2}$') 127 | axs[1,2].set_title(r'$(1+R_o^*)^{-2}$') 128 | 129 | axs[0,0].set_ylabel('y') 130 | axs[1,0].set_ylabel('y') 131 | axs[1,0].set_xlabel('x') 132 | axs[1,1].set_xlabel('x') 133 | 134 | plt.savefig(path+'compare/Ro_scaling.png',dpi=150) 135 | plt.close(fig) 136 | #plt.show() 137 | 138 | 139 | -------------------------------------------------------------------------------- /plot/Ro_hist_plot_balu.py: -------------------------------------------------------------------------------- 1 | ## HISTOGRAM PLOTTING FOR REYNOLDS AND ROSSBY NUMBERS 2 | from __future__ import print_function 3 | 4 | path = '/network/home/aopp/kloewer/swm/paperplot/' 5 | path2 = '/network/aopp/cirrus/pred/kloewer/swm_bf_cntrl/' 6 | path3 = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | 10 | plt.rcParams['mathtext.fontset'] = 'cm' 11 | plt.rcParams['mathtext.rm'] = 'serif' 12 | 13 | # OPTIONS 14 | runfolder = [0,6,0,3,4] 15 | print('Creating Ro histogram plot from run '+str(runfolder)) 16 | 17 | ## read data 18 | runpath = path2+'data/run%04i' % runfolder[0] 19 | D1 = np.load(runpath+'/analysis/Ro_defo_hist.npy').all() 20 | 21 | runpath = path2+'data/run%04i' % runfolder[1] 22 | D2 = np.load(runpath+'/analysis/Ro_defo_hist.npy').all() 23 | 24 | runpath = path3+'run%04i' % runfolder[2] 25 | D3 = np.load(runpath+'/analysis/Ro_defo_hist.npy').all() 26 | print(np.load(runpath+'/param.npy').all()['n_diss']) 27 | 28 | runpath = path3+'run%04i' % runfolder[3] 29 | D4 = np.load(runpath+'/analysis/Ro_defo_hist.npy').all() 30 | print(np.load(runpath+'/param.npy').all()['n_diss']) 31 | 32 | runpath = path3+'run%04i' % runfolder[4] 33 | D5 = np.load(runpath+'/analysis/Ro_defo_hist.npy').all() 34 | print(np.load(runpath+'/param.npy').all()['n_diss']) 35 | 36 | ## EXTEND HISTOGRAM WITH ZERO TO THE RIGHT 37 | 38 | for D in [D1,D2,D3,D4,D5]: 39 | D['Ro_mid'] = np.hstack((D['Ro_mid'],10**1.5)) 40 | D['RoH'] = np.hstack((D['RoH'],0.)) 41 | 42 | ## CDISS 43 | Ro = np.linspace(10**-3.5,10**1.5,10000) 44 | cd = lambda d: 1/(1+(Ro/d)) 45 | cd2 = lambda d: (1 - np.minimum(np.exp(Ro - d),np.ones_like(Ro)))/(1-np.exp(-d)) 46 | 47 | ## PLOT 48 | fig,(ax1,ax2,ax3) = plt.subplots(3,1,figsize=(8,6.5),sharex=True) 49 | 50 | s = 1e6 51 | 52 | ax1.plot(D1['Ro_mid'],D1['RoH']/s,'C0',label=r'Low resolution, $\Delta x = $30km',lw=3) 53 | ax1.plot(D2['Ro_mid'],D2['RoH']/16/s,'C2',label=r'High resolution, $\Delta x = $7.5km',lw=3) 54 | ax1.plot(D3['Ro_mid'],D3['RoH']/s,'C1',label=r'LR + weak backscatter',ls='--') 55 | ax1.plot(D4['Ro_mid'],D4['RoH']/s,'C3',label=r'LR + moderate backscatter',ls='--') 56 | ax1.plot(D5['Ro_mid'],D5['RoH']/s,'C5',label=r'LR + strong backscatter',ls='--') 57 | 58 | ytikmax = 0.25 59 | 60 | ax1.axvline(np.log10(D1['Ro_mean']),0,ytikmax,c='C0',ls='-',lw=2) 61 | ax1.axvline(np.log10(D2['Ro_mean']),0,ytikmax,c='C2',ls='-',lw=2) 62 | ax1.axvline(np.log10(D3['Ro_mean']),0,ytikmax,c='C1',ls='--') 63 | ax1.axvline(np.log10(D4['Ro_mean']),0,ytikmax,c='C3',ls='--') 64 | ax1.axvline(np.log10(D5['Ro_mean']),0,ytikmax,c='C5',ls='--') 65 | 66 | ax1.text(np.log10(D1['Ro_mean'])-0.01,1.3,'mean($R_o$)',rotation=90,ha='right',color='k') 67 | 68 | ax2.plot(np.log10(Ro),cd(1.),'C1--',label=r'$c_{diss}$ for $R_{diss} = 1$, weak backscatter') 69 | ax2.plot(np.log10(Ro),cd(8.),'C3--',label=r'$c_{diss}$ for $R_{diss} = 8$, moderate backscatter') 70 | ax2.plot(np.log10(Ro),cd(64.),'C5--',label=r'$c_{diss}$ for $R_{diss} = 64$, strong backscatter') 71 | 72 | ax3.plot(np.log10(Ro),cd(1.),'C1--',label='as in b') 73 | ax3.plot(np.log10(Ro),cd(8.),'C3--',label='as in b') 74 | ax3.plot(np.log10(Ro),cd(64.),'C5--',label='as in b') 75 | 76 | ax3.plot(np.log10(Ro),cd2(1.),'C0',label='$c_{diss}^*$ for $R_{diss} = 1$') 77 | ax3.plot(np.log10(Ro),cd2(8.),'C4',label='$c_{diss}^*$ for $R_{diss} = 8$') 78 | ax3.plot(np.log10(Ro),cd2(64),'C2',label='$c_{diss}^*$ for $R_{diss} = 64$') 79 | 80 | ax2.plot(np.ones(2)*np.log10(1),[-1,0.5],'C1') 81 | ax2.plot(np.ones(2)*np.log10(8),[-1,0.5],'C3') 82 | ax2.text(np.log10(1)-0.03,0.3,r'$R_{diss} = 1$',rotation=90,ha='right',color='k') 83 | ax2.text(np.log10(8)-0.03,0.3,r'$R_{diss} = 8$',rotation=90,ha='right',color='k') 84 | ax2.text(-2.9,0.6,r'$c_{diss} = (1 + \frac{R_o}{R_{diss}})^{-1}$', fontsize=15) 85 | ax3.text(-2.9,0.6,r'$c_{diss}^* \sim 1 - \exp(R_o - R_{diss})$', fontsize=15) 86 | 87 | ax3.legend(loc=3,ncol=2) 88 | ax2.legend(loc=3) 89 | ax1.legend(loc=1) 90 | 91 | ax1.set_xlim(-3,1) 92 | ax1.set_ylim(-0.1,3.5) 93 | ax2.set_ylim(-0.05,1.05) 94 | ax3.set_ylim(-0.05,1.05) 95 | 96 | ax1.set_title('a',loc='left',fontweight='bold') 97 | ax1.set_title('Rossby number histogram') 98 | 99 | ax2.set_title('b',loc='left',fontweight='bold') 100 | ax2.set_title('Rossby number dissipation scaling') 101 | 102 | ax3.set_title('c',loc='left',fontweight='bold') 103 | ax3.set_title('Rossby number dissipation scaling, exponential version') 104 | 105 | ax3.set_xlabel('log$_{10}(R_o)$') 106 | ax1.set_ylabel(r'$N$ $[10^6]$') 107 | 108 | plt.tight_layout() 109 | plt.savefig(path+'plots/Ro_hist_nadiga.pdf') 110 | plt.close(fig) -------------------------------------------------------------------------------- /calc/power_inout_bs_calc.py: -------------------------------------------------------------------------------- 1 | ## POWER INPUT EXIT CALCULATION 2 | from __future__ import print_function 3 | 4 | # path 5 | import os 6 | path = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 7 | os.chdir(path) # change working directory 8 | 9 | import numpy as np 10 | from scipy import sparse 11 | 12 | # OPTIONS 13 | # several entries in the list concatenates the runs and stores the result in the last folder 14 | runfolder = [4] 15 | print('Calculating power in/out from run ' + str(runfolder)) 16 | 17 | InPower_T = [] 18 | ExPower_T = [] 19 | BfricPower_T = [] 20 | BackPower_T = [] 21 | 22 | ## read data 23 | for r in runfolder: # calculate each run separately 24 | runpath = path+'run%04i' % r 25 | 26 | skip = 5*365 27 | u = np.load(runpath+'/u_sub.npy')[skip:,...] 28 | v = np.load(runpath+'/v_sub.npy')[skip:,...] 29 | eta = np.load(runpath+'/eta_sub.npy')[skip:,...] 30 | e = np.load(runpath+'/e_sub.npy')[skip:,...] 31 | t = np.load(runpath+'/t_sub.npy')[skip:,...] 32 | print('run %i read.' % r) 33 | 34 | ## read param 35 | global param 36 | param = np.load(runpath+'/param.npy').all() 37 | 38 | # import functions 39 | funpath = '/network/home/aopp/kloewer/git/swm/' 40 | exec(open(funpath+'swm_param.py').read()) 41 | exec(open(funpath+'swm_operators.py').read()) 42 | 43 | set_grad_mat() 44 | set_interp_mat() 45 | set_coriolis() 46 | set_forcing() 47 | 48 | tlen = len(t) 49 | ## create ouputfolder 50 | try: 51 | os.mkdir(runpath+'/analysis') 52 | except: 53 | pass 54 | 55 | ## reshape u,v 56 | u = u.reshape((tlen,param['Nu'])).T 57 | v = v.reshape((tlen,param['Nv'])).T 58 | h = eta.reshape((tlen,param['NT'])).T + param['H'] 59 | e = e.reshape((tlen,param['NT'])).T 60 | print('Reshape done.') 61 | 62 | h_q = ITq.dot(h) 63 | h_u = ITu.dot(h) 64 | h_v = ITv.dot(h) 65 | print('h_u, h_v, h_q done.') 66 | 67 | ## input 68 | # Fx is actually Fx/rho 69 | InPower = param['rho']*(u.T*Fx).mean(axis=0) 70 | print('Input Power done.') 71 | 72 | # Shchepetkin and O'Brien divergence of a tensor formulation 73 | hS = ((Gux.dot(u)-Gvy.dot(v))*h,(G2vx.dot(v) + G2uy.dot(u))*h_q) 74 | diff_u = (GTx.dot(hS[0]) + Gqy.dot(hS[1])) / h_u 75 | diff_v = (Gqx.dot(hS[1]) - GTy.dot(hS[0])) / h_v 76 | 77 | # hS will be used for the backscatter term further down 78 | 79 | # biharmonic stress tensor R = (R11, R12, R12, -R11), store only R11, R12 80 | hR = ((Gux.dot(diff_u) - Gvy.dot(diff_v))*h, (G2vx.dot(diff_v) + G2uy.dot(diff_u))*h_q) 81 | 82 | 83 | del h_q, diff_u, diff_v 84 | 85 | # without the 1/h factor compared to the calculation in the rhs 86 | bidiff_u = (GTx.dot(hR[0]) + Gqy.dot(hR[1])) 87 | bidiff_v = (Gqx.dot(hR[1]) - GTy.dot(hR[0])) 88 | 89 | del hR 90 | 91 | ExPower_u = -param['nu_B']*param['rho']*(u*bidiff_u).mean(axis=1) 92 | ExPower_v = -param['nu_B']*param['rho']*(v*bidiff_v).mean(axis=1) 93 | 94 | del bidiff_u, bidiff_v 95 | 96 | print('Biharmonic dissipation term done.') 97 | 98 | BfricPower = -param['rho']*param['c_D']*((IuT.dot(u**2) + IvT.dot(v**2))**(3./2.)).mean(axis=1) 99 | 100 | print('Bottom friction dissipation term done.') 101 | 102 | # Backscatter term 103 | e_over_h = e/h 104 | nu_back = -param['c_back']*param['max_dxdy']*np.sqrt(2*e_over_h.clip(0,e_over_h.max())) 105 | del e_over_h, h, e 106 | 107 | nu_back_hS0 = nu_back*hS[0] 108 | nu_back_hS1 = ITq.dot(nu_back)*hS[1] 109 | 110 | del nu_back, hS 111 | 112 | # without the 1/h factor compared to the calculation in the rhs 113 | back_diff_u = (GTx.dot(nu_back_hS0) + Gqy.dot(nu_back_hS1)) 114 | back_diff_v = (Gqx.dot(nu_back_hS1) - GTy.dot(nu_back_hS0)) 115 | 116 | del nu_back_hS0, nu_back_hS1, h_u, h_v 117 | 118 | BackPower_u = param['rho']*(u*back_diff_u).mean(axis=1) 119 | BackPower_v = param['rho']*(v*back_diff_v).mean(axis=1) 120 | 121 | del back_diff_u, back_diff_v 122 | 123 | print('Backscatter term done.') 124 | 125 | # Interpolation 126 | InPower_T.append(IuT.dot(InPower)) 127 | ExPower_T.append(IuT.dot(ExPower_u) + IvT.dot(ExPower_v)) 128 | BfricPower_T.append(BfricPower) 129 | BackPower_T.append(IuT.dot(BackPower_u) + IvT.dot(BackPower_v)) 130 | 131 | # Averaging over runs 132 | InPower_T = np.array(InPower_T).mean(axis=0) 133 | ExPower_T = np.array(ExPower_T).mean(axis=0) 134 | BfricPower_T = np.array(BfricPower_T).mean(axis=0) 135 | BackPower_T = np.array(BackPower_T).mean(axis=0) 136 | 137 | ## STORING 138 | dic = dict() 139 | all_var2export = ['InPower_T','ExPower_T','BfricPower_T','BackPower_T'] 140 | for v in all_var2export: 141 | exec('dic[v] ='+v) 142 | 143 | np.save(runpath+'/analysis/power_map.npy',dic) 144 | print('Everything stored.') 145 | -------------------------------------------------------------------------------- /calc/misc/Re_hist_calc_bs.py: -------------------------------------------------------------------------------- 1 | ## HISTOGRAM COMPUTATIONS FOR REYNOLDS AND ROSSBY NUMBERS 2 | from __future__ import print_function 3 | 4 | # path 5 | import os 6 | path = os.path.dirname(os.getcwd()) + '/' # on level above 7 | os.chdir(path) # change working directory 8 | 9 | import numpy as np 10 | from scipy import sparse 11 | 12 | # OPTIONS 13 | runfolder = [10] 14 | print('Calculating Reynolds histograms from run ' + str(runfolder)) 15 | 16 | ReH = [] 17 | Re_mean = [] 18 | Re_median = [] 19 | 20 | ## read data - calculate each run separately 21 | for r,i in zip(runfolder,range(len(runfolder))): 22 | runpath = path+'data/run%04i' % r 23 | 24 | skip = 5*365 25 | u = np.load(runpath+'/u_sub.npy')[skip:,...] 26 | v = np.load(runpath+'/v_sub.npy')[skip:,...] 27 | eta = np.load(runpath+'/eta_sub.npy')[skip:,...] 28 | e = np.load(runpath+'/e_sub.npy')[skip:,...] 29 | t = np.load(runpath+'/t_sub.npy')[skip:,...] 30 | print('run %i read.' % r) 31 | 32 | ## read param 33 | global param 34 | param = np.load(runpath+'/param.npy').all() 35 | 36 | # import functions 37 | exec(open(path+'swm_param.py').read()) 38 | exec(open(path+'swm_operators.py').read()) 39 | 40 | set_grad_mat() 41 | set_interp_mat() 42 | set_coriolis() 43 | 44 | tlen = len(t) 45 | ## create ouputfolder 46 | try: 47 | os.mkdir(runpath+'/analysis') 48 | except: 49 | pass 50 | 51 | ## reshape u,v 52 | u = u.reshape((tlen,param['Nu'])).T 53 | v = v.reshape((tlen,param['Nv'])).T 54 | h = eta.reshape((tlen,param['NT'])).T + param['H'] 55 | e = e.reshape((tlen,param['NT'])).T 56 | print('Reshape done.') 57 | 58 | ## COMPUTE REYNOLDS, ROSSBY 59 | u_T = IuT.dot(u) 60 | v_T = IvT.dot(v) 61 | print('u,v interpolation done.') 62 | 63 | #advective term 64 | adv_u = u_T*Gux.dot(u) + v_T*IqT.dot(Guy.dot(u)) 65 | adv_v = u_T*IqT.dot(Gvx.dot(v)) + v_T*Gvy.dot(v) 66 | del u_T,v_T 67 | adv_term = np.sqrt(adv_u**2 + adv_v**2) 68 | del adv_u, adv_v 69 | print('Advection term done.') 70 | 71 | #diffusive term 72 | S = (Gux.dot(u)-Gvy.dot(v),G2vx.dot(v) + G2uy.dot(u)) 73 | del u,v 74 | hS = (h*S[0],ITq.dot(h)*S[1]) 75 | del S 76 | print('Stress tensor S done.') 77 | 78 | diff_u = (GTx.dot(hS[0]) + Gqy.dot(hS[1])) / ITu.dot(h) 79 | diff_v = (Gqx.dot(hS[1]) - GTy.dot(hS[0])) / ITv.dot(h) 80 | print('Harmonic part done.') 81 | 82 | # biharmonic stress tensor R = (R11, R12, R12, -R11), store only R11, R12 83 | R = (Gux.dot(diff_u) - Gvy.dot(diff_v), G2vx.dot(diff_v) + G2uy.dot(diff_u)) 84 | del diff_u, diff_v 85 | nuhR = (param['nu_B']*h*R[0],param['nu_B']*ITq.dot(h)*R[1]) 86 | del R 87 | print('Stress tensor R done.') 88 | 89 | bidiff_u = (GTx.dot(nuhR[0]) + Gqy.dot(nuhR[1])) / ITu.dot(h) 90 | bidiff_v = (Gqx.dot(nuhR[1]) - GTy.dot(nuhR[0])) / ITv.dot(h) 91 | 92 | del nuhR 93 | print('Biharmonic part done.') 94 | 95 | # backscatter 96 | e_over_h = e/h 97 | nu_back = -param['c_back']*param['max_dxdy']*np.sqrt(2*e_over_h.clip(0,e_over_h.max())) 98 | del e_over_h,e 99 | 100 | nu_back_hS0 = nu_back*hS[0] 101 | nu_back_hS1 = ITq.dot(nu_back)*hS[1] 102 | print('nu_back calculated.') 103 | del nu_back 104 | 105 | back_diff_u = (GTx.dot(nu_back_hS0) + Gqy.dot(nu_back_hS1)) / ITu.dot(h) 106 | back_diff_v = (Gqx.dot(nu_back_hS1) - GTy.dot(nu_back_hS0)) / ITv.dot(h) 107 | del nu_back_hS0,nu_back_hS1 108 | 109 | diff_term = np.sqrt(IuT.dot((-bidiff_u + back_diff_u)**2) + IvT.dot((-bidiff_v + back_diff_v)**2)) 110 | #diff_term = np.sqrt(IuT.dot(bidiff_u**2) + IvT.dot(bidiff_v**2)) 111 | print('Diff term done.') 112 | del bidiff_u,bidiff_v,back_diff_u,back_diff_v 113 | 114 | # actual number 115 | Re = (adv_term / diff_term).flatten() 116 | print('Re computed.') 117 | del adv_term, diff_term 118 | 119 | Re_mean.append(Re.mean()) 120 | Re_median.append(np.median(Re)) 121 | Re = np.log10(Re) 122 | 123 | # histogram 124 | Re_min = -3. # in log scale 125 | Re_max = 5. 126 | N = 300 127 | 128 | ReH_temp,Re_edges = np.histogram(Re,np.linspace(Re_min,Re_max,N)) 129 | print('Re histogram done.') 130 | del Re 131 | 132 | # store each run in a list 133 | ReH.append(ReH_temp) 134 | 135 | Re_mid = Re_edges[:-1] + np.diff(Re_edges)/2. 136 | 137 | 138 | ReH = np.array(ReH).sum(axis=0) 139 | Re_mean = np.array(Re_mean).mean() 140 | Re_median = np.median(np.array(Re_median)) #actually median of medians though... 141 | 142 | ## STORING in last 143 | dic = dict() 144 | all_var2export = ['ReH','Re_mid','Re_edges','Re_mean','Re_median'] 145 | 146 | for vars in all_var2export: 147 | exec('dic[vars] ='+vars) 148 | 149 | np.save(runpath+'/analysis/Re_hist.npy',dic) 150 | -------------------------------------------------------------------------------- /calc/misc/Re_hist_calc_bs_old.py: -------------------------------------------------------------------------------- 1 | ## HISTOGRAM COMPUTATIONS FOR REYNOLDS AND ROSSBY NUMBERS 2 | from __future__ import print_function 3 | 4 | # path 5 | import os 6 | path = '/home/mkloewer/python/swm/' 7 | #path = os.path.dirname(os.getcwd()) + '/' # on level above 8 | os.chdir(path) # change working directory 9 | import time as tictoc 10 | 11 | import numpy as np 12 | from scipy import sparse 13 | 14 | # OPTIONS 15 | runfolder = [14] 16 | print('Calculating Reynolds histograms from run ' + str(runfolder)) 17 | 18 | ReH = [] 19 | Re_mean = [] 20 | Re_median = [] 21 | 22 | ## read data - calculate each run separately 23 | for r,i in zip(runfolder,range(len(runfolder))): 24 | runpath = path+'stoch/data/run%04i' % r 25 | 26 | skip = 5*365 27 | u = np.load(runpath+'/u_sub.npy')[skip:,...] 28 | v = np.load(runpath+'/v_sub.npy')[skip:,...] 29 | eta = np.load(runpath+'/h_sub.npy')[skip:,...] 30 | e = np.load(runpath+'/e_sub.npy')[skip:,...] 31 | t = np.load(runpath+'/t_sub.npy')[skip:,...] 32 | print('run %i read.' % r) 33 | 34 | ## read param 35 | global param 36 | param = np.load(runpath+'/param.npy').all() 37 | 38 | # import functions 39 | exec(open(path+'swm_param.py').read()) 40 | exec(open(path+'swm_operators.py').read()) 41 | param['output'] = 0 42 | 43 | set_grad_mat() 44 | set_interp_mat() 45 | set_coriolis() 46 | 47 | tlen = len(t) 48 | ## create ouputfolder 49 | try: 50 | os.mkdir(runpath+'/analysis') 51 | except: 52 | pass 53 | 54 | ## reshape u,v 55 | u = u.reshape((tlen,param['Nu'])).T 56 | v = v.reshape((tlen,param['Nv'])).T 57 | h = eta.reshape((tlen,param['NT'])).T + param['H'] 58 | e = e.reshape((tlen,param['NT'])).T 59 | print('Reshape done.') 60 | 61 | ## COMPUTE REYNOLDS, ROSSBY 62 | u_T = IuT.dot(u) 63 | v_T = IvT.dot(v) 64 | print('u,v interpolation done.') 65 | 66 | #advective term 67 | adv_u = u_T*Gux.dot(u) + v_T*IqT.dot(Guy.dot(u)) 68 | adv_v = u_T*IqT.dot(Gvx.dot(v)) + v_T*Gvy.dot(v) 69 | del u_T,v_T 70 | adv_term = np.sqrt(adv_u**2 + adv_v**2) 71 | del adv_u, adv_v 72 | print('Advection term done.') 73 | 74 | #diffusive term 75 | S = (Gux.dot(u)-Gvy.dot(v),G2vx.dot(v) + G2uy.dot(u)) 76 | del u,v 77 | hS = (h*S[0],ITq.dot(h)*S[1]) 78 | del S 79 | print('Stress tensor S done.') 80 | 81 | diff_u = (GTx.dot(hS[0]) + Gqy.dot(hS[1])) / ITu.dot(h) 82 | diff_v = (Gqx.dot(hS[1]) - GTy.dot(hS[0])) / ITv.dot(h) 83 | print('Harmonic part done.') 84 | 85 | # biharmonic stress tensor R = (R11, R12, R12, -R11), store only R11, R12 86 | R = (Gux.dot(diff_u) - Gvy.dot(diff_v), G2vx.dot(diff_v) + G2uy.dot(diff_u)) 87 | del diff_u, diff_v 88 | nuhR = (param['nu_B']*h*R[0],param['nu_B']*ITq.dot(h)*R[1]) 89 | del R 90 | print('Stress tensor R done.') 91 | 92 | bidiff_u = (GTx.dot(nuhR[0]) + Gqy.dot(nuhR[1])) / ITu.dot(h) 93 | bidiff_v = (Gqx.dot(nuhR[1]) - GTy.dot(nuhR[0])) / ITv.dot(h) 94 | 95 | del nuhR 96 | print('Biharmonic part done.') 97 | 98 | # backscatter 99 | nu_back = -param['c_back']*param['max_dxdy']*np.sqrt(2*e.clip(0,e.max())) 100 | del e 101 | 102 | nu_back_hS0 = nu_back*hS[0] 103 | nu_back_hS1 = ITq.dot(nu_back)*hS[1] 104 | print('nu_back calculated.') 105 | del nu_back 106 | 107 | back_diff_u = (GTx.dot(nu_back_hS0) + Gqy.dot(nu_back_hS1)) / ITu.dot(h) 108 | back_diff_v = (Gqx.dot(nu_back_hS1) - GTy.dot(nu_back_hS0)) / ITv.dot(h) 109 | del nu_back_hS0,nu_back_hS1 110 | 111 | diff_term = np.sqrt(IuT.dot((bidiff_u + back_diff_u)**2) + IvT.dot((bidiff_v + back_diff_v)**2)) 112 | #diff_term = np.sqrt(IuT.dot(bidiff_u**2) + IvT.dot(bidiff_v**2)) 113 | print('Diff term done.') 114 | del bidiff_u,bidiff_v,back_diff_u,back_diff_v 115 | 116 | # actual number 117 | Re = (adv_term / diff_term).flatten() 118 | print('Re computed.') 119 | del adv_term, diff_term 120 | 121 | Re_mean.append(Re.mean()) 122 | Re_median.append(np.median(Re)) 123 | Re = np.log10(Re) 124 | 125 | # histogram 126 | Re_min = -3. # in log scale 127 | Re_max = 5. 128 | N = 300 129 | 130 | ReH_temp,Re_edges = np.histogram(Re,np.linspace(Re_min,Re_max,N)) 131 | print('Re histogram done.') 132 | del Re 133 | 134 | # store each run in a list 135 | ReH.append(ReH_temp) 136 | 137 | Re_mid = Re_edges[:-1] + np.diff(Re_edges)/2. 138 | 139 | 140 | ReH = np.array(ReH).sum(axis=0) 141 | Re_mean = np.array(Re_mean).mean() 142 | Re_median = np.median(np.array(Re_median)) #actually median of medians though... 143 | 144 | ## STORING in last 145 | dic = dict() 146 | all_var2export = ['ReH','Re_mid','Re_edges','Re_mean','Re_median'] 147 | 148 | for vars in all_var2export: 149 | exec('dic[vars] ='+vars) 150 | 151 | np.save(runpath+'/analysis/Re_hist.npy',dic) 152 | -------------------------------------------------------------------------------- /plot/streamplot.py: -------------------------------------------------------------------------------- 1 | ## PLOT STREAMFUNCTION 2 | from __future__ import print_function 3 | #path = '/home/mkloewer/python/swm/' 4 | path = '/network/aopp/cirrus/pred/kloewer/swm_bf_cntrl/data/' 5 | path2 = '/home/kloewer/git/swm/' 6 | path3 = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 7 | outpath = '/network/home/aopp/kloewer/swm/paperplot/' 8 | 9 | import numpy as np 10 | from scipy import sparse 11 | import matplotlib.pyplot as plt 12 | from cmocean import cm 13 | 14 | plt.rcParams['mathtext.fontset'] = 'cm' 15 | plt.rcParams['mathtext.rm'] = 'serif' 16 | 17 | 18 | # OPTIONS 19 | runfolder = [0,6,3] 20 | print('Compare mean plots from run ' + str(runfolder)) 21 | 22 | ## read data 23 | 24 | runpath1 = path+'run%04i' % runfolder[0] 25 | D1 = np.load(runpath1+'/analysis/mean.npy').all() 26 | param1 = np.load(runpath1+'/param.npy').all() 27 | 28 | runpath2 = path+'run%04i' % runfolder[1] 29 | D2 = np.load(runpath2+'/analysis/mean.npy').all() 30 | param2 = np.load(runpath2+'/param.npy').all() 31 | 32 | runpath3 = path3+'run%04i' % runfolder[2] 33 | D3 = np.load(runpath3+'/analysis/mean.npy').all() 34 | param3 = np.load(runpath3+'/param.npy').all() 35 | print(param3['n_diss']) 36 | 37 | ## CALCULATE 38 | u = [0]*3 39 | v = [0]*3 40 | speed = [0]*3 41 | xx = [0]*3 42 | yy = [0]*3 43 | 44 | 45 | global param 46 | param = np.load(runpath1+'/param.npy').all() 47 | exec(open(path2+'swm_operators.py').read()) 48 | exec(open(path2+'swm_output.py').read()) 49 | param['output'] = 0 50 | set_grad_mat() 51 | set_interp_mat() 52 | 53 | u[0] = h2mat(IuT.dot(D1['um'])) 54 | v[0] = h2mat(IvT.dot(D1['vm'])) 55 | speed[0] = np.sqrt(u[0]**2 + v[0]**2) 56 | xx[0],yy[0] = np.meshgrid(param['x_T'],param['y_T']) 57 | 58 | # next run 59 | param = np.load(runpath2+'/param.npy').all() 60 | exec(open(path2+'swm_operators.py').read()) 61 | exec(open(path2+'swm_output.py').read()) 62 | param['output'] = 0 63 | set_grad_mat() 64 | set_interp_mat() 65 | 66 | u[1] = h2mat(IuT.dot(D2['um'])) 67 | v[1] = h2mat(IvT.dot(D2['vm'])) 68 | speed[1] = np.sqrt(u[1]**2 + v[1]**2) 69 | 70 | xx[1],yy[1] = np.meshgrid(param['x_T'],param['y_T']) 71 | 72 | # next run 73 | param = np.load(runpath3+'/param.npy').all() 74 | exec(open(path2+'swm_operators.py').read()) 75 | exec(open(path2+'swm_output.py').read()) 76 | param['output'] = 0 77 | set_grad_mat() 78 | set_interp_mat() 79 | 80 | u[2] = h2mat(IuT.dot(D3['um'])) 81 | v[2] = h2mat(IvT.dot(D3['vm'])) 82 | speed[2] = np.sqrt(u[2]**2 + v[2]**2) 83 | 84 | xx[2],yy[2] = np.meshgrid(param['x_T'],param['y_T']) 85 | 86 | # line width 87 | lww = [4*np.sqrt(speed[0])/np.sqrt(speed[0].max())] 88 | lww.append(4*np.sqrt(speed[1])/np.sqrt(speed[0].max())) 89 | lww.append(4*np.sqrt(speed[2])/np.sqrt(speed[0].max())) 90 | 91 | # wind profile 92 | Fx = param['Fx0']*(np.cos(2*np.pi*(param['y_u']-param['Ly']/2)/param['Ly']) + 2*np.sin(np.pi*(param['y_u'] - param['Ly']/2)/param['Ly'])) 93 | 94 | ## Plotting 95 | fig,axs = plt.subplots(1,3,sharex=True,sharey=True,figsize=(12,5)) 96 | fig.tight_layout(rect=[0.02,.15,0.9,0.92]) 97 | fig.subplots_adjust(wspace=0.03,hspace=0.03) 98 | 99 | pos = axs[0].get_position() 100 | pos2 = axs[2].get_position() 101 | cax = fig.add_axes([pos.x0,0.1,pos2.x1-pos.x0,0.03]) 102 | 103 | s = 1e3 # scaling factor m -> km 104 | 105 | # wind profile 106 | wax = fig.add_axes([0.888,pos.y0,0.1,pos.y1-pos.y0]) 107 | wax.set_ylim(0,param['Ly']/s) 108 | wax.set_yticks([0,1000,2000,3000]) 109 | wax.set_yticklabels([]) 110 | wax.plot(Fx,param['y_u']/s) 111 | wax.plot([0,0],[0,param['Ly']/s],'grey',lw=0.5) 112 | #wax.set_title('d',fontweight='bold',loc='left') 113 | wax.set_title(r'Wind stress $\tau$',loc='left') 114 | 115 | 116 | wax.set_xlabel('[Pa]') 117 | wax.set_xticks([-0.3,0,0.2]) 118 | wax.set_xticklabels([-0.3,0,0.2]) 119 | 120 | #plt.text(0, 1.1,r'Wind stress $\tau$',fontsize=13,ha='left',transform=wax.transAxes) 121 | 122 | for j,i in zip([0,2,1],range(3)): 123 | strm = axs[j].streamplot(xx[i]/s,yy[i]/s,u[i],v[i],color=speed[i],density=2.5,linewidth=lww[i],arrowstyle='->') 124 | 125 | cbar = fig.colorbar(strm.lines,cax=cax,orientation='horizontal') 126 | cbar.set_label('Speed [m/s]') 127 | axs[0].set_xticks([0,1000,2000,3000]) 128 | axs[0].set_yticks([0,1000,2000,3000]) 129 | 130 | axs[0].set_xlim(0,param['Lx']/s) 131 | axs[0].set_ylim(0,param['Ly']/s) 132 | axs[0].set_ylabel(r'$y$ [km]') 133 | axs[1].set_xlabel(r'$x$ [km]') 134 | 135 | axs[0].set_title(r'Low resolution, $\Delta x = $30km') 136 | axs[1].set_title(r'LR + moderate backscatter') 137 | axs[2].set_title(r'High resolution, $\Delta x = $7.5km') 138 | 139 | axs[0].set_title('a',fontweight='bold',loc='left') 140 | axs[1].set_title('b',fontweight='bold',loc='left') 141 | axs[2].set_title('c',fontweight='bold',loc='left') 142 | 143 | #plt.suptitle('Streamlines of mean circulation ($\overline{u},\overline{v}$)',x=0.186,y=0.98) 144 | 145 | #plt.text(0,1.1,'Streamlines of mean circulation ($\overline{u},\overline{v}$)',fontsize=13,ha='left',transform=axs[0].transAxes) 146 | 147 | #plt.suptitle(r'wind stress $\tau$',x=0.86,y=0.98) 148 | plt.savefig(outpath+'plots/streamplot.eps') 149 | plt.close(fig) 150 | -------------------------------------------------------------------------------- /plot/energy_timeseries.py: -------------------------------------------------------------------------------- 1 | ## PLOT ENERGY AND ENSTROPY TIME SERIES 2 | from __future__ import print_function 3 | 4 | path1 = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 5 | path2 = '/network/aopp/cirrus/pred/kloewer/swm_bf_cntrl/data/' 6 | outpath = '/network/home/aopp/kloewer/swm/paperplot/' 7 | 8 | import os; os.chdir(path2) # change working directory 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | import matplotlib.patches as patches 12 | import matplotlib.gridspec as gridspec 13 | 14 | plt.rcParams['mathtext.fontset'] = 'cm' 15 | plt.rcParams['mathtext.rm'] = 'serif' 16 | 17 | # OPTIONS 18 | runfolder = [0,6,0,3,8] 19 | print('Compare mean plots from run ' + str(runfolder)) 20 | 21 | ## read data 22 | 23 | runpath1 = path2+'run%04i' % runfolder[0] 24 | D1 = np.load(runpath1+'/analysis/mean_timeseries.npy').all() 25 | 26 | runpath2 = path2+'run%04i' % runfolder[1] 27 | D2 = np.load(runpath2+'/analysis/mean_timeseries.npy').all() 28 | 29 | runpath3 = path1+'run%04i' % runfolder[2] 30 | D3 = np.load(runpath3+'/analysis/mean_timeseries.npy').all() 31 | 32 | runpath4 = path1+'run%04i' % runfolder[3] 33 | D4 = np.load(runpath4+'/analysis/mean_timeseries.npy').all() 34 | 35 | runpath5 = path1+'run%04i' % runfolder[4] 36 | D5 = np.load(runpath5+'/analysis/mean_timeseries.npy').all() 37 | 38 | for D in [D1,D3,D4,D5]: # from seconds to years 39 | D['t'] = D['t'] / 3600. / 24. / 365. 40 | 41 | # create new t2 time axis based on the knowledge that dt = 86260 seconds 42 | D2['t'] = (np.arange(len(D2['t']))*86260) / 3600. / 24. / 365. 43 | 44 | ## 45 | 46 | def running_mean(x, N): 47 | cumsum = np.cumsum(np.insert(x, 0, 0)) 48 | return (cumsum[N:] - cumsum[:-N]) / N 49 | 50 | ## PLOTTING 51 | 52 | #fig,((ax1,ax3),(ax2,ax4)) = plt.subplots(2,2,sharex=True,sharey='row',figsize=(8,6)) 53 | 54 | #fig = plt.figure(figsize=(8,6))parameteri 55 | #gs = gridspec.GridSpec(2, 2,width_ratios=[20,1]) 56 | 57 | # fig = plt.figure(figsize=(8,3)) 58 | # gs = gridspec.GridSpec(1, 2,width_ratios=[20,1]) 59 | 60 | fig,ax1 = plt.subplots(1,1,figsize=(8,3)) 61 | 62 | # ax1 = plt.subplot(gs[0]) 63 | #ax2 = plt.subplot(gs[1,0]) 64 | 65 | # ax3 = plt.subplot(gs[1]) 66 | #ax4 = plt.subplot(gs[1,1]) 67 | 68 | fig.tight_layout(rect=[0.02,0.03,1.01,0.95]) 69 | # fig.subplots_adjust(wspace=0.03,hspace=0.15) 70 | 71 | #ax1.set_xticklabels([]) 72 | 73 | # ax3.set_xticks([]) 74 | # ax4.set_xticks([]) 75 | 76 | # ax3.set_yticklabels([]) 77 | # ax4.set_yticklabels([]) 78 | 79 | ax1.set_xlim(0,30) 80 | # ax2.set_xlim(0,30) 81 | ax1.set_ylim(0,170) 82 | # ax3.set_ylim(0,170) 83 | 84 | # ax2.set_ylim(0,10) 85 | # ax4.set_ylim(0,10) 86 | 87 | # ax3.set_xlim(0,1) 88 | # ax4.set_xlim(0,1) 89 | 90 | KEmm = [0,]*5 91 | PEmm = [0,]*5 92 | for i,D in enumerate([D1,D2,D3,D4,D5]): 93 | KEmm[i] = D['KEm'][5*365:].mean()/1e3 94 | PEmm[i] = D['PEm'][5*365:].mean()/1e3 95 | 96 | # ax3.plot([0,1],np.ones(2)*KEmm[1],'C2',lw=3) 97 | # ax3.plot([0,1],np.ones(2)*KEmm[0],'C0',lw=3) 98 | # ax3.plot([0,1],np.ones(2)*KEmm[2],'C1',lw=1) 99 | # ax3.plot([0,1],np.ones(2)*KEmm[3],'C3',lw=1) 100 | # ax3.plot([0,1],np.ones(2)*KEmm[4],'C5',lw=1) 101 | 102 | # ax3.text(0.2,KEmm[1],"%i" % KEmm[1]) 103 | # ax3.text(0.2,KEmm[0],"%i" % KEmm[0]) 104 | # ax3.text(0.2,KEmm[2],"%i" % KEmm[2]) 105 | # ax3.text(0.2,KEmm[3],"%i" % KEmm[3]) 106 | # ax3.text(0.2,KEmm[4],"%i" % KEmm[4]) 107 | 108 | # ax4.plot([0,1],np.ones(2)*PEmm[1],'C2',lw=3) 109 | # ax4.plot([0,1],np.ones(2)*PEmm[0],'C0',lw=3) 110 | # ax4.plot([0,1],np.ones(2)*PEmm[2],'C1',lw=1) 111 | # ax4.plot([0,1],np.ones(2)*PEmm[3],'C3',lw=1) 112 | # ax4.plot([0,1],np.ones(2)*PEmm[4],'C5',lw=1) 113 | 114 | # ax4.text(0.2,PEmm[1],"%.1f" % PEmm[1]) 115 | # ax4.text(0.2,PEmm[0],"%.1f" % PEmm[0]) 116 | # ax4.text(0.2,PEmm[2],"%.1f" % PEmm[2]) 117 | # ax4.text(0.2,PEmm[3],"%.1f" % PEmm[3]) 118 | # ax4.text(0.2,PEmm[4],"%.1f" % PEmm[4]) 119 | 120 | # 121 | ax1.plot(D2['t'],D2['KEm']/1e3,'C2',label=r'High resolution, $\Delta x = $7.5km',lw=1.5) 122 | ax1.plot(D1['t'],D1['KEm']/1e3,'C0',label=r'Low resolution, $\Delta x = $30km',lw=1.5) 123 | ax1.plot(D3['t'],D3['KEm']/1e3,'C1',label=r'LR + weak backscatter',lw=1.5) 124 | ax1.plot(D4['t'],D4['KEm']/1e3,'C3',label=r'LR + moderate backscatter',lw=1.5) 125 | ax1.plot(D5['t'],D5['KEm']/1e3,'C5',label=r'LR + strong backscatter',lw=1.5) 126 | 127 | # monthly mean for potential energy 128 | m = 1 129 | for D in [D1,D2,D3,D4,D5]: 130 | #D['PEm'] = D['PEm'][:-(len(D['PEm']) % m)].reshape((-1,m)).mean(axis=1) 131 | #D['t'] = D['t'][:-(len(D['t']) % m)].reshape((-1,m)).mean(axis=1) 132 | 133 | D['PEm'] = running_mean(D['PEm'],m) 134 | D['t'] = running_mean(D['t'],m) 135 | 136 | # ax2.plot(D2['t'],D2['PEm']/1e3,'C2',lw=2) 137 | # ax2.plot(D1['t'],D1['PEm']/1e3,'C0',lw=2) 138 | # ax2.plot(D3['t'],D3['PEm']/1e3,'C1',lw=1) 139 | # ax2.plot(D4['t'],D4['PEm']/1e3,'C3',lw=1) 140 | # ax2.plot(D5['t'],D5['PEm']/1e3,'C5',lw=1,zorder=-1) 141 | 142 | ax1.add_patch(patches.Rectangle((0,0),5,ax1.get_ylim()[1],color='0.7')) 143 | # ax2.add_patch(patches.Rectangle((0,0),5,ax2.get_ylim()[1],color='grey',alpha=.3)) 144 | #invisible bar for legend 145 | ax1.bar(0,0,color='0.7',label='spin-up') 146 | 147 | ax1.set_title('Kinetic energy',loc='left') 148 | #ax1.set_title('a',loc='left',fontweight='bold') 149 | ax1.set_ylabel(r'kJ m$^{-2}$') 150 | ax1.set_ylim(0,150) 151 | 152 | # ax2.set_title('Potential energy PE') 153 | # ax2.set_title('b',loc='left',fontweight='bold') 154 | # ax2.set_ylabel(r'kJm$^{-2}$') 155 | ax1.set_xlabel('time [years]') 156 | ax1.legend(loc=4,fontsize=8,ncol=3) 157 | 158 | #ax1.grid() 159 | 160 | # ax3.set_title('c',fontweight='bold') 161 | # ax4.set_title('d',fontweight='bold') 162 | 163 | # ax3.set_ylabel('mean(KE)') 164 | # ax3.yaxis.set_label_position('right') 165 | 166 | # ax4.set_ylabel('mean(PE)') 167 | # ax4.yaxis.set_label_position('right') 168 | 169 | 170 | plt.savefig(outpath + 'plots/energy_timeseries_ke.eps') 171 | plt.close(fig) 172 | -------------------------------------------------------------------------------- /plot/powermap_plot_bs.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | path = '/network/aopp/cirrus/pred/kloewer/swm_bf_cntrl/data/' 4 | dpath = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 5 | outpath = '/network/home/aopp/kloewer/swm/paperplot/' 6 | 7 | import os; os.chdir(path) # change working directory 8 | import numpy as np 9 | from scipy import sparse 10 | import matplotlib.pyplot as plt 11 | import time as tictoc 12 | from netCDF4 import Dataset 13 | import glob 14 | from matplotlib.colors import BoundaryNorm,LogNorm 15 | import cmocean 16 | 17 | plt.rcParams['mathtext.fontset'] = 'cm' 18 | plt.rcParams['mathtext.rm'] = 'serif' 19 | 20 | # OPTIONS 21 | runfolder = [0,6,3] 22 | print('Plots for run ' + str(runfolder)) 23 | 24 | # read data 25 | 26 | runpath1 = path+'run%04i' % runfolder[0] 27 | D1 = np.load(runpath1+'/analysis/power_map.npy').all() 28 | param1 = np.load(runpath1+'/param.npy').all() 29 | 30 | runpath2 = path+'run%04i' % runfolder[1] 31 | D2 = np.load(runpath2+'/analysis/power_map.npy').all() 32 | param2 = np.load(runpath2+'/param.npy').all() 33 | 34 | runpath3 = dpath+'run%04i' % runfolder[2] 35 | D3 = np.load(runpath3+'/analysis/power_map.npy').all() 36 | param3 = np.load(runpath3+'/param.npy').all() 37 | print(param3['n_diss']) 38 | 39 | # functions 40 | def h2mat(h,param): 41 | return h.reshape((param['ny'],param['nx'])) 42 | 43 | def u2mat(u,param): 44 | return u.reshape((param['ny'],param['nx']-1)) 45 | 46 | def v2mat(v,param): 47 | return v.reshape((param['ny']-1,param['nx'])) 48 | 49 | def q2mat(q,param): 50 | return q.reshape((param['ny']+1,param['nx']+1)) 51 | # 52 | 53 | m = [0]*(len(runfolder)*3) 54 | s = 1e3 55 | 56 | expo = 1. 57 | 58 | # LOW RESOLUTION RUN 59 | in1 = h2mat(D1['InPower_T'],param1)*s 60 | m[0] = in1.mean() 61 | in1 = np.sign(in1)*abs(in1)**expo 62 | 63 | bf1 = h2mat(D1['BfricPower_T'],param1)*s 64 | m[1] = bf1.mean() 65 | bf1 = np.sign(bf1)*abs(bf1)**expo 66 | 67 | ex1 = h2mat(D1['ExPower_T'],param1)*s 68 | m[2] = ex1.mean() 69 | ex1 = np.sign(ex1)*abs(ex1)**expo 70 | 71 | # BACKSCATTER RUN 72 | in3 = h2mat(D3['InPower_T'],param3)*s 73 | m[3] = in3.mean() 74 | in3 = np.sign(in3)*abs(in3)**expo 75 | 76 | bf3 = h2mat(D3['BfricPower_T'],param3)*s 77 | m[4] = bf3.mean() 78 | bf3 = np.sign(bf3)*abs(bf3)**expo 79 | 80 | D3['ExPower_T'] += D3['BackPower_T'] 81 | 82 | ex3 = h2mat(D3['ExPower_T'],param3)*s 83 | m[5] = ex3.mean() 84 | ex3 = np.sign(ex3)*abs(ex3)**expo 85 | 86 | # bs = h2mat(D3['BackPower_T'],param3)*s 87 | # m[6] = bs.mean() 88 | # bs = np.sign(bs)*np.sqrt(abs(bs)) 89 | 90 | # HIGH RESOLUTION RUN 91 | in2 = h2mat(D2['InPower_T'],param2)*s 92 | m[6] = in2.mean() 93 | in2 = np.sign(in2)*abs(in2)**expo 94 | 95 | bf2 = h2mat(D2['BfricPower_T'],param2)*s 96 | m[7] = bf2.mean() 97 | bf2 = np.sign(bf2)*abs(bf2)**expo 98 | 99 | ex2 = h2mat(D2['ExPower_T'],param2)*s 100 | m[8] = ex2.mean() 101 | ex2 = np.sign(ex2)*abs(ex2)**expo 102 | 103 | mround = [np.round(mi,2) for mi in m] 104 | 105 | budget_closed = np.array(m).reshape((3,-1)) 106 | 107 | 108 | ## PLOTTING 109 | 110 | fig,axs = plt.subplots(3,3,figsize=(8.8,9),sharex=True,sharey=True) 111 | 112 | plt.tight_layout(rect=[0,.07,1,0.97]) 113 | fig.subplots_adjust(wspace=0.03,hspace=0.03) 114 | 115 | pos = axs[-1,0].get_position() 116 | pos2 = axs[-1,-1].get_position() 117 | cax = fig.add_axes([pos.x0,0.06,pos2.x1-pos.x0,0.02]) 118 | 119 | levs = np.linspace(-75**expo,75**expo,31) 120 | tik = np.array([-75,-50,-25,0,25,50,75]) 121 | tik = np.sign(tik)*abs(tik)**expo 122 | 123 | q1 = axs[0,0].contourf(param1['x_T'],param1['y_T'],in1,levs,cmap=cmocean.cm.balance,extend='both') 124 | cbar = fig.colorbar(q1,cax=cax,orientation='horizontal',ticks=tik) 125 | cbar.set_label(r'Power [Wm$^{-2} \cdot 10^{-3}$]') 126 | cbar.set_ticklabels(np.round(abs(tik)**expo*np.sign(tik)).astype(int)) 127 | 128 | axs[1,0].contourf(param3['x_T'],param3['y_T'],in3,levs,cmap=cmocean.cm.balance,extend='both') 129 | axs[2,0].contourf(param2['x_T'],param2['y_T'],in2,levs,cmap=cmocean.cm.balance,extend='both') 130 | 131 | axs[0,2].contourf(param1['x_T'],param1['y_T'],ex1,levs,cmap=cmocean.cm.balance,extend='both') 132 | axs[1,2].contourf(param3['x_T'],param3['y_T'],ex3,levs,cmap=cmocean.cm.balance,extend='both') 133 | axs[2,2].contourf(param2['x_T'],param2['y_T'],ex2,levs,cmap=cmocean.cm.balance,extend='both') 134 | 135 | axs[0,1].contourf(param1['x_T'],param1['y_T'],bf1,levs,cmap=cmocean.cm.balance,extend='both') 136 | axs[1,1].contourf(param3['x_T'],param3['y_T'],bf3,levs,cmap=cmocean.cm.balance,extend='both') 137 | axs[2,1].contourf(param2['x_T'],param2['y_T'],bf2,levs,cmap=cmocean.cm.balance,extend='both') 138 | 139 | #axs[1,3].contourf(param3['x_T'],param3['y_T'],bs,levs,cmap=cmocean.cm.balance,extend='both') 140 | 141 | 142 | axs[0,0].set_title('Wind forcing power',loc='left') 143 | axs[0,1].set_title('Bottom friction power',loc='left') 144 | axs[0,2].set_title('Biharmonic viscosity\n+ backscatter power',loc='left') 145 | #axs[1,3].set_title('Backscatter power',loc='left') 146 | 147 | abc = 'abcdefghijkl' 148 | abci = 0 149 | for i,axcol in enumerate(axs): 150 | for j,ax in enumerate(axcol): 151 | # if not(i in [0,2] and j == 3): 152 | plt.text(0.93,0.93,abc[abci],transform=ax.transAxes,fontweight='bold') 153 | plt.text(0.965,0.87,"%.2f" % mround[abci],transform=ax.transAxes,ha='right') 154 | abci += 1 155 | 156 | axs[0,0].set_xticks([]) 157 | axs[0,0].set_yticks([]) 158 | axs[0,0].set_xlim(15e3,param1['Lx']-15e3) 159 | axs[0,0].set_ylim(15e3,param1['Ly']-15e3) 160 | 161 | axs[0,0].set_ylabel(r'Low resolution, $\Delta x = $30km',fontsize=11) 162 | axs[1,0].set_ylabel(r'LR + strong backscatter',fontsize=11) 163 | axs[2,0].set_ylabel(r'High resolution, $\Delta x = $7.5km',fontsize=11) 164 | 165 | axs[-1,0].set_xlabel(r'$x$') 166 | axs[-1,1].set_xlabel(r'$x$') 167 | axs[-1,2].set_xlabel(r'$x$') 168 | #axs[-1,3].set_xlabel(r'$x$') 169 | 170 | #axs[0,3].set_frame_on(False) 171 | #axs[2,3].set_frame_on(False) 172 | 173 | axs[0,2].set_ylabel(r'$y$') 174 | axs[0,2].yaxis.set_label_position('right') 175 | 176 | axs[1,2].set_ylabel(r'$y$') 177 | axs[1,2].yaxis.set_label_position('right') 178 | 179 | axs[2,2].set_ylabel(r'$y$') 180 | axs[2,2].yaxis.set_label_position('right') 181 | 182 | plt.savefig(outpath+'plots/power_maps_bs.png',dpi=300) 183 | plt.close(fig) 184 | -------------------------------------------------------------------------------- /plot/energymap_plot.py: -------------------------------------------------------------------------------- 1 | ## PLOT ENERGY RESERVOIR MAPS 2 | from __future__ import print_function 3 | 4 | path1 = '/network/aopp/cirrus/pred/kloewer/swm_back_ronew/' 5 | path2 = '/network/aopp/cirrus/pred/kloewer/swm_bf_cntrl/data/' 6 | outpath = '/network/home/aopp/kloewer/swm/paperplot/' 7 | 8 | import numpy as np 9 | from scipy import sparse 10 | import matplotlib.pyplot as plt 11 | from cmocean import cm 12 | 13 | plt.rcParams['mathtext.fontset'] = 'cm' 14 | plt.rcParams['mathtext.rm'] = 'serif' 15 | 16 | # OPTIONS 17 | runfolder = [0,6,3] 18 | print('Compare mean plots from run ' + str(runfolder)) 19 | 20 | ## read data 21 | 22 | runpath1 = path2+'run%04i' % runfolder[0] 23 | D1 = np.load(runpath1+'/analysis/mean.npy').all() 24 | param1 = np.load(runpath1+'/param.npy').all() 25 | 26 | runpath2 = path2+'run%04i' % runfolder[1] 27 | D2 = np.load(runpath2+'/analysis/mean.npy').all() 28 | param2 = np.load(runpath2+'/param.npy').all() 29 | 30 | runpath3 = path1+'run%04i' % runfolder[2] 31 | D3 = np.load(runpath3+'/analysis/mean.npy').all() 32 | param3 = np.load(runpath3+'/param.npy').all() 33 | print(param3['n_diss']) 34 | 35 | # functions 36 | def h2mat(h,param): 37 | return h.reshape((param['ny'],param['nx'])) 38 | 39 | def u2mat(u,param): 40 | return u.reshape((param['ny'],param['nx']-1)) 41 | 42 | def v2mat(v,param): 43 | return v.reshape((param['ny']-1,param['nx'])) 44 | 45 | def q2mat(q,param): 46 | return q.reshape((param['ny']+1,param['nx']+1)) 47 | 48 | ## 49 | 50 | expo = 1. 51 | 52 | mm = np.empty((3,4)) 53 | 54 | mm[0,0] = D1['mke'].mean() 55 | mm[1,0] = D3['mke'].mean() 56 | mm[2,0] = D2['mke'].mean() 57 | 58 | mm[0,1] = D1['eke'].mean() 59 | mm[1,1] = D3['eke'].mean() 60 | mm[2,1] = D2['eke'].mean() 61 | 62 | mm[0,2] = D1['mpe'].mean() 63 | mm[1,2] = D3['mpe'].mean() 64 | mm[2,2] = D2['mpe'].mean() 65 | 66 | mm[0,3] = D1['epe'].mean() 67 | mm[1,3] = D3['epe'].mean() 68 | mm[2,3] = D2['epe'].mean() 69 | 70 | # total energy contribution 71 | rm = (mm.T / mm.sum(axis=1)).T 72 | rm = np.round(rm*100,1).flatten() 73 | 74 | for v in ['mke','eke']: 75 | D1[v] = (D1[v]/1e3)**expo 76 | D2[v] = (D2[v]/1e3)**expo 77 | D3[v] = (D3[v]/1e3)**expo 78 | 79 | for v in ['epe','mpe']: 80 | D1[v] = (D1[v]/1e3)**expo 81 | D2[v] = (D2[v]/1e3)**expo 82 | D3[v] = (D3[v]/1e3)**expo 83 | 84 | ## PLOTTING 85 | levs=[] 86 | for v in ['mke','eke','mpe','epe']: 87 | maxs = np.max((np.max(D1[v]),np.max(D2[v]))) 88 | #mins = np.min((np.min(D1[v]),np.min(D2[v]))) 89 | levs.append(np.linspace(0,maxs*0.95,32)) 90 | 91 | fig,axs = plt.subplots(3,4,figsize=(12,9),sharex=True,sharey=True) 92 | plt.tight_layout(rect=[0,.08,1,0.98]) 93 | fig.subplots_adjust(wspace=0.03,hspace=0.03) 94 | n = axs.shape[1] 95 | caxs = [0,]*n 96 | for i in range(n): 97 | pos = axs[-1,i].get_position() 98 | caxs[i] = fig.add_axes([pos.x0,0.06,pos.width,0.03]) 99 | 100 | qaxs = np.empty_like(axs) 101 | 102 | tiks = [np.array([0,100,200,300,400]),np.array([0,100,200,300,400]),np.array([0,1,2,3,4,5]),np.array([0,2,4,6,8,10,12])] 103 | #tiks = [np.array([0,100,200,300,400]),np.array([0,100,200,300,400,500])*2,np.array([0,1,2,3,4,5,6])*2,np.array([0,10,20,30,40,50])] 104 | 105 | 106 | qaxs[0,0] = axs[0,0].contourf(param1['x_T'],param1['y_T'],h2mat(D1['mke'],param1),levs[0],cmap=cm.thermal,extend='max') 107 | cb1 = fig.colorbar(qaxs[0,0],cax=caxs[0],orientation='horizontal',ticks=tiks[0]**expo) 108 | cb1.set_ticklabels(tiks[0]) 109 | cb1.set_label(r'[kJ m$^{-2}$]') 110 | 111 | qaxs[0,1] = axs[0,1].contourf(param1['x_T'],param1['y_T'],h2mat(D1['eke'],param1),levs[1],cmap=cm.thermal,extend='max') 112 | cb2 = fig.colorbar(qaxs[0,1],cax=caxs[1],orientation='horizontal',ticks=tiks[1]**expo) 113 | cb2.set_ticklabels(tiks[1].astype(np.int)) 114 | cb2.set_label(r'[kJ m$^{-2}$]') 115 | 116 | qaxs[0,2] = axs[0,2].contourf(param1['x_T'],param1['y_T'],h2mat(D1['mpe'],param1),levs[2],cmap=cm.thermal,extend='max') 117 | cb3 = fig.colorbar(qaxs[0,2],cax=caxs[2],orientation='horizontal',ticks=tiks[2]**expo) 118 | cb3.set_ticklabels(tiks[2]) 119 | cb3.set_label(r'[kJ m$^{-2}$]') 120 | 121 | qaxs[0,3] = axs[0,3].contourf(param1['x_T'],param1['y_T'],h2mat(D1['epe'],param1),levs[3],cmap=cm.thermal,extend='max') 122 | cb4 = fig.colorbar(qaxs[0,3],cax=caxs[3],orientation='horizontal',ticks=tiks[3]**expo) 123 | cb4.set_ticklabels(tiks[3]) 124 | cb4.set_label(r'[kJ m$^{-2}$]') 125 | 126 | axs[1,0].contourf(param3['x_T'],param3['y_T'],h2mat(D3['mke'],param3),levs[0],cmap=cm.thermal,extend='max') 127 | axs[1,1].contourf(param3['x_T'],param3['y_T'],h2mat(D3['eke'],param3),levs[1],cmap=cm.thermal,extend='max') 128 | axs[1,2].contourf(param3['x_T'],param3['y_T'],h2mat(D3['mpe'],param3),levs[2],cmap=cm.thermal,extend='max') 129 | axs[1,3].contourf(param3['x_T'],param3['y_T'],h2mat(D3['epe'],param3),levs[3],cmap=cm.thermal,extend='max') 130 | 131 | axs[2,0].contourf(param2['x_T'],param2['y_T'],h2mat(D2['mke'],param2),levs[0],cmap=cm.thermal,extend='max') 132 | axs[2,1].contourf(param2['x_T'],param2['y_T'],h2mat(D2['eke'],param2),levs[1],cmap=cm.thermal,extend='max') 133 | axs[2,2].contourf(param2['x_T'],param2['y_T'],h2mat(D2['mpe'],param2),levs[2],cmap=cm.thermal,extend='max') 134 | axs[2,3].contourf(param2['x_T'],param2['y_T'],h2mat(D2['epe'],param2),levs[3],cmap=cm.thermal,extend='max') 135 | 136 | axs[0,0].set_title('MKE',loc='left') 137 | axs[0,1].set_title('EKE',loc='left') 138 | axs[0,2].set_title('MPE',loc='left') 139 | axs[0,3].set_title('EPE',loc='left') 140 | 141 | axs[0,0].set_xticks([]) 142 | axs[0,0].set_yticks([]) 143 | 144 | axs[0,0].set_xlim(15e3,param1['Lx']-15e3) # to avoid a tiny white frame 145 | axs[0,0].set_ylim(15e3,param1['Ly']-15e3) 146 | 147 | axs[0,0].set_ylabel(r'Low resolution, $\Delta x = $30km',fontsize=11) 148 | axs[1,0].set_ylabel(r'LR + moderate backscatter',fontsize=11) 149 | axs[2,0].set_ylabel(r'High resolution, $\Delta x = $7.5km',fontsize=11) 150 | 151 | abc = 'abcdefghijkl' 152 | abci = 0 153 | for axcol in axs: 154 | for ax in axcol: 155 | plt.text(0.93,0.93,abc[abci],transform=ax.transAxes,fontweight='bold',color='w') 156 | plt.text(0.97,0.04,"%.1f%%" % rm[abci],transform=ax.transAxes,fontweight='bold',color='w',ha='right') 157 | abci += 1 158 | 159 | axs[-1,0].set_xlabel(r'$x$') 160 | axs[-1,1].set_xlabel(r'$x$') 161 | axs[-1,2].set_xlabel(r'$x$') 162 | axs[-1,3].set_xlabel(r'$x$') 163 | 164 | axs[0,3].set_ylabel(r'$y$') 165 | axs[0,3].yaxis.set_label_position('right') 166 | 167 | axs[1,3].set_ylabel(r'$y$') 168 | axs[1,3].yaxis.set_label_position('right') 169 | 170 | axs[2,3].set_ylabel(r'$y$') 171 | axs[2,3].yaxis.set_label_position('right') 172 | 173 | plt.savefig(outpath+'plots/energymap.png',dpi=300) 174 | plt.close(fig) 175 | -------------------------------------------------------------------------------- /swm_output.py: -------------------------------------------------------------------------------- 1 | ## OUTPUT FUNCTIONS 2 | # PART1: STORE DATA in netCDF4 file (output__nc_ini,output_nc,output_nc_fin) 3 | # PART2: STORE INFO in txt file (output_txt_ini, ... 4 | # PART3: STORE PARAMETERS IN .NPY FILE 5 | 6 | ## STORE DATA 7 | def output_nc_ini(): 8 | """ Initialise the netCDF4 file.""" 9 | 10 | param['output_j'] = 0 # output index 11 | 12 | # store files, dimensions and variables in dictionnaries 13 | ncu = dict() 14 | ncv = dict() 15 | nceta = dict() 16 | 17 | # creating the netcdf files 18 | ncformat = 'NETCDF4' 19 | ncu['file'] = Dataset(param['output_runpath']+'/u.nc','w',format=ncformat) 20 | ncv['file'] = Dataset(param['output_runpath']+'/v.nc','w',format=ncformat) 21 | nceta['file'] = Dataset(param['output_runpath']+'/eta.nc','w',format=ncformat) 22 | 23 | # write general attributes 24 | for ncfile in [ncu,ncv,nceta]: 25 | ncfile['file'].history = 'Created ' + tictoc.ctime(tictoc.time()) 26 | ncfile['file'].description = 'Data from: Shallow-water model in double gyre configuration.' 27 | ncfile['file'].details = 'Cartesian coordinates, beta-plane approximation, Arakawa C-grid' 28 | 29 | # all param ints floats and strings as global attribute 30 | for key in param.keys(): 31 | if (type(param[key]) is int) or (type(param[key]) is float) or (type(param[key]) is str): 32 | ncfile['file'].setncattr(key,param[key]) 33 | 34 | # create dimensions 35 | ncu['xdim'] = ncu['file'].createDimension('x',param['nx']-1) 36 | ncu['ydim'] = ncu['file'].createDimension('y',param['ny']) 37 | #ncu['tdim'] = ncu['file'].createDimension('t',param['output_tlen']) 38 | ncu['tdim'] = ncu['file'].createDimension('t',None) 39 | 40 | 41 | ncv['xdim'] = ncv['file'].createDimension('x',param['nx']) 42 | ncv['ydim'] = ncv['file'].createDimension('y',param['ny']-1) 43 | ncv['tdim'] = ncv['file'].createDimension('t',None) 44 | 45 | nceta['xdim'] = nceta['file'].createDimension('x',param['nx']) 46 | nceta['ydim'] = nceta['file'].createDimension('y',param['ny']) 47 | nceta['tdim'] = nceta['file'].createDimension('t',None) 48 | 49 | # create variables 50 | p = 'f4' # 32-bit precision storing, or f8 for 64bit 51 | for ncfile,var in zip([ncu,ncv,nceta],['u','v','eta']): 52 | # store time as integers as measured in seconds and gets large 53 | ncfile['t'] = ncfile['file'].createVariable('t','i8',('t',),zlib=True,fletcher32=True) 54 | ncfile['x'] = ncfile['file'].createVariable('x','f8',('x',),zlib=True,fletcher32=True) 55 | ncfile['y'] = ncfile['file'].createVariable('y','f8',('y',),zlib=True,fletcher32=True) 56 | ncfile[var] = ncfile['file'].createVariable(var,p,('t','y','x'),zlib=True,fletcher32=True) 57 | 58 | # write units 59 | for ncfile in [ncu,ncv,nceta]: 60 | ncfile['t'].units = 's' 61 | ncfile['t'].long_name = 'time' 62 | ncfile['x'].units = 'm' 63 | ncfile['x'].long_name = 'x' 64 | ncfile['y'].units = 'm' 65 | ncfile['y'].long_name = 'y' 66 | 67 | ncu['u'].units = 'm/s' 68 | ncv['v'].units = 'm/s' 69 | nceta['eta'].units = 'm' 70 | 71 | # write dimensions 72 | for ncfile,var in zip([ncu,ncv,nceta],['u','v','T']): 73 | ncfile['x'][:] = param['x_'+var] 74 | ncfile['y'][:] = param['y_'+var] 75 | 76 | # make globally available 77 | global ncfiles 78 | ncfiles = [ncu,ncv,nceta] 79 | 80 | output_txt('Output will be stored in '+param['outputpath']+param['runfolder']+' every %i hours.' % (param['output_dt']/3600.)) 81 | 82 | 83 | def output_nc(u,v,eta,t): 84 | """ Writes u,v,eta fields on every nth time step """ 85 | # output index j 86 | j = param['output_j'] # for convenience 87 | 88 | for ncfile in ncfiles: 89 | ncfile['t'][j] = t 90 | 91 | #TODO issue, use unlimited time dimension or not? 92 | ncfiles[0]['u'][j,:,:] = u2mat(u) 93 | ncfiles[1]['v'][j,:,:] = v2mat(v) 94 | ncfiles[2]['eta'][j,:,:] = h2mat(eta) 95 | 96 | param['output_j'] += 1 97 | 98 | def output_nc_fin(): 99 | """ Finalise the output netCDF4 file.""" 100 | 101 | for ncfile in ncfiles: 102 | ncfile['file'].close() 103 | 104 | output_txt('All output written in '+param['runfolder']+'.') 105 | 106 | ## STORE INFO in TXT FILE 107 | def readable_secs(secs): 108 | """ Returns a human readable string representing seconds in terms of days, hours, minutes, seconds. """ 109 | 110 | days = np.floor(secs/3600/24) 111 | hours = np.floor((secs/3600) % 24) 112 | minutes = np.floor((secs/60) % 60) 113 | seconds = np.floor(secs%3600%60) 114 | 115 | if days > 0: 116 | return ("%id, %ih" % (days,hours)) 117 | elif hours > 0: 118 | return ("%ih, %imin" % (hours,minutes)) 119 | elif minutes > 0: 120 | return ("%imin, %is" % (minutes,seconds)) 121 | else: 122 | return ("%.2fs" % secs) 123 | 124 | def duration_est(tic): 125 | """ Saves an estimate for the total time the model integration will take in the output txt file. """ 126 | time_togo = (tictoc.time()-tic) / (i+1) * param['Nt'] 127 | str1 = 'Model integration will take approximately '+readable_secs(time_togo)+', ' 128 | print(str1) 129 | 130 | if param['output']: 131 | str2 = 'and is hopefully done on '+tictoc.asctime(tictoc.localtime(tic + time_togo)) 132 | output_txt(str1+str2) 133 | print(str2) 134 | 135 | def output_txt_ini(): 136 | """ Initialise the output txt file for information about the run.""" 137 | if param['output']: 138 | param['output_txtfile'] = open(param['output_runpath']+'/info.txt','w') 139 | s = ('Shallow water model run %i initialised on ' % param['run_id'])+tictoc.asctime()+'\n' 140 | param['output_txtfile'].write(s) 141 | 142 | def output_scripts(): 143 | """Save all model scripts into a zip file.""" 144 | if param['output']: 145 | zf = zipfile.ZipFile(param['output_runpath']+'/scripts.zip','w') 146 | all_scripts = glob.glob('swm_*.py') 147 | [zf.write(script) for script in all_scripts] 148 | zf.close() 149 | output_txt('All model scripts stored in a zipped file.') 150 | 151 | def output_txt(s,end='\n'): 152 | """ Write into the output txt file.""" 153 | if param['output']: 154 | param['output_txtfile'].write(s+end) 155 | param['output_txtfile'].flush() 156 | 157 | def output_txt_fin(): 158 | """ Finalise the output txt file.""" 159 | if param['output']: 160 | param['output_txtfile'].close() 161 | 162 | ## STORE PARAMETERS 163 | def output_param(): 164 | """ Stores the param dictionary in a .npy file """ 165 | if param['output']: 166 | # filter out 'output_txtfile' as this is a unsaveable textwrapper 167 | dict_tmp = {key:param[key] for key in param.keys() if key != 'output_txtfile'} 168 | np.save(param['output_runpath']+'/param.npy',dict_tmp) 169 | 170 | # store also as a more readable .txt file for quick access on the parameters 171 | param_txtfile = open(param['output_runpath']+'/param.txt','w') 172 | for key in dict_tmp.keys(): 173 | if not(key in ['x_T','y_T','x_u','y_u','x_v','y_v','x_q','y_q']): 174 | param_txtfile.write(key + 2*'\t' + str(dict_tmp[key]) + '\n') 175 | 176 | param_txtfile.close() 177 | output_txt('Param dictionary stored as txt and zip.\n') 178 | -------------------------------------------------------------------------------- /calc/floats/floats_calc.py: -------------------------------------------------------------------------------- 1 | ## LAGRANGIAN FLOATS 2 | import numpy as np 3 | from netCDF4 import Dataset 4 | from scipy.interpolate import RegularGridInterpolator as RGI 5 | 6 | path = '/home/mkloewer/python/swm/' 7 | 8 | # OPTIONS 9 | runfolder = [2,3,4,5,6] 10 | print('Calculating floats from run ' + str(runfolder)) 11 | 12 | ## pad function for u,v 13 | def uv_pad(u,v): 14 | """ Pads u,v with kinematic and lateral boundary conditions. """ 15 | bs = 0 # boundary speed (positive inwards) 16 | u = np.pad(u,((0,0),(1,1),(1,1)),'constant',constant_values=((0,0),(bs,-bs),(bs,-bs))) # kinematic bc 17 | v = np.pad(v,((0,0),(1,1),(1,1)),'constant',constant_values=((0,0),(bs,-bs),(bs,-bs))) 18 | 19 | return u,v 20 | 21 | ## Reading data in blocks to save memory. 22 | def read_data(index_start): 23 | """ Based on the start index decide which datasets to load and do so.""" 24 | index_end = index_start + 2*ntime 25 | 26 | file_length0 = np.hstack((0,file_length)) 27 | file_length_each = np.hstack((file_length[0],np.diff(file_length))) 28 | 29 | start_crit = np.logical_and(index_start <= file_length,index_start > file_length0[:-1]) 30 | end_crit = np.logical_and(index_end <= file_length,index_end > file_length0[:-1]) 31 | 32 | data_to_read = np.logical_or(start_crit,end_crit) 33 | 34 | d = 0 35 | for r,rn in zip(np.array(runfolder)[data_to_read],np.arange(len(runfolder))[data_to_read]): 36 | 37 | # r is the run id 38 | # rn is the relative number of the run, starting with 0 for the first in runfolder 39 | 40 | runpath = path+'data/run%04i' % r 41 | 42 | if d == 0: # in case the first data set is read 43 | 44 | idx0 = index_start - file_length0[rn] 45 | idx1 = min(index_end - file_length0[rn],file_length_each[rn]+1) 46 | 47 | ncu = Dataset(runpath+'/u.nc') 48 | u = ncu.variables['u'][idx0:idx1,:,:] 49 | ncu.close() 50 | 51 | ncv = Dataset(runpath+'/v.nc') 52 | v = ncv.variables['v'][idx0:idx1,:,:] 53 | ncv.close() 54 | 55 | else: # concatenate second data set 56 | print('reading second file') 57 | idx0 = 1 # skip the first as this is a duplicate from the last step of previous file 58 | idx1 = index_end - file_length0[rn] + 1 59 | 60 | ncu = Dataset(runpath+'/u.nc') 61 | ncv = Dataset(runpath+'/v.nc') 62 | 63 | u = np.concatenate((u,ncu.variables['u'][idx0:idx1,:,:])) 64 | v = np.concatenate((v,ncv.variables['v'][idx0:idx1,:,:])) 65 | 66 | d = 1 # set to 1 to concatenate any further data set 67 | 68 | return u,v 69 | 70 | ## read grid 71 | file_length = np.empty(len(runfolder)).astype(np.int) # list to store the number of time steps in each file 72 | 73 | for i,r in enumerate(runfolder): 74 | runpath = path+'data/run%04i' % r 75 | ncu = Dataset(runpath+'/u.nc') 76 | 77 | if i == 0: time = ncu.variables['t'][:] 78 | else: time = np.hstack((time,ncu.variables['t'][:])) 79 | 80 | file_length[i] = len(time) 81 | 82 | dt = time[1]-time[0] 83 | 84 | # read spatial grid 85 | param = np.load(runpath+'/param.npy').all() 86 | 87 | # renaming for convenience 88 | x_u = param['x_u'] 89 | y_u = param['y_u'] 90 | 91 | x_v = param['x_v'] 92 | y_v = param['y_v'] 93 | 94 | # pad x,y to include the boundary conditions 95 | # grid is not equidistant at the boundary however ... 96 | x_u = np.hstack((0.,x_u,param['Lx'])) 97 | y_u = np.hstack((0.,y_u,param['Ly'])) 98 | 99 | y_v = np.hstack((0,y_v,param['Ly'])) 100 | x_v = np.hstack((0,x_v,param['Lx'])) 101 | 102 | print('Grid read.') 103 | 104 | ## OPTIONS 105 | N = 100 # number of floats 106 | ntime = 1460 # number of timesteps to integrate forward: equals one year 107 | R = 1000 # number of repetitions (from random start dates) 108 | 109 | # preallocate 110 | nbins = 254 111 | H = np.zeros((nbins,nbins)) 112 | 113 | #exclude up to 30km from boundary 114 | Hrange = [[30e3,3810e3],[30e3,3810e3]] 115 | 116 | # edges of inital seeding region 117 | seedx = np.array([100,200])*1e3 118 | seedy = np.array([100,1920])*1e3 119 | 120 | all_startidxs = np.sort(np.random.randint(0,len(time)-ntime-2,R)) 121 | 122 | ichunk = 0 123 | while all_startidxs.shape[0]: # delete from all_startidxs in every loop until empty 124 | ichunk += 1 125 | 126 | # indices for current chunk 127 | startidxs = all_startidxs[all_startidxs < (all_startidxs[0]+ntime)] 128 | 129 | # number of repetitions within chunk 130 | R_chunk = len(startidxs) 131 | 132 | # remove these dates from all_startidxs 133 | all_startidxs = all_startidxs[len(startidxs):] 134 | 135 | u,v = read_data(startidxs[0]) 136 | print('Data chunk %i read.' % ichunk) 137 | 138 | # padding with boundary conditions 139 | u,v = uv_pad(u,v) 140 | print('Padding boundary conditions: done.') 141 | 142 | # Advect the floats 143 | Xa = np.empty((ntime,N,R_chunk)).astype(np.float64) 144 | Ya = np.empty_like(Xa) 145 | 146 | # preallocate 147 | X = np.empty((ntime,N)).astype(np.float64) 148 | Y = np.empty_like(X).astype(np.float64) 149 | 150 | for r in range(R_chunk): 151 | # relative index within dataset 152 | i_rel = startidxs[r] - startidxs[0] 153 | 154 | # set initial conditions 155 | X[0,:] = np.random.rand(N)*np.diff(seedx) + seedx[0] 156 | Y[0,:] = np.random.rand(N)*np.diff(seedy) + seedy[0] 157 | 158 | # old time step 159 | Iu1 = RGI((x_u,y_u),u[i_rel,:,:].T,bounds_error=False,fill_value=-1) 160 | Iv1 = RGI((x_v,y_v),v[i_rel,:,:].T,bounds_error=False,fill_value=-1) 161 | 162 | for i in range(ntime-1): 163 | # Following the ideas of the Crank-Nicolson method 164 | # However, as the RHS is discrete, Euler forward is used to estimate 165 | # the RHS of the next time step 166 | 167 | # next time step 168 | # fill_value means once they are out of the boundary floats stop moving 169 | Iu2 = RGI((x_u,y_u),u[i+i_rel+1,:,:].T,bounds_error=False,fill_value=0) 170 | Iv2 = RGI((x_v,y_v),v[i+i_rel+1,:,:].T,bounds_error=False,fill_value=0) 171 | 172 | # old RHS 173 | dXdt1 = Iu1((X[i,:],Y[i,:])) 174 | dYdt1 = Iv1((X[i,:],Y[i,:])) 175 | 176 | # new RHS based on new time step 177 | dXdt2 = Iu2((X[i,:] + dt*dXdt1,Y[i,:] + dt*dYdt1)) 178 | dYdt2 = Iv2((X[i,:] + dt*dXdt1,Y[i,:] + dt*dYdt1)) 179 | 180 | # average of old and new RHS 181 | X[i+1,:] = X[i,:] + 0.5*dt*(dXdt1+dXdt2) 182 | Y[i+1,:] = Y[i,:] + 0.5*dt*(dYdt1+dYdt2) 183 | 184 | # rename to avoid re-setting up of RGI functions 185 | Iu1 = Iu2 # next -> old 186 | Iv1 = Iv2 187 | 188 | Xa[:,:,r] = X 189 | Ya[:,:,r] = Y 190 | 191 | print('Advecting floats done.') 192 | 193 | # free memory 194 | del u,v 195 | 196 | # histogram do not count the grid cell at the boundary 197 | Hi,xe,ye = np.histogram2d(Xa.flatten(),Ya.flatten(),bins=nbins,range=Hrange) 198 | H += Hi 199 | print('Histogram computed.') 200 | 201 | # free memory 202 | del Xa,Ya 203 | 204 | 205 | print(H.sum()) 206 | 207 | # mid points 208 | xm = xe[:-1] + (xe[1]-xe[0])/2. 209 | ym = ye[:-1] + (ye[1]-ye[0])/2. 210 | 211 | ## STORING 212 | dic = dict() 213 | all_var2export = ['X','Y','seedx','seedy','H','xe','ye','xm','ym'] 214 | 215 | for vars in all_var2export: 216 | exec('dic[vars] ='+vars) 217 | 218 | np.save(runpath+'/analysis/floats.npy',dic) 219 | print('Everything stored.') 220 | --------------------------------------------------------------------------------