PageRenderTime 38ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/model/model_handles2.m

http://shel.googlecode.com/
MATLAB | 1544 lines | 1135 code | 150 blank | 259 comment | 79 complexity | 32b376cbf647d8712f9e4053adb5389c MD5 | raw file
Possible License(s): GPL-2.0
  1. %--------------------------------------------------------------------------
  2. % This file is part of SHEL SHallow-water numerical modEL
  3. %
  4. % SHEL is free software: you can redistribute it and/or modify
  5. % it under the terms of the GNU General Public License as published by
  6. % the Free Software Foundation, either version 3 of the License, or
  7. % (at your option) any later version.
  8. %
  9. % SHEL is distributed in the hope that it will be useful,
  10. % but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. % GNU General Public License for more dr.etails.
  13. %
  14. % You should have received a copy of the GNU General Public License
  15. % along with SHEL. If not, see <http://www.gnu.org/licenses/>.
  16. %--------------------------------------------------------------------------
  17. function s = model_handles2(r)
  18. %function s = model_handles2
  19. %
  20. %Call it this way:
  21. % s = model_handles;
  22. % y = s.model_compute_input(); % --> the parenthesis ARE REQUIRED!
  23. % y = s.model_compute_output( handles );
  24. %globals are replaced by a big structure
  25. r.time = nan;
  26. r.timetr = nan;
  27. r.dt = nan;
  28. r.dttr = nan;
  29. r.ltr = nan;
  30. r.frame = nan;
  31. r.duration = nan;
  32. r.outputdt = nan;
  33. r.L = nan;
  34. r.outputL = nan;
  35. r.frame = nan;
  36. r.printG = nan;
  37. r.film = nan;
  38. r.mov = nan;
  39. r.myfullfile = nan;
  40. r.mydir = nan;
  41. r.optprint = nan;
  42. r.dx = nan;
  43. r.dy = nan;
  44. r.M = nan;
  45. r.N = nan;
  46. r.x0 = nan;
  47. r.y0 = nan;
  48. r.x = nan;
  49. r.y = nan;
  50. r.x_u = nan;
  51. r.y_u = nan;
  52. r.x_v = nan;
  53. r.y_v = nan;
  54. r.x_w = nan;
  55. r.y_w = nan;
  56. r.loadbathymetry = nan;
  57. r.bathymetryfile = nan;
  58. r.varsinfile = nan;
  59. %Test-cases
  60. r.tc_bump = nan;
  61. r.tc_geostrophic = nan;
  62. r.tc_isla = nan;
  63. r.tc_taylor = nan;
  64. %boundary condition
  65. r.u_closed = nan;
  66. r.v_closed = nan;
  67. %r.bc_closed;
  68. r.noslip = nan;
  69. %r.step bathym
  70. r.step = nan;
  71. %bump
  72. r.bump_x0 = nan;
  73. r.bump_y0 = nan;
  74. r.bump_sx = nan;
  75. r.bump_sy = nan;
  76. r.bump_d0 = nan;
  77. %island
  78. r.isla_x0 = nan;
  79. r.isla_y0 = nan;
  80. r.isla_R = nan;
  81. %r.tracer
  82. r.tracer = nan;
  83. r.TrXo = nan;
  84. r.TrYo = nan;
  85. r.TrR = nan;
  86. %Grid and bathymetry related
  87. r.land = nan;
  88. r.d0 = nan;
  89. r.d0_r = nan;
  90. %T-cells
  91. r.Tr = nan;
  92. r.eta0 = nan;
  93. r.eta_old = nan;
  94. r.eta = nan;
  95. r.eta_new = nan;
  96. r.H_old = nan;
  97. r.H = nan;
  98. r.H_new = nan;
  99. r.d = nan;
  100. r.mask = nan;
  101. r.masknan = nan;
  102. r.u_t = nan;
  103. r.v_t = nan;
  104. %Diagnostic quantities
  105. r.ke = nan;
  106. r.pe = nan;
  107. r.eke = nan;
  108. r.gradux = nan;
  109. r.graduy = nan;
  110. r.gradvx = nan;
  111. r.gradvy = nan;
  112. r.curl_t = nan;
  113. r.potvorticity_t = nan;
  114. r.strechrate_t = nan;
  115. r.shearrate_t = nan;
  116. r.sqstrechrate_t = nan;
  117. r.sqshearrate_t = nan;
  118. r.enstrophy_t = nan;
  119. r.sqstrain_t = nan;
  120. r.divergence_t = nan;
  121. r.sqdivergence_t = nan;
  122. r.okuboweiss_t = nan;
  123. %r.u-cells
  124. r.u_a = nan;
  125. r.u_old = nan;
  126. r.u = nan;
  127. r.u_new = nan;
  128. r.mask_u = nan;
  129. %r.v-cells
  130. r.v_a = nan;
  131. r.v_old = nan;
  132. r.v = nan;
  133. r.v_new = nan;
  134. r.mask_v = nan;
  135. %Z-cells
  136. r.curl_w = nan;
  137. r.potvorticity_w = nan;
  138. r.shearrate_w = nan;
  139. r.sqshearrate_w = nan;
  140. r.enstrophy_w = nan;
  141. r.okuboweiss_w = nan;
  142. %r.time-dependent r.properties (domain integrated)
  143. r.volume = nan;
  144. r.iKe = nan;
  145. r.iPe = nan;
  146. r.vtime = nan;
  147. r.iVort = nan;
  148. r.iEnst = nan;
  149. r.iSqStrech = nan;
  150. r.iSqShear = nan;
  151. r.iSqStrain = nan;
  152. r.iOWeiss = nan;
  153. r.iMomentumU = nan;
  154. r.iMomentumV = nan;
  155. r.iEke = nan;
  156. r.K = nan;
  157. r.gama = nan;
  158. s.model_compute_input = @ComputeModelInput;
  159. s.model_compute_output = @ComputeModelOutput;
  160. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  161. %% Here starts the model Inputs part
  162. %%Initial conditions
  163. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  164. function ComputeModelInput(r)
  165. %function ComputeModelInputs
  166. %GR : clears figure of images
  167. r.frame = 1;
  168. r.time = 0.;
  169. r.timetr = r.time + 2 * r.dt;
  170. ComputeTime(r);
  171. makecoordinates(r);
  172. fillfields(r);
  173. function ComputeTime(r)
  174. %function updateTime
  175. r.L = getL(r.duration,r.dt);
  176. r.outputL = getL(r.outputdt, r.dt);
  177. function L_L = getL (duration_L, dt_L)
  178. %function L_L = getL (duration_L, dt_L)
  179. L_L = floor(duration_L / dt_L);
  180. function makecoordinates(r)
  181. %function makecoordinates
  182. if r.loadbathymetry
  183. r.varsinfile = who('-file',r.bathymetryfile);
  184. if ~isempty(r.varsinfile)
  185. load(r.bathymetryfile, 'r.d');
  186. siz = size(r.d);
  187. r.M = siz(1);
  188. r.N = siz(2);
  189. end
  190. end
  191. r.x0 = r.dx/2;
  192. r.y0 = r.dy/2;
  193. %T-cell
  194. r.x = (1:r.M)' * (1:r.N);
  195. r.y = (1:r.M)' * (1:r.N);
  196. for j = 1:r.N
  197. r.x(:,j) = r.x0 + (r.x(:,j)/j - 1) * r.dx;
  198. end
  199. for i = 1:r.M
  200. r.y(i,:) = r.y0 + (r.y(i,:)/i - 1) * r.dy;
  201. end
  202. %r.u-cell
  203. r.x_u = (1:r.M+1)' * (1:r.N);
  204. r.y_u = (1:r.M+1)' * (1:r.N);
  205. for j = 1:r.N
  206. r.x_u(:,j) = r.x0 + (r.x_u(:,j)/j - 1) * r.dx - r.dx/2;
  207. end
  208. for i = 1:r.M
  209. r.y_u(i,:) = r.y0 + (r.y_u(i,:)/i - 1) * r.dy;
  210. end
  211. %r.v-cell
  212. r.x_v = (1:r.M)' * (1:r.N+1);
  213. r.y_v = (1:r.M)' * (1:r.N+1);
  214. for j = 1:r.N
  215. r.x_v(:,j) = r.x0 + (r.x_v(:,j)/j - 1) * r.dx;
  216. end
  217. for i = 1:r.M
  218. r.y_v(i,:) = r.y0 + (r.y_v(i,:)/i - 1) * r.dy - r.dy/2;
  219. end
  220. %W-cell
  221. r.x_w = (1:r.M)' * (1:r.N);
  222. r.y_w = (1:r.M)' * (1:r.N);
  223. for j = 1:r.N
  224. r.x_w(:,j) = r.x0 + (r.x_w(:,j)/j - 1) * r.dx - r.dx/2;
  225. end
  226. for i = 1:r.M
  227. r.y_w(i,:) = r.y0 + (r.y_w(i,:)/i - 1) * r.dy - r.dy/2;
  228. end
  229. function fillfields(r)
  230. %function fillfields
  231. % Arakawa C staggered grid (Arakawa 1966)
  232. %
  233. % --j y
  234. % | --- r.v --- r.v ------- r.v r.u -- T -- r.u
  235. % i | | | | | |
  236. % x r.u T r.u T r.u T | r.v |
  237. % | | | | | |
  238. % --- r.v --- r.v ------- r.v r.u -- T -- r.u
  239. % T-cell r.u-cell r.v-cell
  240. %
  241. % T(r.eta, r.H, r.Tr, r.d, f, r.mask, r.u(r.u, r.mask_u r.v(r.v, r.mask_v
  242. % x, y, wind and bottom r.x_u, r.y_u) r.x_v, r.y_v)
  243. % stress)
  244. % --j y
  245. % | T--- r.u ---T
  246. % i | |
  247. % x r.v W r.v
  248. % | |
  249. % T--- r.u ---T
  250. % W-cell
  251. %
  252. % W(zr.eta - curl of r.v, vorticity)
  253. %Depth field (bathymetry)%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  254. r.land = -99;
  255. %%Constant depth or read from bathymetry file
  256. if r.tc_taylor %Submarine mount equals 30% of total mean depth
  257. r.d = r.d0 - cylindermap(r,zeros(size(r.d)), 0.3 * r.d0, r.bump_sx, r.bump_sy, ...
  258. r.M * r.dx * .5 - r.bump_x0, ...
  259. r.N * r.dy * .5 - r.bump_y0);
  260. elseif r.loadbathymetry && sum(strcmp(r.varsinfile,'r.d'))
  261. load(r.bathymetryfile, 'r.d');
  262. else
  263. r.d = r.d0 * ones(r.M,r.N);
  264. end
  265. %%changing depth
  266. if r.step
  267. r.d = maker.step(r.d,r.d0_r.step);
  268. end
  269. %%Closed boundaries: boundaries are filled with r.land
  270. if r.v_closed
  271. for j = 1:r.N-1:r.N;
  272. for i = 1:r.M
  273. r.d(i,j) = r.land;
  274. end
  275. end
  276. end
  277. if r.u_closed
  278. for i = 1:r.M-1:r.M;
  279. for j = 1:r.N
  280. r.d(i,j) = r.land;
  281. end
  282. end
  283. end
  284. %%Inner islands (random)
  285. %%%arguments: depth, io, jo, r
  286. if r.tc_isla
  287. r.d = makeisland(r,r.d, r.M * r.dx * .5 - r.isla_x0, r.N * r.dy * .5 - r.isla_y0, r.isla_R);
  288. end
  289. %WATERMASK matrices%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  290. %T-cell
  291. %%all-water
  292. r.mask = ones(r.M,r.N);
  293. %%eventual islands and closed domain
  294. for j=1:r.N
  295. for i=1:r.M
  296. if r.d(i,j) < 0.
  297. r.mask(i,j) = 0;
  298. end
  299. end
  300. end
  301. %r.u-Cell and r.v-cell
  302. r.mask_u = ones(r.M+1,r.N);
  303. r.mask_v = ones(r.M,r.N+1);
  304. for j = 1:r.N
  305. for i = 1:r.M
  306. if r.mask( i, j) == 0
  307. r.mask_u( i, j) = r.mask(i,j);
  308. r.mask_u(i+1, j) = r.mask(i,j);
  309. r.mask_v( i, j) = r.mask(i,j);
  310. r.mask_v( i,j+1) = r.mask(i,j);
  311. end
  312. end
  313. end
  314. if r.noslip
  315. %r.u-cells
  316. for j = 2:r.N-1
  317. for i = 2:r.M
  318. r.mask_u(i,j) = r.mask(i ,j+1) * r.mask(i ,j-1) * r.mask(i-1,j+1) * r.mask(i-1,j-1);
  319. end
  320. end
  321. %r.v-Cells
  322. for j = 2:r.N
  323. for i = 2:r.M-1
  324. r.mask_v(i,j) = r.mask(i+1, j) * r.mask(i+1,j-1) * r.mask(i-1, j) * r.mask(i-1,j-1);
  325. end
  326. end
  327. end
  328. %Water level fields%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  329. if (r.tc_bump || r.tc_geostrophic)
  330. r.eta_old = bumpmap(r,r.bump_d0, r.bump_sx, r.bump_sy, r.M * r.dx * .5 - r.bump_x0, ...
  331. r.N * r.dy * .5 - r.bump_y0);
  332. else
  333. if r.loadbathymetry && sum(strcmp(r.varsinfile,'r.eta'))
  334. load(r.bathymetryfile, 'r.eta');
  335. r.eta_old = r.eta;
  336. else
  337. r.eta_old = r.eta0 * ones(r.M,r.N);
  338. end
  339. end
  340. r.eta = r.eta_old;
  341. r.eta_new = r.eta;
  342. %Bottom-to-surface depth (always positive below the water surface)
  343. %r.H = r.eta + r.d.
  344. r.H_old = r.eta_old + r.d;
  345. r.H =r.H_old;
  346. r.H_new = r.H_old;
  347. if r.tracer
  348. %Unitary concentration...
  349. r.Tr = zeros(r.M,r.N);
  350. r.Tr = cylindermap(r,r.Tr, 1., r.TrR, r.TrR, r.M * r.dx * .5 - r.TrXo, ...
  351. r.N * r.dy * .5 - r.TrYo);
  352. end
  353. %r.u velocity fields%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  354. if r.tc_geostrophic
  355. r.u_old = ugeo(r.eta);
  356. elseif r.tc_taylor % 3 cm/s r.u-flow
  357. r.u_old = zeros(size(r.mask_u));
  358. %%uncomment one of the following lines
  359. r.u_old = 0.03 * ones(size(r.mask_u));
  360. %r.u_old(1:r.M:r.M+1,:) = 0.03 * ones(size(r.mask_u(1:r.M:r.M+1,:)));
  361. else
  362. if r.loadbathymetry && sum(strcmp(r.varsinfile,'r.u'))
  363. load(r.bathymetryfile, 'r.u');
  364. r.u_old = r.u;
  365. else
  366. r.u_old = zeros(r.M+1,r.N);
  367. end
  368. end
  369. r.u = r.u_old;
  370. r.u_new = r.u;
  371. r.u_a = r.u;
  372. %r.v velocity fields%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  373. if r.tc_geostrophic
  374. r.v_old = vgeo(r.eta);
  375. else
  376. if r.loadbathymetry && sum(strcmp(r.varsinfile,'r.v'))
  377. load(r.bathymetryfile, 'r.v');
  378. r.v_old = r.v;
  379. else
  380. r.v_old = zeros(r.M,r.N+1);
  381. end
  382. end
  383. r.v = r.v_old;
  384. r.v_new = r.v;
  385. r.v_a = r.v;
  386. %call this function when you need
  387. %to manually initialize the level
  388. %in the Taylor column flow.
  389. if r.tc_taylor
  390. makeGeostLevelFromU(r)
  391. end
  392. %Z field%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  393. r.curl_w = zeros(r.M+1,r.N+1);
  394. r.potvorticity_w = zeros(r.M+1,r.N+1);
  395. r.enstrophy_w = zeros(r.M+1,r.N+1);
  396. r.shearrate_w = zeros(r.M+1,r.N+1);
  397. r.sqshearrate_w = zeros(r.M+1,r.N+1);
  398. r.okuboweiss_w = zeros(r.M+1,r.N+1);
  399. %Visualization matrices%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  400. r.masknan = ones(r.M,r.N);
  401. for j=1:r.N
  402. for i=1:r.M
  403. if r.mask(i,j) == 0
  404. r.masknan(i,j) = nan;
  405. else
  406. r.masknan(i,j) = 1;
  407. end
  408. end
  409. end
  410. r.u_t = zeros(r.M,r.N);
  411. r.v_t = zeros(r.M,r.N);
  412. r.ke = zeros(r.M,r.N);
  413. r.pe = zeros(r.M,r.N);
  414. r.curl_t = zeros(r.M,r.N);
  415. r.potvorticity_t = zeros(r.M,r.N);
  416. r.strechrate_t = zeros(r.M,r.N);
  417. r.shearrate_t = zeros(r.M,r.N);
  418. r.enstrophy_t = zeros(r.M,r.N);
  419. r.sqstrain_t = zeros(r.M,r.N);
  420. r.okuboweiss_t = zeros(r.M,r.N);
  421. r.sqshearrate_t = zeros(r.M,r.N);
  422. r.sqstrechrate_t = zeros(r.M,r.N);
  423. r.divergence_t = zeros(r.M,r.N);
  424. r.sqdivergence_t = zeros(r.M,r.N);
  425. %Eddy kinetic energy
  426. r.gradux=zeros(r.M,r.N);
  427. r.graduy=zeros(r.M,r.N);
  428. r.gradvx=zeros(r.M,r.N);
  429. r.gradvy=zeros(r.M,r.N);
  430. r.eke=zeros(r.M,r.N);
  431. %One-dimensional diagnostic variables
  432. %Energy initialization
  433. r.vtime = nan(1,L);
  434. r.iKe = nan(1,L);
  435. r.iPe = nan(1,L);
  436. r.iEke = nan(1,L);
  437. r.volume = nan(1,L);
  438. r.iVort = nan(1,L);
  439. r.iEnst = nan(1,L);
  440. r.iSqShear = nan(1,L);
  441. r.iSqStrech = nan(1,L);
  442. r.iSqStrain = nan(1,L);
  443. r.iOWeiss = nan(1,L);
  444. r.iMomentumU = nan(1,L);
  445. r.iMomentumV = nan(1,L);
  446. ComputeDiagnostics(1);
  447. %cylinder field
  448. function map_L = cylindermap(r,map_L, l, sx, sy, x_L, y_L)
  449. ind = find ( (x - x_L).^2 / sx^2 + (y - y_L).^2 / sy^2 < 1. );
  450. map_L(ind) = l;
  451. %bump test-case field
  452. function map_L = bumpmap(r,l, sx, sy, x_L, y_L)
  453. map_L = zeros(r.M,r.N);
  454. for i = 1:r.M
  455. for j = 1:r.N
  456. map_L(i,j) = l * exp( - ( ( x(i,j) - x_L )^2 / sx^2 + ( y(i,j) - y_L )^2 / sy^2 ) );
  457. end
  458. end
  459. function depth = makeisland(r,depth, x_L, y_L, r)
  460. %function depth = makeisland(depth, x_L, y_L, r)
  461. for i = 1:r.M
  462. for j = 1:r.N
  463. if r^2 > ( x(i,j) - x_L )^2 + ( y(i,j) - y_L )^2
  464. depth(i,j) = r.land;
  465. end
  466. end
  467. end
  468. function ugeo_L = ugeo(r, r.eta_L)
  469. %function ugeo_L = ugeo(r.eta_L)
  470. j_L = floor(r.N/2)+1;
  471. sig_L = 1.;
  472. ug_L = zeros(r.M,r.N);
  473. for i=1:r.M
  474. for j=1:r.N
  475. ug_L(i,j) = g / f * ( j - j_L ) / sig_L^2 * r.eta_L(i,j);
  476. end
  477. end
  478. ugeo_L = InterpolTU(ug_L);
  479. function vgeo_L = vgeo(r,r.eta_L)
  480. %function vgeo_L = vgeo(r.eta_L)
  481. i_L = floor(r.M/2)+1;
  482. sig_L = 1.;
  483. vg_L = zeros(r.M,r.N);
  484. for i=1:r.M
  485. for j=1:r.N
  486. vg_L(i,j) = - g / f * ( i - i_L ) / sig_L^2 * r.eta_L(i,j);
  487. end
  488. end
  489. vgeo_L = InterpolTV(vg_L);
  490. function bath = makestep(bath,depth)
  491. %function bath = makestep(bath,depth)
  492. %Creates a r.stepped bathymetry
  493. sz = size(bath);
  494. M = sz(1);
  495. N = sz(2);
  496. j0 = N/5;
  497. for i = 1:M
  498. for j = 1:N
  499. if j < 0.9 * i + j0
  500. bath(i,j) = depth;
  501. end
  502. end
  503. end
  504. function makeGeostLevelFromU(r)
  505. for j=2:r.N
  506. for i=1:r.M
  507. r.eta(i,j) = r.eta(i,j-1) * r.mask(i,j-1) - r.dy * f/g * (...
  508. r.mask_u(i,j) * r.u(i,j) + r.mask_u(i+1,j) * r.u(i+1,j) ...
  509. + r.mask_u(i,j-1) * r.u(i,j-1) + r.mask_u(i+1,j-1) * r.u(i+1,j-1) ...
  510. ) / ( ...
  511. r.mask_u(i,j) + r.mask_u(i+1,j) + r.mask_u(i,j-1) + r.mask_u(i+1,j-1) ...
  512. );
  513. r.eta(i,j) = r.mask(i,j) * r.eta(i,j);
  514. end
  515. end
  516. r.eta_old = r.eta;
  517. r.eta_new = r.eta;
  518. r.H_old = r.eta_old + r.d;
  519. r.H =r.H_old;
  520. r.H_new = r.H_old;
  521. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  522. %% Here starts the model Outputs part
  523. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  524. function ComputeModelOutput( r, handles )
  525. %function ComputeModelOutputs( handles ) [old ComputeModel]
  526. %r.time parameters and output parameters
  527. s = GUI_common_handles;
  528. %Movie initialization
  529. clear mex;
  530. tic;
  531. ol = 0;
  532. movie = false;
  533. %Define the type of output
  534. switch optprint
  535. case {11, 12, 13, 14, 15}
  536. movie = true;
  537. end
  538. % Write output of initial condition to disk.
  539. if printG
  540. if movie
  541. %Open a new avi file.
  542. filename = sprintf('%s.avi', [mydir,'/',myfullfile]);
  543. mov = avifile(filename,'fps', 10,'quality',100,'compression','None');
  544. end
  545. s.GUI_printit(frame, handles, optprint);
  546. frame = frame + 1;
  547. end
  548. % Main loop in r.time
  549. r.ltr = 0;
  550. for l = 1 : L
  551. %Takes care of the numerical scheme
  552. %for momentum and for the r.tracer
  553. %This line can easily be replaced
  554. %with a switch, choosing one kernel
  555. %among many (mex file kernel, other
  556. %kernels ...).
  557. kernel_SHEL(r,l);
  558. % Take care of plotting the outputs and write them to disk.
  559. if ol == outputL
  560. ol=0;
  561. if film
  562. s.GUI_plotmodel(handles);
  563. pause(0.1); %s
  564. end
  565. if printG
  566. s.GUI_printit(frame, handles, optprint);
  567. frame = frame + 1;
  568. end
  569. %Display r.time
  570. strin = sprintf('r.time = %0.3g s', r.time);
  571. set(handles.timetext,'String',strin);
  572. pause(0.01); %s pause (required if I want to update the clock).
  573. end
  574. ol=ol+1;
  575. %End of main loop in r.time
  576. end
  577. % Take care of writing the final output on disk
  578. if printG
  579. if movie
  580. mov = close(mov);
  581. end
  582. end
  583. if ~film
  584. s.GUI_plotmodel(handles);
  585. end
  586. % Display simulation statistics and performance
  587. cput = toc;
  588. disp(sprintf('Elapsed r.time: %0.5f s\nTime per iteration: %0.5f s\r.N', cput, cput/L));
  589. if r.tracer
  590. disp(sprintf('Made %0.3d r.tracer iterations on a total of %0.3d iterations', r.ltr, l));
  591. end
  592. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  593. %% Here starts the Kernel part
  594. %%the numerical scheme
  595. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  596. function kernel_SHEL(r,l)
  597. %function kernel_SHEL (old ComputeModel)
  598. %Explicit leapfrog scheme
  599. %combined with Asselin-Roberts filter
  600. %(the filter supresses the computational mode
  601. %and prevents decoupling between odd/even timer.steps)
  602. %
  603. % Arakawa C staggered grid (Arakawa 1966)
  604. %
  605. % --j y
  606. % | --- r.v --- r.v ------- r.v r.u -- T -- r.u
  607. % i | | | | | |
  608. % x r.u T r.u T r.u T | r.v |
  609. % | | | | | |
  610. % --- r.v --- r.v ------- r.v r.u -- T -- r.u
  611. % T-cell r.u-cell r.v-cell
  612. % r.M x r.N r.M+1 x r.N r.M x r.N+1
  613. % T(r.eta, r.H, r.Tr, r.d, f, r.mask, r.u(r.u, r.mask_u r.v(r.v, r.mask_v
  614. % x, y, wind and bottom r.x_u, r.y_u) r.x_v, r.y_v)
  615. % stress, curl(r.v,r.u,0))
  616. %
  617. % --j y
  618. % | --- r.u ---
  619. % i | |
  620. % x r.v W r.v
  621. % | |
  622. % --- r.u ---
  623. % T-cell
  624. % r.M+1 x r.N+1
  625. % W( curl(r.u,r.v,0) )
  626. % (deformation rate = curl(-r.u,r.v,0)
  627. %%%
  628. %Update the r.time
  629. r.time = r.time + r.dt;
  630. %Compute the r.time scheme of the momentum+continuity model
  631. ComputeLeapfrog;
  632. %Compute all the tracers
  633. if r.tracer
  634. if r.timetr <= r.time
  635. [r.Tr, r.dttr] = ComputeTracer_FT(r.Tr, r.K);
  636. r.timetr = r.time + r.dttr;
  637. r.ltr = r.ltr + 1;
  638. end
  639. end
  640. %Numerics to compute the diagnostic variables
  641. ComputeDiagnostics(r, l);
  642. function ComputeLeapfrog(r)
  643. %Shallow-water equations solver
  644. %
  645. %T-cells
  646. r.dtmask;
  647. %r.u-cells
  648. r.dtmask_u;
  649. %r.v-cells
  650. r.dtmask_v;
  651. %% Solve the spatial schemes in the interior of the domain
  652. % For the water elevation
  653. RHSr.eta = ComputeContinuity(r.H, r.eta, r.u, r.v, r.mask);
  654. r.eta_new = r.eta_old + 2 * r.dt * RHSr.eta .* r.mask;
  655. r.H_new = r.eta_new + r.d;
  656. ind = find(r.H_new < 0);
  657. r.eta_new(ind) = -r.d;
  658. dtmask = (r.eta_new - r.eta_old) * .5 ./ RHSr.eta .* r.mask;
  659. %Must build the dtmask_u and dtmask_v in order to preserve momentum
  660. %too.
  661. dtmask_u = buildmask_U(dtmask,r.mask_u);
  662. dtmask_v = buildmask_V(dtmask',r.mask_v')';
  663. RHSr.eta = ComputeContinuity(r.H, r.eta, r.u, r.v, dtmask);
  664. % For the r.u and r.v components of velocity
  665. % % The old 10%-faster way (but a lot more error-prone)
  666. % [RHSu, RHSv] = ComputeUV2D_old;
  667. % Switch r.v <-> r.u; r.v_old <-> r.u_old; r.dy <-> r.dx and -1. <-> 1. (coriolis)
  668. % Transpose the matrices.
  669. RHSu = ComputeSpaceU_CS( r.H, r.H_old, r.eta, ...
  670. r.u, r.u_old, r.v, r.v_old, ...
  671. dtmask_u, r.dx, r.dy, 1.);
  672. RHSv = ComputeSpaceU_CS( r.H', r.H_old', r.eta', ...
  673. r.v', r.v_old', r.u', r.u_old', ...
  674. dtmask_v', r.dy, r.dx, -1.)';
  675. %% LEAPFROG r.time-SCHEME
  676. % Water level r.time scheme
  677. r.eta_new = r.eta_old + 2 * RHSr.eta .* r.mask;
  678. r.H_new = r.eta_new + r.d;
  679. %r.u and r.v r.time schemes inside the domain.
  680. %Leapfrog means that 2xdt is passed as teh r.time r.step.
  681. r.v_new = ComputeTimeU_FT(r.v_old', r.v_new', RHSv', r.H_old', r.H_new', r.mask_v', 2.)';
  682. r.u_new = ComputeTimeU_FT(r.u_old, r.u_new, RHSu, r.H_old, r.H_new, r.mask_u, 2.);
  683. %% r.time scheme at the northern/southern and eastern/southern OB (2 x r.d
  684. %% <- LeapFrog)
  685. %Southern and northern boundaries (along r.v -> transpose inputs)
  686. %(transposed inputs -> transposed outputs).
  687. [r.eta_new, r.H_new, r.v_new, r.u_new] = ComputeOB_U( ...
  688. r.eta_new', r.eta_old', r.H_new', r.H_old', r.d',...
  689. r.v_new', r.mask_v', ...
  690. r.u_new', r.u_old', r.mask_u', ...
  691. 2*r.dt, r.dy ...
  692. );
  693. %Eastern and western boundaries (along r.u)
  694. %The previous outputs were transposed, so we transpose
  695. %them back as inputs.
  696. [r.eta_new, r.H_new, r.u_new, r.v_new] = ComputeOB_U( ...
  697. r.eta_new', r.eta_old, r.H_new', r.H_old, r.d,...
  698. r.u_new', r.mask_u, ...
  699. r.v_new', r.v_old, r.mask_v, ...
  700. 2*r.dt, r.dx ...
  701. );
  702. %% Asselin-Robert filter
  703. r.eta = r.eta + r.gama * ( r.eta_old - 2 * r.eta + r.eta_new );
  704. r.u = r.u + r.gama * ( r.u_old - 2 * r.u + r.u_new );
  705. r.v = r.v + r.gama * ( r.v_old - 2 * r.v + r.v_new );
  706. %% Update matrices
  707. r.eta_old = r.eta;
  708. r.eta = r.eta_new;
  709. r.H_old = r.H;
  710. r.H = r.H_new;
  711. r.u_old = r.u;
  712. r.u = r.u_new;
  713. r.v_old = r.v;
  714. r.v = r.v_new;
  715. function RHSr.eta = ComputeContinuity(r.H, r.eta, r.u, r.v, r.mask)
  716. %function ComputeContinuity
  717. %Shallow-water equations solver
  718. % r.H;
  719. % r.eta;
  720. % r.u;
  721. % r.v;
  722. % r.mask;
  723. % rHSr.eta;
  724. r.dx;
  725. r.dy;
  726. [r.M,r.N] = size(r.eta);
  727. RHSr.eta = zeros(r.M,r.N);
  728. %Compute along r.u then along r.v
  729. RHSr.eta(2:r.M-1,2:r.N-1) = - ( ...
  730. ComputeContinuityU(r.H,r.u,r.mask,r.dx) + ComputeContinuityU(r.H',r.v',r.mask',r.dy)' ...
  731. );
  732. function RHS = ComputeContinuityU(r.H,r.u,r.mask,r.dx)
  733. [r.M,r.N] = size(r.H);
  734. RHS = ( ...
  735. r.mask(3:r.M,2:r.N-1) .* .5 ...
  736. .* ( r.H(3:r.M,2:r.N-1) + r.H(2:r.M-1,2:r.N-1) ) .* r.u(3:r.M,2:r.N-1) ... %i+1, i, i+1
  737. - r.mask(1:r.M-2,2:r.N-1) .* .5 ...
  738. .* ( r.H(2:r.M-1,2:r.N-1) + r.H(1:r.M-2,2:r.N-1) ) .* r.u(2:r.M-1,2:r.N-1) ... %i, i-1, i
  739. )/r.dx;
  740. function RHSu = ComputeSpaceU_CS( ...
  741. r.H, r.H_old, r.eta, ...
  742. r.u, r.u_old, r.v, r.v_old, ...
  743. r.mask_u, r.dx, r.dy, ...
  744. signcoriolis ...
  745. )
  746. %% function newu = ComputeSpaceU_CS
  747. %Shallow-water equations solver for the r.u component
  748. %of the flow Centred in Space (CS).
  749. %
  750. % Centred differences (CD) or Centred in Space (CS).
  751. %
  752. %NOTE: Any viscous and frictional term
  753. %must be evaluated in tindex(i-1,r.M)e l-1.
  754. %
  755. % switch r.v <-> r.u; j <-> i and r.dy <-> r.dx relative to ComputeU2D
  756. % switch r.v_old <-> r.u_old
  757. % take special care for the coriolis force term
  758. %% r.variables
  759. r.g;
  760. r.f;
  761. r.Nu;
  762. r.wind;
  763. r.bottom;
  764. r.pressure;
  765. r.coriolis;
  766. r.wall;
  767. r.uwind;
  768. r.vwind;
  769. rho0;
  770. rho_air;
  771. r.lb;
  772. r.karman;
  773. wall = false;
  774. %% r.u spatial scheme
  775. [r.M, r.N] = size(r.eta);
  776. RHSu = zeros(size(r.u));
  777. r.H_u = zeros(size(r.u));
  778. r.H_old_u = zeros(size(r.u));
  779. v_old_u = zeros(size(r.u));
  780. v_u = zeros(size(r.u));
  781. r.H_u(2:r.M,2:r.N-1) = twoaverage_u(r.H,r.M,r.N);
  782. r.H_old_u(2:r.M,2:r.N-1) = twoaverage_u(r.H_old,r.M,r.N);
  783. v_old_u(2:r.M,2:r.N-1) = fouraverage_u(r.v_old(:,2:r.N),r.M, r.N-2);
  784. v_u(2:r.M,2:r.N-1) = fouraverage_u(r.v(:,2:r.N),r.M, r.N-2);
  785. RHSu(2:r.M,2:r.N-1) = r.mask_u(2:r.M,2:r.N-1) .* ( ...
  786. ...%advection along r.u ...
  787. - 0.2500 / r.dx * ( ... %i-1, i
  788. r.mask_u(3:r.M+1,2:r.N-1) .* ( r.u(3:r.M+1,2:r.N-1) + r.u(2:r.M,2:r.N-1) ).^2 .* r.H(2:r.M,2:r.N-1) ... %i+1, i, i+1, i, i
  789. - r.mask_u(1:r.M-1,2:r.N-1) .* ( r.u(2:r.M,2:r.N-1) + r.u(1:r.M-1,2:r.N-1) ).^2 .* r.H(1:r.M-1,2:r.N-1) ... %i, i-1, i, i-1, i-1
  790. ) ...
  791. ...%advection along r.v
  792. - 0.0625 / r.dy * ( ... %i-1, i
  793. ( ...
  794. r.mask_u(2:r.M,3:r.N) .* ( r.H(2:r.M,3:r.N) + r.H(2:r.M,2:r.N-1) + r.H(1:r.M-1,3:r.N) + r.H(1:r.M-1,2:r.N-1) ) ... % j+1 ; j ; i-1,j+1 ; i-1
  795. .* ( r.v(2:r.M,3:r.N) + r.v(1:r.M-1,3:r.N) ) .* ( r.u(2:r.M,3:r.N) + r.u(2:r.M,2:r.N-1) ) ...% j+1 ; i-1,j+1 ; j+1 ; i
  796. - r.mask_u(2:r.M,1:r.N-2) .* ( r.H(2:r.M,2:r.N-1) + r.H(2:r.M,1:r.N-2) + r.H(1:r.M-1,2:r.N-1) + r.H(1:r.M-1,1:r.N-2) ) ... % i ; j-1 ; i-1 ; i-1,j-1
  797. .* ( r.v(2:r.M,2:r.N-1) + r.v(1:r.M-1,2:r.N-1) ) .* ( r.u(2:r.M,2:r.N-1) + r.u(2:r.M,1:r.N-2) ) ...% i ; i-1,j-1 ; i ; j-1
  798. ) ...
  799. ) ...
  800. ...%Coriolis Force (r.u -> +; r.v -> -)
  801. + coriolis * ( ...
  802. signcoriolis * f * v_u(2:r.M,2:r.N-1) .* r.H_u(2:r.M,2:r.N-1) ... % i ; i-1 .
  803. )...
  804. ...%Pressure gradient Force
  805. + pressure * ( ...
  806. - g * r.H_u(2:r.M,2:r.N-1) .* ( r.eta(2:r.M,2:r.N-1) - r.eta(1:r.M-1,2:r.N-1) ) / r.dx ...
  807. ... % i ; i-1 ; i ; i-1
  808. )...
  809. ...%Viscosity along r.u
  810. + ( ... % i ; i-1
  811. + Nu * r.mask_u(3:r.M+1,2:r.N-1) .* r.H_old(2:r.M,2:r.N-1) .* ( r.u_old(3:r.M+1,2:r.N-1) - r.u_old(2:r.M,2:r.N-1) ) / r.dx ... % i ; i+1 ; i ; i
  812. - Nu * r.mask_u(1:r.M-1,2:r.N-1) .* r.H_old(1:r.M-1,2:r.N-1) .* ( r.u_old(2:r.M,2:r.N-1) - r.u_old(1:r.M-1,2:r.N-1) ) / r.dx ... % i-1 ; i ; i-1; i-1
  813. ) / r.dx ... % i ; i-1
  814. ...%Viscosity along r.v
  815. + ( ... % i ; i-1 ; i ; i-1 .
  816. + Nu / r.dy * r.mask_u(2:r.M,3:r.N) .* r.H_old(2:r.M,2:r.N-1) .* ( r.u_old(2:r.M,3:r.N) - r.u_old(2:r.M,2:r.N-1) ) ... % (j;j+1;i-1,j+1;i-1);j+1 ; j
  817. - Nu / r.dy * r.mask_u(2:r.M,1:r.N-2) .* r.H_old(2:r.M,1:r.N-2) .* ( r.u_old(2:r.M,2:r.N-1) - r.u_old(2:r.M,1:r.N-2) ) ... % (j-1;j;i-1;i-1,j-1);j ; j-1
  818. ) / r.dy ...
  819. );
  820. %Add bottom stress. Look out, so that the bottom stress doesn't
  821. %reverts the direction of momentum ... This wouldn't be very realistic.
  822. if bottom || wall
  823. stress = zeros(size(RHSu(2:r.M,2:r.N-1)));
  824. if bottom
  825. stress = bottomstress( r.u_old(2:r.M,2:r.N-1), v_old_u(2:r.M,2:r.N-1), ...
  826. r.H_old_u(2:r.M,2:r.N-1), ...
  827. lb, karman );
  828. end
  829. if wall
  830. stress = stress + bottomstress(r.u_old(2:r.M,2:r.N-1), 0, r.dy, lb, karman) ...
  831. .* ( ...
  832. (1 - r.mask(1:r.M-1,3:r.N)) .* r.H_old(1:r.M-1,3:r.N) + ...
  833. (1 - r.mask(2:r.M,3:r.N)) .* r.H_old(2:r.M,3:r.N) + ...
  834. (1 - r.mask(1:r.M-1,1:r.N-2)) .* r.H_old(1:r.M-1,1:r.N-2) + ...
  835. (1 - r.mask(2:r.M,1:r.N-2)) .* r.H_old(2:r.M,1:r.N-2) ...
  836. ) * 0.5 / r.dy;
  837. end
  838. ind = find( (RHSu(2:r.M,2:r.N-1) - r.mask_u(2:r.M,2:r.N-1) .* stress) ./ RHSu(2:r.M,2:r.N-1) > 0 );
  839. RHSu(ind) = RHSu(ind) - r.mask_u(ind) .* stress(ind);
  840. ind = find( (RHSu(2:r.M,2:r.N-1) - r.mask_u(2:r.M,2:r.N-1) .* stress) ./ RHSu(2:r.M,2:r.N-1) <= 0 );
  841. RHSu(ind) = 0.;
  842. end
  843. %Add wind stress.
  844. if wind
  845. RHSu(2:r.M,2:r.N-1) = RHSu(2:r.M,2:r.N-1) ...
  846. + r.mask_u(2:r.M,2:r.N-1) .* windstress(...
  847. uwind * ones(size(r.u(2:r.M,2:r.N-1))), ...
  848. vwind * ones(size(r.u(2:r.M,2:r.N-1))), ...
  849. rho0, rho_air ...
  850. );
  851. end
  852. function r.u_new = ComputeTimeU_FT(r.u_old, r.u_new, RHSu, r.H_old, r.H_new, r.mask_u, r.dt)
  853. %function r.u_new = ComputeTimeU_FT(r.u_old, r.u_new, RHSu, r.H_old, r.H_new, r.mask_u, r.dt)
  854. %
  855. %Numerical solver with the Forward in r.time (FT) Euler r.time r.stepping method.
  856. %
  857. [r.M,r.N] = size(r.H_old);
  858. r.u_new(2:r.M,2:r.N-1) = r.mask_u(2:r.M,2:r.N-1) .* ( ...
  859. r.u_old(2:r.M,2:r.N-1) .* ( r.H_old(2:r.M,2:r.N-1) + r.H_old(1:r.M-1,2:r.N-1) ) ...
  860. + 2 * r.dt * RHSu(2:r.M,2:r.N-1) ...
  861. ) ...
  862. ./ ( r.H_new(2:r.M,2:r.N-1) + r.H_new(1:r.M-1,2:r.N-1) );
  863. function [r.eta_new, r.H_new, r.u_new, r.v_new] = ComputeOB_U( ...
  864. r.eta_new, r.eta_old, r.H_new, r.H_old, r.d,...
  865. r.u_new, r.mask_u, ...
  866. r.v_new, r.v_old, r.mask_v, ...
  867. r.dt, r.dx ...
  868. )
  869. %function computeOB
  870. %Solve the north, south, east and west boundary condition
  871. %for the r.eta, r.u and r.v variables.
  872. r.g;
  873. %BC conditions
  874. r.flather;
  875. r.neumann;
  876. radiatr.etan;
  877. radiatelevel;
  878. flather = 0;
  879. neumann = 0;
  880. radiatr.etan = 0;
  881. radiatelevel = 1;
  882. [r.M,r.N] = size(r.d);
  883. %% Eastern (1,:) and Western (r.M,:) boundaries
  884. if radiatelevel
  885. %Waterlevel: GW radiation
  886. r.eta_new(1:r.M-1:r.M,:) = r.mask_u(1:r.M:r.M+1,:) .* ( ...
  887. r.eta_old(1:r.M-1:r.M,:)- r.dt / r.dx .* sqrt( g * r.H_old(1:r.M-1:r.M,:) ) ...
  888. .* ( r.eta_old(1:r.M-1:r.M,:) - r.eta_old(2:r.M-3:r.M-1,:) ) ...
  889. );
  890. %no r.mask below, cuz r.H must yield -99 where r.land is.W
  891. r.H_new(1:r.M-1:r.M,:) = r.eta_new(1:r.M-1:r.M,:) + r.d(1:r.M-1:r.M,:);
  892. end
  893. if flather
  894. %Normal velocity: Flather
  895. r.u_new(1:r.M:r.M+1,:) = [-1 * ones(1,r.N); ones(1,r.N)] .* r.mask_u(1:r.M:r.M+1,:) ...
  896. .* sqrt( g ./ r.H_new(1:r.M-1:r.M,:) ) .* r.eta_new(1:r.M-1:r.M,:);
  897. elseif neumann
  898. %Normal velocity: Null-gradient
  899. r.u_new(1:r.M:r.M+1,1:r.N) = r.mask_u(1:r.M:r.M+1,1:r.N) .* r.u_new(2:r.M-2:r.M,1:r.N);
  900. end
  901. if radiatr.etan
  902. %Tangential velocity: GW radiation
  903. r.v_new(1:r.M-1:r.M,2:r.N) = r.mask_v(1:r.M-1:r.M,2:r.N) .* ...
  904. ( ...
  905. r.v_old(1:r.M-1:r.M,2:r.N) .* ( r.H_old(1:r.M-1:r.M,2:r.N) + r.H_old(1:r.M-1:r.M,1:r.N-1) ) ...
  906. - r.dt / r.dx .* sqrt( g * .5 * ( r.H_old(1:r.M-1:r.M,2:r.N) + r.H_old(1:r.M-1:r.M,1:r.N-1) ) ) ...
  907. .* ( r.v_old(1:r.M-1:r.M,2:r.N) - r.v_old( 2:r.M-3:r.M-1,2:r.N) ) ...
  908. ) ...
  909. ./ ( r.H_new(1:r.M-1:r.M,2:r.N) + r.H_new(1:r.M-1:r.M,1:r.N-1) );
  910. end
  911. function [r.Tr, r.dttr] = ComputeTracer_FT(r.Tr, K_L)
  912. %Advection-diffusion r.tracer equation solver
  913. %Explicit forward in r.time and upwind
  914. %
  915. r.dx;
  916. r.dy;
  917. r.dt;
  918. %T-cells
  919. r.H;
  920. r.H_new;
  921. r.mask;
  922. %r.u-cells
  923. r.u_a;
  924. r.mask_u;
  925. %r.v-cells
  926. r.v_a;
  927. r.mask_v;
  928. %% Solve the r.tracer spatial scheme in the whole of the domain
  929. RHSt = r.mask .* ( ...
  930. ComputeSpaceT_UP_U(r.H,r.u_a,r.mask_u, r.Tr, K_L, r.dx) ... %Along r.u
  931. + ComputeSpaceT_UP_U(r.H',r.v_a',r.mask_v',r.Tr',K_L,r.dy)' ... %then along r.v
  932. );
  933. %% FIND THE OPTIMAL r.tracer r.dt AS A MULTIPLE OF MOMENTUM r.dt
  934. % within the reasonable limit of maximum 100 * r.dt.
  935. minRHSt = min(min(RHSt));
  936. ind = find(RHSt == minRHSt);
  937. r.dttr = min( floor( abs(- r.H(ind) .* r.Tr(ind) ./ minRHSt) / r.dt ), 1000) ...
  938. * r.dt;
  939. %% r.tracer FORWARD-IN-r.time SCHEME
  940. Tr_new = r.mask .* (r.H .* r.Tr + r.dttr * RHSt) ./ r.H_new;
  941. %% Update matrices
  942. r.Tr = Tr_new;
  943. function RHSt = ComputeSpaceT_UP_U(r.H, r.u, r.mask_u, r.Tr, K_L, dx_L)
  944. %function RHSt = ComputeSpaceT_UP_U(r.H, r.u, r.mask_u, r.Tr, r.K, r.dx)
  945. %
  946. %UPWIND
  947. %
  948. r.nullgrad;
  949. nullgrad = false;
  950. [r.M,r.N]=size(r.H);
  951. Hm = zeros(r.M+1,r.N);
  952. TrUm = zeros(r.M+1,r.N);
  953. TrUp = zeros(r.M+1,r.N);
  954. TrDif = zeros(r.M+1,r.N);
  955. %Computing quantities for the interior of the domain
  956. TrUm(1:r.M,:) = .5 * (abs(r.u(1:r.M,:)) - r.u(1:r.M,:)) .* r.Tr;
  957. TrUp(2:r.M+1,:) = .5 * (abs(r.u(2:r.M+1,:)) + r.u(2:r.M+1,:)) .* r.Tr;
  958. TrDif(2:r.M,:) = r.Tr(1:r.M-1,:) - r.Tr(2:r.M,:);
  959. Hm(2:r.M,:) = .5 * ( r.H(1:r.M-1,:) + r.H(2:r.M,:) );
  960. %Computing the quantities for the boundaries
  961. if nullgrad %Considering null-gradient:
  962. TrUm(r.M+1,:) = .5 * (abs(r.u(r.M+1,:)) - r.u(r.M+1,:)) .* r.Tr(r.M,:);
  963. TrUp(1,:) = .5 * (abs(r.u(1,:)) + r.u(1,:)) .* r.Tr(1,:);
  964. TrDif(1:r.M:r.M+1,:) = 0.;
  965. else %else null value is considered
  966. TrUm(r.M+1,:) = .5 * (abs(r.u(r.M+1,:)) - r.u(r.M+1,:)) * 0.;
  967. TrUp(1,:) = .5 * (abs(r.u(1,:)) + r.u(1,:)) * 0.;
  968. TrDif(1,:) = - r.Tr(1,:);
  969. TrDif(r.M+1,:) = r.Tr(r.M,:);
  970. end
  971. %This algo considers that the bathymetry has always a null gradient
  972. %at the boundary:
  973. Hm(1:r.M:r.M+1,:) = r.H(1:r.M-1:r.M,:);
  974. %Computing the fluxes at each face of the r.M+1 faces
  975. FFluxU = ComputeFaceFluxT_UP(Hm, TrUp, TrUm, TrDif, dx_L, K_L);
  976. %The T-cell increment is the flux balance.
  977. RHSt = r.mask_u(1:r.M,:) .* FFluxU(1:r.M,:) ...
  978. - r.mask_u(2:r.M+1,:) .* FFluxU(2:r.M+1,:);
  979. function RHSt = ComputeFaceFluxT_UP(Hm, TrUp, TrUm, TrDif, dx_L, K_L)
  980. %function RHSt = ComputeFaceFluxT_UP(Hm, TrUp, TrUm, TrDif, dx_L, K_L)
  981. %Pure upwind scheme.
  982. RHSt = Hm .* ( ...
  983. TrUp - TrUm ...
  984. + K_L / dx_L * TrDif ...
  985. ) / dx_L;
  986. function av = fouraverage_u(r.v, r.M, r.N)
  987. %% function av = fouraverage_u(r.v, r.mask, r.M, r.N)
  988. av = .25 * ( ...
  989. r.v(2:r.M,1:r.N) + ...
  990. r.v(2:r.M,2:r.N+1) + ...
  991. r.v(1:r.M-1,1:r.N) + ...
  992. r.v(1:r.M-1,2:r.N+1) ...
  993. );
  994. function av = twoaverage_u( r.H, r.M, r.N)
  995. av = .5 * ( ...
  996. r.H(2:r.M,2:r.N-1) + r.H(1:r.M-1,2:r.N-1) ...
  997. );
  998. function tb_L = bottomstress( u_L, v_L, r.H_L, lb, karman)
  999. % Bottom stress
  1000. %function tb_L = bottomstress( u_L, v_L, r.H_L )
  1001. %
  1002. %r.H_L is the total depth height
  1003. cd_L = karman / log( ( 0.5 .* r.H_L + lb ) / lb ) ;
  1004. % Checked-out Blumberg and Mellor 1987
  1005. % Double-checked with Pietrzak 2002
  1006. cd_L = max(cd_L .* cd_L, 0.0025);
  1007. tb_L = cd_L .* sqrt ( u_L .* u_L + v_L .* v_L ) .* u_L;
  1008. function u_L = windstress(u_L, v_L, rho0, rho_air)
  1009. %% Wind stress
  1010. %function tv_L = windstress(v_L)
  1011. vmod_L = sqrt( u_L .* u_L + v_L .* v_L );
  1012. if vmod_L < 6.
  1013. Cd_L = -.26097 .* vmod_L + 2.4316;
  1014. else
  1015. Cd_L = .064986 .* vmod_L + .44053;
  1016. end
  1017. Cd_L = Cd_L * .001;
  1018. u_L = Cd_L .* rho_air / rho0 .* vmod_L .* u_L;
  1019. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1020. %% Here starts the diagnostics part
  1021. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1022. function diag = ComputeDiagnostics(l)
  1023. %function ComputeDiagnostics
  1024. %
  1025. %Computes global:
  1026. % r.volume (m3)
  1027. % kinetic energy (J)
  1028. % potential energy (J)
  1029. % total energy (J)
  1030. % vorticity (m2/s)
  1031. % enstrophy (J)
  1032. % squared normal strain (J)
  1033. % squared shear strain (J)
  1034. % squared strain (J)
  1035. % Okubo-Weiss
  1036. % momentum (r.M^3 * r.M / s)a
  1037. %
  1038. %Computes local:
  1039. % kinetic energy (J)
  1040. % potential energy (J)
  1041. % total energy (J)
  1042. % curl (1/s)
  1043. % divergence (1/s)
  1044. % stretch (normal strain) (1/s)
  1045. % shear (shear strain) (1/s)
  1046. % squared strain (1/s)
  1047. % enstrophy (1/s2)
  1048. % OkuboWeiss (1/s2)
  1049. %
  1050. r.u_a;
  1051. r.v_a;
  1052. r.u;
  1053. r.v;
  1054. r.u_t;
  1055. r.v_t;
  1056. r.H;
  1057. r.eta;
  1058. r.M;
  1059. r.N;
  1060. r.dx;
  1061. r.dy;
  1062. r.dt;
  1063. rho0;
  1064. r.g;
  1065. r.K;
  1066. r.mask;
  1067. r.ke;
  1068. r.pe;
  1069. r.strechrate_t;
  1070. r.shearrate_w;
  1071. r.divergence_t;
  1072. r.sqstrain_t;
  1073. r.sqstrechrate_t;
  1074. r.sqshearrate_w;
  1075. r.curl_w;
  1076. r.enstrophy_t;
  1077. r.enstrophy_w;
  1078. r.okuboweiss_t;
  1079. %Eddy kinetic energy
  1080. r.gradux;
  1081. r.graduy;
  1082. r.gradvx;
  1083. r.gradvy;
  1084. r.eke;
  1085. %r.time-dependent r.properties
  1086. r.time;
  1087. r.volume;
  1088. r.iKe;
  1089. r.iPe;
  1090. r.vtime;
  1091. r.iVort;
  1092. r.iEnst;
  1093. r.iSqStrech;
  1094. r.iSqShear;
  1095. r.iSqStrain;
  1096. r.iOWeiss;
  1097. r.iMomentumU;
  1098. r.iMomentumV;
  1099. r.iEke;
  1100. dA = r.dx * r.dy; %m2
  1101. %Computes the average velocity field
  1102. r.u_a = ((l - 1) * r.u_a + r.u ) / l;
  1103. r.v_a = ((l - 1) * r.v_a + r.v ) / l;
  1104. %Eddy kinetic energy
  1105. r.gradux = (r.u(2:r.M+1,:) - r.u(1:r.M,:)) / r.dx;
  1106. r.gradvy = (r.v(:,2:r.N+1) - r.v(:,1:r.N)) / r.dy;
  1107. r.graduy(2:r.M,2:r.N-2) = (r.u(2:r.M,3:r.N-1) - r.u(2:r.M,2:r.N-2)) / r.dy;
  1108. r.gradvx(2:r.M-2,2:r.N) = (r.v(3:r.M-1,2:r.N) - r.v(2:r.M-2,2:r.N)) / r.dx;
  1109. %Compute diagnostic fields
  1110. %Curl
  1111. computeCurl_w; % 1 / s
  1112. %Strain rate
  1113. r.strechrate_t = r.mask .* ((r.u(2:r.M+1,:) - r.u(1:r.M,:)) * r.dy ...
  1114. - (r.v(:,2:r.N+1) - r.v(:,1:r.N)) * r.dx) / dA; % 1 / s
  1115. computeShearRate_w % 1 / s
  1116. %Growth rate
  1117. r.divergence_t = r.mask .* ((r.u(2:r.M+1,1:r.N) - r.u(1:r.M,1:r.N)) * r.dy ...
  1118. + (r.v(1:r.M,2:r.N+1) - r.v(1:r.M,1:r.N)) * r.dx) / dA; % 1/ s
  1119. %Potential vorticity
  1120. computePotentialVorticity_w
  1121. %This is the so-called scalar of Arakawa-Okubo-Weiss.
  1122. %Computes the local enstrophy, squared strain rate and Okubo-Weiss
  1123. %parameter %Look for Weiss
  1124. %La Jolla Institute Report from 1981.
  1125. %Physica r.d: Nonlinear 1991.
  1126. %Look for Okubo-Weiss parameter/function
  1127. %Look for Arakawa 1966 paper.
  1128. r.enstrophy_w = .5 * ( r.curl_w.^2); %1 / s2
  1129. r.enstrophy_t = interpolFtoT(r.enstrophy_w, r.mask, r.M, r.N);
  1130. r.sqshearrate_w = .5 * r.shearrate_w.^2;
  1131. r.sqshearrate_t = interpolFtoT(r.sqshearrate_w, r.mask, r.M, r.N);
  1132. r.sqstrechrate_t = .5 * r.strechrate_t.^2 .* r.mask;
  1133. r.sqstrain_t = r.sqstrechrate_t + r.sqshearrate_t;
  1134. r.sqdivergence_t = .5 * r.divergence_t.^2 .* r.mask;
  1135. r.okuboweiss_w = (r.sqshearrate_w - r.enstrophy_w);
  1136. r.okuboweiss_t = interpolFtoT(r.okuboweiss_w, r.mask, r.M, r.N);
  1137. r.okuboweiss_t = r.okuboweiss_t + r.sqstrechrate_t .* r.mask;
  1138. %vers?o do Aires do escalar de Okubo-Weiss
  1139. r.okuboweiss_t = r.okuboweiss_t - r.sqdivergence_t;
  1140. %%interpolate from r.u and r.v to T cells
  1141. r.u_t = .5 * ( r.u(1:r.M,:) + r.u(2:r.M+1,:) );
  1142. r.v_t = .5 * ( r.v(:,1:r.N) + r.v(:,2:r.N+1) );
  1143. Hnoland = r.H;
  1144. Hnoland(find(r.H < -1)) = 0.;
  1145. %r.volume
  1146. %r.volume(l) = dA * sum(sum(Hnoland)); %m3
  1147. %Perturbed r.volume
  1148. r.volume(l) = dA * sum(sum(r.eta .* r.mask)); %m3
  1149. %Momentum (actually it's only the integrated velocity)
  1150. r.iMomentumU(l) = dA * sum(sum(r.u_t .* Hnoland,2)); % kg * r.M / s
  1151. r.iMomentumV(l) = dA * sum(sum(r.v_t .* Hnoland,1)); % kg * r.M / s
  1152. %Kinetic energy
  1153. r.ke = .5 * rho0 * dA * (r.u_t.^2 + r.v_t.^2) .* Hnoland .* r.mask; % kg * r.M * r.M / s2 = J
  1154. r.iKe(l) = sum(sum(r.ke)); % kg * r.M * r.M / s2 = J
  1155. %Potential energy
  1156. r.pe = .5 * rho0 * g * dA .* r.eta.^2 .* r.mask; %kg r.M * r.M / s2 = J
  1157. r.iPe(l) = sum(sum(r.pe)); %kg r.M * r.M / s2 = J
  1158. %Eddy kinetic energy
  1159. r.eke = r.eke + rho0 * dA * r.K * 2 * r.dt * (r.gradux.^2 + r.gradvy.^2 + r.graduy.^2 + r.gradvx.^2) ...
  1160. .* Hnoland .* r.mask;
  1161. r.iEke(l) = sum(sum(r.eke));
  1162. %r.vorticity
  1163. r.iVort(l) = sum(sum(r.curl_w)) * dA; % m2 / s
  1164. %r.enstrophy
  1165. r.iEnst(l) = sum(sum(r.enstrophy_w)) * dA; % m2 / s2
  1166. %r.squared strain
  1167. r.iSqShear(l) = sum(sum(r.sqshearrate_w))* dA;
  1168. r.iSqStrech(l) = sum(sum(r.sqstrechrate_t)) * dA;
  1169. r.iSqStrain(l) = sum(sum(r.sqstrain_t)) * dA;
  1170. %r.Okubo-Weiss
  1171. r.iOWeiss(l) = sum(sum(r.okuboweiss_t)) * dA; %<--- too large numerical error
  1172. %r.iOWeiss(l) = r.iSqStrain(l) - r.iEnst(l);
  1173. %r.time
  1174. r.vtime(l) = r.time;
  1175. diag = [...
  1176. r.volume(l), ...
  1177. r.iKe(l), ...
  1178. r.iPe(l), ...
  1179. r.iVort(l), ...
  1180. r.iEnst(l), ...
  1181. r.iSqStrain(l), ...
  1182. r.iOWeiss(l) ...
  1183. ];
  1184. function computeCurl_w
  1185. %function computeCurl_w % 1 / s
  1186. r.curl_w;
  1187. r.curl_t;
  1188. r.mask;
  1189. r.mask_v;
  1190. r.mask_u,
  1191. r.u;
  1192. r.v;
  1193. r.M;
  1194. r.N;
  1195. r.dy;
  1196. r.dx;
  1197. dA = r.dx .* r.dy;
  1198. %Curl of velocity in the interior...
  1199. r.curl_w(2:r.M,2:r.N) = ((r.mask_v(2:r.M,2:r.N) .* r.v(2:r.M,2:r.N) ...
  1200. - r.mask_v(1:r.M-1,2:r.N) .* r.v(1:r.M-1,2:r.N)) .* r.dy ...
  1201. - (r.mask_u(2:r.M,2:r.N) .* r.u(2:r.M,2:r.N) ...
  1202. - r.mask_u(2:r.M,1:r.N-1) .* r.u(2:r.M,1:r.N-1)) .* r.dx) ./ dA; % 1 / s
  1203. %... at the corners %Thank you for the conversation with F.L.!
  1204. %lower-left SW
  1205. r.curl_w(1,1) = ((r.mask_v(1,1) * r.v(1,1)) * r.dy ...
  1206. - (r.mask_u(1,1) * r.u(1,1)) * r.dx)/dA; % 1 / s
  1207. %lower-right SE
  1208. r.curl_w(1,r.N+1) = ((r.mask_v(1,r.N+1) * r.v(1,r.N+1)) * r.dy ...
  1209. - ( - r.mask_u(1,r.N) * r.u(1,r.N)) * r.dx)/dA; % 1 / s
  1210. %top-left NW
  1211. r.curl_w(r.M+1,1) = (( - r.mask_v(r.M,1) * r.v(r.M,1)) * r.dy ...
  1212. - (r.mask_u(r.M+1,1) * r.u(r.M+1,1)) * r.dx)/dA; % 1 / s
  1213. %top-right NE
  1214. r.curl_w(r.M+1,r.N+1) = ((- r.mask_v(r.M,r.N+1) * r.v(r.M,r.N+1)) * r.dy ...
  1215. - (- r.mask_u(r.M+1,r.N) * r.u(r.M+1,r.N)) * r.dx)/dA; % 1 / s
  1216. %... at the western boundary
  1217. r.curl_w(2:r.M,1) = ((r.mask_v(2:r.M,1) .* r.v(2:r.M,1) - r.mask_v(1:r.M-1,1) .* r.v(1:r.M-1,1)) * r.dy ...
  1218. - (r.mask_u(2:r.M,1) .* r.u(2:r.M,1)) * r.dx)/dA; % 1 / s
  1219. %... at the eastern boundary
  1220. r.curl_w(2:r.M,r.N+1) = ((r.mask_v(2:r.M,r.N+1) .* r.v(2:r.M,r.N+1) - r.mask_v(1:r.M-1,r.N+1) .* r.v(1:r.M-1,r.N+1)) * r.dy ...
  1221. - (- r.mask_u(2:r.M,r.N) .* r.u(2:r.M,r.N)) * r.dx)/dA; % 1 / s
  1222. %... at the southern boundary
  1223. r.curl_w(1,2:r.N) = ((r.mask_v(1,2:r.N) .* r.v(1,2:r.N)) * r.dy ...
  1224. - (r.mask_u(1,2:r.N) .* r.u(1,2:r.N) - r.mask_u(1,1:r.N-1) .* r.u(1,1:r.N-1)) * r.dx)/dA; % 1 / s
  1225. %... at the northern boundary
  1226. r.curl_w(r.M+1,2:r.N) = ((- r.mask_v(r.M,2:r.N) .* r.v(r.M,2:r.N)) * r.dy ...
  1227. - (r.mask_u(r.M+1,2:r.N) .* r.u(r.M+1,2:r.N) - r.mask_u(r.M+1,1:r.N-1) .* r.u(r.M+1,1:r.N-1)) * r.dx)/dA; % 1 / s
  1228. % interpolation from the {Z,W,F}-cell to the T-Cell
  1229. r.curl_t = interpolFtoT(r.curl_w, r.mask, r.M, r.N);
  1230. function computeShearRate_w
  1231. %function computeShearRate_w 1 / s
  1232. %
  1233. r.shearrate_w;
  1234. r.shearrate_t;
  1235. r.mask;
  1236. r.u;
  1237. r.v;
  1238. r.M;
  1239. r.N;
  1240. r.dy;
  1241. r.dx;
  1242. dA = r.dx * r.dy;
  1243. %Curl of (-r.u,r.v,0)
  1244. %interior of the domain...
  1245. r.shearrate_w(2:r.M,2:r.N) = ((r.v(2:r.M,2:r.N) - r.v(1:r.M-1,2:r.N)) * r.dy ...
  1246. + (r.u(2:r.M,2:r.N) - r.u(2:r.M,1:r.N-1)) * r.dx) / dA;
  1247. %bottom-left corner (SW)
  1248. r.shearrate_w(1,1) = ((r.v(1,1)) * r.dy ...
  1249. + (r.u(1,1)) * r.dx) / dA;
  1250. %bottom-right corner (SE)
  1251. r.shearrate_w(1,r.N+1) = ((r.v(1,r.N+1)) * r.dy ...
  1252. + (- r.u(1,r.N)) * r.dx) / dA;
  1253. %top-left corner (NW)
  1254. r.shearrate_w(r.M+1,1) = ((- r.v(r.M,1)) * r.dy ...
  1255. + (r.u(r.M+1,1)) * r.dx) / dA;
  1256. %top-right corner (NE)
  1257. r.shearrate_w(r.M+1,r.N+1) = ((- r.v(r.M,r.N+1)) * r.dy ...
  1258. + (- r.u(r.M+1,r.N)) * r.dx) / dA;
  1259. %western boundary
  1260. r.shearrate_w(2:r.M,1) = ((r.v(2:r.M,1) - r.v(1:r.M-1,1)) * r.dy ...
  1261. + (r.u(2:r.M,1)) * r.dx) / dA;
  1262. %eastern boundary
  1263. r.shearrate_w(2:r.M,r.N+1) = ((r.v(2:r.M,r.N+1) - r.v(1:r.M-1,r.N)) * r.dy ...
  1264. + (- r.u(2:r.M,r.N)) * r.dx) / dA;
  1265. %southern boundary
  1266. r.shearrate_w(1,2:r.N) = ((r.v(1,2:r.N)) * r.dy ...
  1267. + (r.u(1,2:r.N) - r.u(1,1:r.N-1)) * r.dx) / dA;
  1268. %northern boundary
  1269. r.shearrate_w(r.M+1,2:r.N) = ((- r.v(r.M,2:r.N)) * r.dy ...
  1270. + (r.u(r.M+1,2:r.N) - r.u(r.M+1,1:r.N-1)) * r.dx) / dA;
  1271. % interpolate from F-cell to a T-cell
  1272. r.shearrate_t = interpolFtoT(r.shearrate_w, r.mask, r.M, r.N);
  1273. function computePotentialVorticity_w
  1274. %function computePotentialVorticity_w % 1 / s / r.M
  1275. %
  1276. r.potvorticity_t;
  1277. r.mask;
  1278. r.curl_w;
  1279. r.potvorticity_w;
  1280. r.coriolis;
  1281. r.f;
  1282. r.H;
  1283. r.M;
  1284. r.N;
  1285. %Adding coriolis
  1286. if coriolis
  1287. r.potvorticity_w = r.curl_w + f; % ??? r.curl_w * dA + f???
  1288. end
  1289. %potential vorticity
  1290. %within the domain...
  1291. r.potvorticity_w(2:r.M,2:r.N) = r.potvorticity_w(2:r.M,2:r.N) * 4. ./ ...
  1292. (r.H(2:r.M,2:r.N) + r.H(1:r.M-1,2:r.N) + r.H(1:r.M-1,1:r.N-1) + r.H(2:r.M,1:r.N-1));
  1293. %bottom-left corner (SW)
  1294. r.potvorticity_w(1,1) = r.potvorticity_w(1,1) / ...
  1295. (r.H(1,1));
  1296. %bottom-right corner (SE)
  1297. r.potvorticity_w(1,r.N+1) = r.potvorticity_w(1,r.N+1)/ ...
  1298. (r.H(1,r.N));
  1299. %top-left corner (NW)
  1300. r.potvorticity_w(r.M+1,1) = r.potvorticity_w(r.M+1,1) / ...
  1301. (r.H(r.M,1));
  1302. %top-right corner (NE)
  1303. r.potvorticity_w(r.M+1,r.N+1) = r.potvorticity_w(r.M+1,r.N+1) / ...
  1304. (r.H(r.M,1));
  1305. %western boundary
  1306. r.potvorticity_w(2:r.M,1) = r.potvorticity_w(2:r.M,1) * 2. ./ ...
  1307. (r.H(2:r.M,1) + r.H(1:r.M-1,1));
  1308. %eastern boundary
  1309. r.potvorticity_w(2:r.M,r.N+1) = r.potvorticity_w(2:r.M,r.N+1) * 2. ./ ...
  1310. (r.H(1:r.M-1,r.N) + r.H(2:r.M,r.N));
  1311. %southern boundary
  1312. r.potvorticity_w(1,2:r.N) = r.potvorticity_w(1,2:r.N) * 2. ./ ...
  1313. (r.H(1,2:r.N) + r.H(1,1:r.N-1));
  1314. %northern boundary
  1315. r.potvorticity_w(r.M+1,2:r.N) = r.potvorticity_w(r.M+1,2:r.N) * 2. ./ ...
  1316. (r.H(r.M,2:r.N) + r.H(r.M,1:r.N-1));
  1317. %interpolate from an F-cell to a T-cell
  1318. r.potvorticity_t = interpolFtoT( r.potvorticity_w, r.mask, r.M, r.N);
  1319. function tgrid = interpolFtoT(fgrid, r.mask, r.M, r.N)
  1320. %% function tgrid = interpolFtoT(fgrid, r.mask, r.M, r.N)
  1321. tgrid = .25 * r.mask .* ( ...
  1322. fgrid(1:r.M,1:r.N) ...
  1323. + fgrid(2:r.M+1,1:r.N) ...
  1324. + fgrid(2:r.M+1,2:r.N+1) ...
  1325. + fgrid(1:r.M,2:r.N+1) ...
  1326. );
  1327. %--------------------------------------------------------------------------
  1328. %SHEL SHallow-water numerical modEL
  1329. %Copyright (C) 2006,2009,2010,2011. Guillaume Riflet,
  1330. %Instituto Superior T?cnico da Universidade T?cnica de Lisboa.
  1331. %--------------------------------------------------------------------------