MOM6
shelf_triangular_FEstuff.F90
Go to the documentation of this file.
2 
4 use mom_grid, only : ocean_grid_type
5 use mom_time_manager, only : time_type, set_time, time_type_to_real
7 use mom_eos, only : eos_type
9 
10 implicit none ; private
11 
12 #include <MOM_memory.h>
13 type, public :: ice_shelf_cs ; private
14  type(mom_restart_cs), pointer :: restart_csp => null()
15  type(ocean_grid_type) :: grid ! A structure containing metrics, etc.
16  ! The rest is private
17  character(len=128) :: restart_output_dir = ' '
18  real, pointer, dimension(:,:) :: &
19  mass_shelf => null(), & ! The mass per unit area of the ice shelf or sheet, in kg m-2.
20  area_shelf_h => null(), & ! The area per cell covered by the ice shelf, in m2.
21 
22  t_flux => null(), & ! The UPWARD sensible ocean heat flux at the ocean-ice
23  ! interface, in W m-2.
24  salt_flux => null(), & ! The downward salt flux at the ocean-ice interface, in kg m-2 s-1.
25  lprec => null(), & ! The downward liquid water flux at the ocean-ice interface,
26  ! in kg m-2 s-1.
27  ! Perhaps these diagnostics should only be kept with the call?
28  exch_vel_t => null(), &
29  exch_vel_s => null(), &
30  tfreeze => null(), & ! The freezing point potential temperature an the ice-ocean
31  ! interface, in deg C.
32  tflux_shelf => null(), & ! The UPWARD diffusive heat flux in the ice shelf at the
33  ! ice-ocean interface, in W m-2.
34 !!! DNG !!!
35  u_shelf => null(), & ! the zonal (?) velocity of the ice shelf/sheet... in meters per second???
36  ! on q-points (B grid)
37  v_shelf => null(), & ! the meridional velocity of the ice shelf/sheet... m/s ??
38  ! on q-points (B grid)
39  h_shelf => null(), & ! the thickness of the shelf in m... redundant with mass
40  ! but may make code more readable
41  hmask => null(),& ! used to indicate ice-covered cells, as well as partially-covered
42  ! 1: fully covered, solve for velocity here
43  ! (for now all ice-covered cells are treated the same, this may change)
44  ! 2: partially covered, do not solve for velocity
45  ! 0: no ice in cell.
46  ! 3: bdry condition on thickness set - not in computational domain
47  ! -2 : default (out of computational boundary, and not = 3
48 
49  ! NOTE: hmask will change over time and NEEDS TO BE MAINTAINED
50  ! otherwise the wrong nodes will be included in velocity calcs.
51  u_face_mask => null(), v_face_mask => null(), &
52  ! masks for velocity boundary conditions - on *C GRID* - this is because the FEM solution
53  ! cares about FACES THAT GET INTEGRATED OVER, not vertices
54  ! Will represent boundary conditions on computational boundary (or permanent boundary
55  ! between fast-moving and near-stagnant ice
56  ! FOR NOW: 1=interior bdry, 0=no-flow boundary, 2=stress bdry condition, 3=inhomogeneous dirichlet boundary
57  umask => null(), vmask => null(), &
58  ! masks on the actual degrees of freedom (B grid) -
59  ! 1=normal node, 3=inhomogeneous boundary node, 0 - no flow node (will also get ice-free nodes)
60  ice_visc_bilinear => null(), &
61  ice_visc_lower_tri => null(), &
62  ice_visc_upper_tri => null(), &
63  thickness_boundary_values => null(), &
64  u_boundary_values => null(), &
65  v_boundary_values => null(), &
66 
67 
68  taub_beta_eff_bilinear => null(), & ! nonlinear part of "linearized" basal stress - exact form depends on basal law exponent
69  ! and/or whether flow is "hybridized" a la Goldberg 2011
70  taub_beta_eff_lower_tri => null(), &
71  taub_beta_eff_upper_tri => null(), &
72 
73  od_rt => null(), float_frac_rt => null(), &
74  od_av => null(), float_frac => null() !! two arrays that represent averages of ocean values that are maintained
75  !! within the ice shelf module and updated based on the "ocean state".
76  !! OD_av is ocean depth, and float_frac is the average amount of time
77  !! a cell is "exposed", i.e. the column thickness is below a threshold.
78  !! both are averaged over the time of a diagnostic (ice velocity)
79 
80  !! [if float_frac = 1 ==> grounded; obv. counterintuitive; might fix]
81 
82  real :: ustar_bg ! A minimum value for ustar under ice shelves, in m s-1.
83  real :: cp ! The heat capacity of sea water, in J kg-1 K-1.
84  real :: cp_ice ! The heat capacity of fresh ice, in J kg-1 K-1.
85  real :: gamma_t ! The (fixed) turbulent exchange velocity in the
86  ! 2-equation formulation, in m s-1.
87  real :: salin_ice ! The salinity of shelf ice, in PSU.
88  real :: temp_ice ! The core temperature of shelf ice, in C.
89  real :: kv_ice ! The viscosity of ice, in m2 s-1.
90  real :: density_ice ! A typical density of ice, in kg m-3.
91  real :: kv_molec ! The molecular kinematic viscosity of sea water, m2 s-1.
92  real :: kd_molec_salt ! The molecular diffusivity of salt, in m2 s-1.
93  real :: kd_molec_temp ! The molecular diffusivity of heat, in m2 s-1.
94  real :: lat_fusion ! The latent heat of fusion, in J kg-1.
95 
96 !!!! PHYSICAL AND NUMERICAL PARAMETERS FOR ICE DYNAMICS !!!!!!
97 
98  real :: time_step ! this is the shortest timestep that the ice shelf sees, and
99  ! is equal to the forcing timestep (it is passed in when the shelf
100  ! is initialized - so need to reorganize MOM driver.
101  ! it will be the prognistic timestep ... maybe.
102 
103 !!! all need to be initialized
104 
105  real :: a_glen_isothermal
106  real :: n_glen
107  real :: eps_glen_min
108  real :: c_basal_friction
109  real :: n_basal_friction
110  real :: density_ocean_avg ! this does not affect ocean circulation OR thermodynamics
111  ! it is to estimate the gravitational driving force at the shelf front
112  ! (until we think of a better way to do it- but any difference will be negligible)
113  real :: thresh_float_col_depth ! the water column depth over which the shelf if considered to be floating
114  real :: input_flux
115  real :: input_thickness
116 
117  real :: len_lat ! this really should be a Grid or Domain field
118 
119 
120  real :: velocity_update_time_step ! the time to update the velocity through the nonlinear
121  ! elliptic equation. i think this should be done no more often than
122  ! ~ once a day (maybe longer) because it will depend on ocean values
123  ! that are averaged over this time interval, and the solve will begin
124  ! to lose meaning if it is done too frequently
125  integer :: velocity_update_sub_counter ! there is no outer loop for the velocity solve; the counter will have to be stored
126  integer :: velocity_update_counter ! the "outer" timestep number
127  integer :: nstep_velocity ! ~ (velocity_update_time_step / time_step)
128 
129  real :: cg_tolerance, nonlinear_tolerance
130  integer :: cg_max_iterations
131  integer :: nonlin_solve_err_mode ! 1: exit vel solve based on nonlin residual
132  ! 2: exit based on "fixed point" metric (|u - u_last| / |u| < tol where | | is infty-norm
133  real :: cfl_factor ! in uncoupled run, how to limit subcycled advective timestep
134  ! i.e. dt = CFL_factor * min (dx / u)
135 
136 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
137 
138  type(time_type) :: time ! The component's time.
139  type(eos_type), pointer :: eqn_of_state => null() ! Type that indicates the
140  ! equation of state to use.
141  logical :: isshelf ! True if a shelf model is to be used.
142  logical :: shelf_mass_is_dynamic ! True if the ice shelf mass changes with
143  ! time.
144  logical :: override_shelf_movement ! If true, user code specifies the shelf
145  ! movement instead of using the dynamic ice-shelf mode.
146  logical :: isthermo ! True if the ice shelf can exchange heat and mass with
147  ! the underlying ocean.
148  logical :: threeeq ! If true, the 3 equation consistency equations are
149  ! used to calculate the flux at the ocean-ice interface.
150  integer :: id_melt = -1, id_exch_vel_s = -1, id_exch_vel_t = -1, &
151  id_tfreeze = -1, id_tfl_shelf = -1, &
152  id_u_shelf = -1, id_v_shelf = -1, id_h_shelf = -1, id_h_mask = -1, &
153  id_u_mask = -1, id_v_mask = -1, &
154  id_surf_elev = -1, id_bathym = -1, id_float_frac = -1, id_col_thick = -1, &
155  id_area_shelf_h = -1, id_od_rt = -1, id_float_frac_rt = -1
156  type(diag_ctrl) :: diag ! A structure that is used to control diagnostic
157  ! output.
158  type(user_ice_shelf_cs), pointer :: user_cs => null()
159 
160  logical :: write_output_to_file ! this is for seeing arrays w/out netcdf capability
161 end type ice_shelf_cs
162 contains
163 
164 subroutine matrix_diagonal_triangle (CS, u_diagonal, v_diagonal)
166  type(ice_shelf_cs), pointer :: CS
167  real, dimension (:,:), intent(inout) :: u_diagonal, v_diagonal
168 
169 ! returns the diagonal entries of the matrix for a Jacobi preconditioning
170 
171  real, pointer, dimension (:,:) :: umask, vmask, &
172  nu_lower, nu_upper, beta_lower, beta_upper, hmask
173  type(ocean_grid_type), pointer :: G
174  integer :: i, j, is, js, cnt, isc, jsc, iec, jec
175  real :: A, n, ux, uy, vx, vy, eps_min, domain_width, dxh, dyh, dxdyh
176 
177  g => cs%grid
178 
179 ! if (G%symmetric) then
180 ! isym=1
181 ! else
182 ! isym=0
183 ! endif
184 
185 
186  isc = g%isc ; jsc = g%jsc ; iec = g%iec ; jec = g%jec
187 
188  umask => cs%umask ; vmask => cs%vmask ; hmask => cs%hmask
189  nu_lower => cs%ice_visc_lower_tri ; nu_upper => cs%ice_visc_upper_tri
190  beta_lower => cs%taub_beta_eff_lower_tri ; beta_upper => cs%taub_beta_eff_upper_tri
191 
192  do i=isc-1,iec+1 ; do j=jsc-1,jec+1 ; if (hmask(i,j) .eq. 1) then
193  dxh = g%dxT(i,j)
194  dyh = g%dyT(i,j)
195  dxdyh = g%areaT(i,j)
196 
197  if (umask(i,j-1) .eq. 1) then ! this (bot right) is a degree of freedom node
198 
199  ux = 1./dxh ; uy = 0./dyh
200  vx = 0. ; vy = 0.
201 
202  u_diagonal(i,j-1) = u_diagonal(i,j-1) + &
203  .5 * dxdyh * nu_lower(i,j) * ((4*ux+2*vy) * (1./dxh) + (uy+vy) * (0./dyh))
204 
205  u_diagonal(i,j-1) = u_diagonal(i,j-1) + &
206  beta_lower(i,j) * dxdyh * 1./24
207 
208  ux = 0. ; uy = 0.
209  vx = 1./dxh ; vy = 0./dyh
210 
211  v_diagonal(i,j-1) = v_diagonal(i,j-1) + &
212  .5 * dxdyh * nu_lower(i,j) * ((uy+vx) * (1./dxh) + (4*vy+2*ux) * (0./dyh))
213 
214  v_diagonal(i,j-1) = v_diagonal(i,j-1) + &
215  beta_lower(i,j) * dxdyh * 1./24
216 
217  ux = 0./dxh ; uy = -1./dyh
218  vx = 0. ; vy = 0.
219 
220  u_diagonal(i,j-1) = u_diagonal(i,j-1) + &
221  .5 * dxdyh * nu_upper(i,j) * ((4*ux+2*vy) * (0./dxh) + (uy+vy) * (-1./dyh))
222 
223  u_diagonal(i,j-1) = u_diagonal(i,j-1) + &
224  beta_upper(i,j) * dxdyh * 1./24
225 
226  vx = 0./dxh ; vy = -1./dyh
227  ux = 0. ; uy = 0.
228 
229  v_diagonal(i,j-1) = v_diagonal(i,j-1) + &
230  .5 * dxdyh * nu_upper(i,j) * ((uy+vx) * (0./dxh) + (4*vy+2*ux) * (-1./dyh))
231 
232  v_diagonal(i,j-1) = v_diagonal(i,j-1) + &
233  beta_upper(i,j) * dxdyh * 1./24
234 
235  endif
236 
237  if (umask(i-1,j) .eq. 1) then ! this (top left) is a degree of freedom node
238 
239  ux = 0./dxh ; uy = 1./dyh
240  vx = 0. ; vy = 0.
241 
242  u_diagonal(i-1,j) = u_diagonal(i-1,j) + &
243  .5 * dxdyh * nu_lower(i,j) * ((4*ux+2*vy) * (0./dxh) + (uy+vy) * (1./dyh))
244 
245  u_diagonal(i,j-1) = u_diagonal(i,j-1) + &
246  beta_lower(i,j) * dxdyh * 1./24
247 
248  ux = 0. ; uy = 0.
249  vx = 0./dxh ; vy = 1./dyh
250 
251  v_diagonal(i-1,j) = v_diagonal(i-1,j) + &
252  .5 * dxdyh * nu_lower(i,j) * ((uy+vx) * (0./dxh) + (4*vy+2*ux) * (1./dyh))
253 
254  v_diagonal(i,j-1) = v_diagonal(i,j-1) + &
255  beta_lower(i,j) * dxdyh * 1./24
256 
257  ux = -1./dxh ; uy = 0./dyh
258  vx = 0. ; vy = 0.
259 
260  u_diagonal(i-1,j) = u_diagonal(i-1,j) + &
261  .5 * dxdyh * nu_upper(i,j) * ((4*ux+2*vy) * (-1./dxh) + (uy+vy) * (0./dyh))
262 
263  u_diagonal(i,j-1) = u_diagonal(i,j-1) + &
264  beta_upper(i,j) * dxdyh * 1./24
265 
266  vx = -1./dxh ; vy = 0./dyh
267  ux = 0. ; uy = 0.
268 
269  v_diagonal(i-1,j) = v_diagonal(i-1,j) + &
270  .5 * dxdyh * nu_upper(i,j) * ((uy+vx) * (-1./dxh) + (4*vy+2*ux) * (0./dyh))
271 
272  v_diagonal(i,j-1) = v_diagonal(i,j-1) + &
273  beta_upper(i,j) * dxdyh * 1./24
274 
275  endif
276 
277  if (umask(i-1,j-1) .eq. 1) then ! this (bot left) is a degree of freedom node
278 
279  ux = -1./dxh ; uy = -1./dyh
280  vx = 0. ; vy = 0.
281 
282  u_diagonal(i-1,j-1) = u_diagonal(i-1,j-1) + &
283  .5 * dxdyh * nu_upper(i,j) * ((4*ux+2*vy) * (-1./dxh) + (uy+vy) * (-1./dyh))
284 
285  u_diagonal(i-1,j-1) = u_diagonal(i-1,j-1) + &
286  beta_lower(i,j) * dxdyh * 1./24
287 
288  vx = -1./dxh ; vy = -1./dyh
289  ux = 0. ; uy = 0.
290 
291  v_diagonal(i-1,j-1) = v_diagonal(i-1,j-1) + &
292  .5 * dxdyh * nu_upper(i,j) * ((uy+vx) * (-1./dxh) + (4*vy+2*ux) * (-1./dyh))
293 
294  v_diagonal(i-1,j-1) = v_diagonal(i-1,j-1) + &
295  beta_lower(i,j) * dxdyh * 1./24
296  endif
297 
298  if (umask(i,j) .eq. 1) then ! this (top right) is a degree of freedom node
299 
300  ux = 1./ dxh ; uy = 1./dyh
301  vx = 0. ; vy = 0.
302 
303  u_diagonal(i,j) = u_diagonal(i,j) + &
304  .5 * dxdyh * nu_upper(i,j) * ((4*ux+2*vy) * (1./dxh) + (uy+vy) * (1./dyh))
305 
306  u_diagonal(i,j) = u_diagonal(i,j) + &
307  beta_upper(i,j) * dxdyh * 1./24
308 
309  vx = 1./ dxh ; vy = 1./dyh
310  ux = 0. ; uy = 0.
311 
312  v_diagonal(i,j) = v_diagonal(i,j) + &
313  .5 * dxdyh * nu_upper(i,j) * ((uy+vx) * (1./dxh) + (4*vy+2*ux) * (1./dyh))
314 
315  v_diagonal(i,j) = v_diagonal(i,j) + &
316  beta_upper(i,j) * dxdyh * 1./24
317 
318  endif
319  endif ; enddo ; enddo
320 
321 end subroutine matrix_diagonal_triangle
322 
323 !~ subroutine apply_boundary_values_triangle (CS, time, u_boundary_contr, v_boundary_contr)
324 
325  !~ type(time_type), intent(in) :: Time
326  !~ type(ice_shelf_CS), pointer :: CS
327  !~ real, dimension (:,:), intent(inout) :: u_boundary_contr, v_boundary_contr
328 
329 !~ ! this will be a per-setup function. the boundary values of thickness and velocity
330 !~ ! (and possibly other variables) will be updated in this function
331 
332  !~ real, pointer, dimension (:,:) :: u_boundary_values, &
333  !~ v_boundary_values, &
334  !~ umask, vmask, hmask, &
335  !~ nu_lower, nu_upper, beta_lower, beta_upper
336  !~ type(ocean_grid_type), pointer :: G
337  !~ integer :: 0, i, j, cnt, isc, jsc, iec, jec
338  !~ real :: A, n, ux, uy, vx, vy, eps_min, domain_width, dxh, dyh, dxdyh
339 
340  !~ G => CS%grid
341 
342 !~ ! if (G%symmetric) then
343 !~ ! isym=1
344 !~ ! else
345 !~ ! isym=0
346 !~ ! endif
347 
348 
349 
350  !~ isc = G%isc ; jsc = G%jsc ; iec = G%iec ; jec = G%jec
351 
352  !~ u_boundary_values => CS%u_boundary_values
353  !~ v_boundary_values => CS%v_boundary_values
354  !~ umask => CS%umask ; vmask => CS%vmask ; hmask => CS%hmask
355  !~ nu_lower => CS%ice_visc_lower_tri ; nu_upper => CS%ice_visc_upper_tri
356  !~ beta_lower => CS%taub_beta_eff_lower_tri ; beta_upper => CS%taub_beta_eff_upper_tri
357 
358  !~ domain_width = CS%len_lat
359 
360  !~ do i=isc-1,iec+1 ; do j=jsc-1,jec+1 ; if (hmask(i,j) .eq. 1) then
361 
362  !~ if ((umask(i-1,j-1) .eq. 3) .OR. (umask(i,j-1) .eq. 3) .OR. (umask(i-1,j) .eq. 3)) then
363 
364  !~ dxh = G%dxh(i,j)
365  !~ dyh = G%dyh(i,j)
366  !~ dxdyh = G%dxdyh(i,j)
367 
368  !~ ux = (u_boundary_values(i,j-1)-u_boundary_values(i-1,j-1))/dxh
369  !~ vx = (v_boundary_values(i,j-1)-v_boundary_values(i-1,j-1))/dxh
370  !~ uy = (u_boundary_values(i-1,j)-u_boundary_values(i-1,j-1))/dyh
371  !~ vy = (v_boundary_values(i-1,j)-v_boundary_values(i-1,j-1))/dyh
372 
373  !~ if (umask (i,j-1) .eq. 1) then ! this (bot right) is a degree of freedom node
374 
375  !~ u_boundary_contr (i,j-1) = u_boundary_contr (i,j-1) + &
376  !~ .5 * dxdyh * nu_lower (i,j) * ((4*ux+2*vy) * (1./dxh) + (uy+vy) * (0./dyh))
377 
378  !~ v_boundary_contr (i,j-1) = v_boundary_contr (i,j-1) + &
379  !~ .5 * dxdyh * nu_lower (i,j) * ((uy+vx) * (1./dxh) + (4*vy+2*ux) * (0./dyh))
380 
381  !~ u_boundary_contr (i,j-1) = u_boundary_contr (i,j-1) + &
382  !~ beta_lower(i,j) * dxdyh * 1./24 * (u_boundary_values(i-1,j-1) + &
383  !~ u_boundary_values(i-1,j) + u_boundary_values(i,j-1))
384 
385  !~ v_boundary_contr (i,j-1) = v_boundary_contr (i,j-1) + &
386  !~ beta_lower(i,j) * dxdyh * 1./24 * (v_boundary_values(i-1,j-1) + &
387  !~ v_boundary_values(i-1,j) + v_boundary_values(i,j-1))
388  !~ endif
389 
390  !~ if (umask (i-1,j) .eq. 1) then ! this (top left) is a degree of freedom node
391 
392  !~ u_boundary_contr (i-1,j) = u_boundary_contr (i-1,j) + &
393  !~ .5 * dxdyh * nu_lower (i,j) * ((4*ux+2*vy) * (0./dxh) + (uy+vy) * (1./dyh))
394 
395  !~ v_boundary_contr (i-1,j) = v_boundary_contr (i-1,j) + &
396  !~ .5 * dxdyh * nu_lower (i,j) * ((uy+vx) * (0./dxh) + (4*vy+2*ux) * (1./dyh))
397 
398  !~ u_boundary_contr (i,j-1) = u_boundary_contr (i,j-1) + &
399  !~ beta_lower(i,j) * dxdyh * 1./24 * (u_boundary_values(i-1,j-1) + &
400  !~ u_boundary_values(i-1,j) + u_boundary_values(i,j-1))
401 
402  !~ v_boundary_contr (i,j-1) = v_boundary_contr (i,j-1) + &
403  !~ beta_lower(i,j) * dxdyh * 1./24 * (v_boundary_values(i-1,j-1) + &
404  !~ v_boundary_values(i-1,j) + v_boundary_values(i,j-1))
405  !~ endif
406 
407  !~ if (umask (i-1,j-1) .eq. 1) then ! this (bot left) is a degree of freedom node
408 
409  !~ u_boundary_contr (i-1,j-1) = u_boundary_contr (i-1,j-1) + &
410  !~ .5 * dxdyh * nu_upper (i,j) * ((4*ux+2*vy) * (-1./dxh) + (uy+vy) * (-1./dyh))
411 
412  !~ v_boundary_contr (i-1,j-1) = v_boundary_contr (i-1,j-1) + &
413  !~ .5 * dxdyh * nu_upper (i,j) * ((uy+vx) * (-1./dxh) + (4*vy+2*ux) * (-1./dyh))
414 
415  !~ u_boundary_contr (i-1,j-1) = u_boundary_contr (i-1,j-1) + &
416  !~ beta_lower(i,j) * dxdyh * 1./24 * (u_boundary_values(i-1,j-1) + &
417  !~ u_boundary_values(i-1,j) + u_boundary_values(i,j-1))
418 
419  !~ v_boundary_contr (i-1,j-1) = v_boundary_contr (i-1,j-1) + &
420  !~ beta_lower(i,j) * dxdyh * 1./24 * (v_boundary_values(i-1,j-1) + &
421  !~ v_boundary_values(i-1,j) + v_boundary_values(i,j-1))
422  !~ endif
423 
424  !~ endif
425 
426  !~ if ((umask(i,j) .eq. 3) .OR. (umask(i,j-1) .eq. 3) .OR. (umask(i-1,j) .eq. 3)) then
427 
428  !~ dxh = G%dxh(i,j)
429  !~ dyh = G%dyh(i,j)
430  !~ dxdyh = G%dxdyh(i,j)
431 
432  !~ ux = (u_boundary_values(i,j)-u_boundary_values(i-1,j))/dxh
433  !~ vx = (v_boundary_values(i,j)-v_boundary_values(i-1,j))/dxh
434  !~ uy = (u_boundary_values(i,j)-u_boundary_values(i,j-1))/dyh
435  !~ vy = (v_boundary_values(i,j)-v_boundary_values(i,j-1))/dyh
436 
437  !~ if (umask (i,j-1) .eq. 1) then ! this (bot right) is a degree of freedom node
438 
439  !~ u_boundary_contr (i,j-1) = u_boundary_contr (i,j-1) + &
440  !~ .5 * dxdyh * nu_upper (i,j) * ((4*ux+2*vy) * (0./dxh) + (uy+vy) * (-1./dyh))
441 
442  !~ v_boundary_contr (i,j-1) = v_boundary_contr (i,j-1) + &
443  !~ .5 * dxdyh * nu_upper (i,j) * ((uy+vx) * (0./dxh) + (4*vy+2*ux) * (-1./dyh))
444 
445  !~ u_boundary_contr (i,j-1) = u_boundary_contr (i,j-1) + &
446  !~ beta_upper(i,j) * dxdyh * 1./24 * (u_boundary_values(i,j) + &
447  !~ u_boundary_values(i-1,j) + &
448  !~ u_boundary_values(i,j-1))
449 
450  !~ v_boundary_contr (i,j-1) = v_boundary_contr (i,j-1) + &
451  !~ beta_upper(i,j) * dxdyh * 1./24 * (u_boundary_values(i,j) + &
452  !~ u_boundary_values(i-1,j) + &
453  !~ u_boundary_values(i,j-1))
454  !~ endif
455 
456  !~ if (umask (i-1,j) .eq. 1) then ! this (top left) is a degree of freedom node
457 
458  !~ u_boundary_contr (i-1,j) = u_boundary_contr (i-1,j) + &
459  !~ .5 * dxdyh * nu_upper (i,j) * ((4*ux+2*vy) * (-1./dxh) + (uy+vy) * (0./dyh))
460 
461  !~ v_boundary_contr (i-1,j) = v_boundary_contr (i-1,j) + &
462  !~ .5 * dxdyh * nu_upper (i,j) * ((uy+vx) * (-1./dxh) + (4*vy+2*ux) * (0./dyh))
463 
464  !~ u_boundary_contr (i,j-1) = u_boundary_contr (i,j-1) + &
465  !~ beta_upper(i,j) * dxdyh * 1./24 * (u_boundary_values(i,j) + &
466  !~ u_boundary_values(i-1,j) + &
467  !~ u_boundary_values(i,j-1))
468 
469  !~ v_boundary_contr (i,j-1) = v_boundary_contr (i,j-1) + &
470  !~ beta_upper(i,j) * dxdyh * 1./24 * (u_boundary_values(i,j) + &
471  !~ u_boundary_values(i-1,j) + &
472  !~ u_boundary_values(i,j-1))
473  !~ endif
474 
475  !~ if (umask (i,j) .eq. 1) then ! this (top right) is a degree of freedom node
476 
477  !~ u_boundary_contr (i,j) = u_boundary_contr (i,j) + &
478  !~ .5 * dxdyh * nu_upper (i,j) * ((4*ux+2*vy) * (1./dxh) + (uy+vy) * (1./dyh))
479 
480  !~ v_boundary_contr (i,j) = v_boundary_contr (i,j) + &
481  !~ .5 * dxdyh * nu_upper (i,j) * ((uy+vx) * (1./dxh) + (4*vy+2*ux) * (1./dyh))
482 
483  !~ u_boundary_contr (i,j) = u_boundary_contr (i,j) + &
484  !~ beta_upper(i,j) * dxdyh * 1./24 * (u_boundary_values(i,j) + &
485  !~ u_boundary_values(i-1,j) + &
486  !~ u_boundary_values(i,j-1))
487 
488  !~ v_boundary_contr (i,j) = v_boundary_contr (i,j) + &
489  !~ beta_upper(i,j) * dxdyh * 1./24 * (u_boundary_values(i,j) + &
490  !~ u_boundary_values(i-1,j) + &
491  !~ u_boundary_values(i,j-1))
492  !~ endif
493 
494 
495  !~ endif
496  !~ endif ; enddo ; enddo
497 
498 !~ end subroutine apply_boundary_values_triangle
499 
500 !~ subroutine calc_shelf_visc_triangular (CS,u,v)
501  !~ type(ice_shelf_CS), pointer :: CS
502  !~ real, dimension(:,:), intent(inout) :: u, v
503 
504 !~ ! update DEPTH_INTEGRATED viscosity, based on horizontal strain rates - this is for triangle FEM solve so there is
505 !~ ! an "upper" and "lower" triangular viscosity
506 
507 !~ ! also this subroutine updates the nonlinear part of the basal traction
508 
509 !~ ! this may be subject to change later... to make it "hybrid"
510 
511  !~ real, pointer, dimension (:,:) :: nu_lower , &
512  !~ nu_upper, &
513  !~ beta_eff_lower, &
514  !~ beta_eff_upper
515  !~ real, pointer, dimension (:,:) :: H, &! thickness
516  !~ hmask
517 
518  !~ type(ocean_grid_type), pointer :: G
519  !~ integer :: 0, i, j, iscq, iecq, jscq, jecq, isd, jsd, ied, jed, iegq, jegq, giec, gjec, gisc, gjsc, cnt, isc, jsc, iec, jec, is, js
520  !~ real :: A, n, ux, uy, vx, vy, eps_min, umid, vmid, unorm, C_basal_friction, n_basal_friction, dxh, dyh, dxdyh
521 
522  !~ G => CS%grid
523 
524  !~ isc = G%isc ; jsc = G%jsc ; iec = G%iec ; jec = G%jec
525  !~ iscq = G%iscq ; iecq = G%iecq ; jscq = G%jscq ; jecq = G%jecq
526  !~ isd = G%isd ; jsd = G%jsd ; ied = G%isd ; jed = G%jsd
527  !~ iegq = G%iegq ; jegq = G%jegq
528  !~ gisc = G%domain%nx_halo+1 ; gjsc = G%domain%ny_halo+1
529  !~ giec = G%domain%nxtot+gisc ; gjec = G%domain%nytot+gjsc
530  !~ is = iscq - (1-0); js = jscq - (1-0)
531 
532  !~ A = CS%A_glen_isothermal ; n = CS%n_glen; eps_min = CS%eps_glen_min
533 
534  !~ H => CS%h_shelf
535  !~ hmask => CS%hmask
536  !~ nu_upper => CS%ice_visc_upper_tri
537  !~ nu_lower => CS%ice_visc_lower_tri
538  !~ beta_eff_upper => CS%taub_beta_eff_upper_tri
539  !~ beta_eff_lower => CS%taub_beta_eff_lower_tri
540 
541  !~ C_basal_friction = CS%C_basal_friction ; n_basal_friction = CS%n_basal_friction
542 
543  !~ do i=isd,ied
544  !~ do j=jsd,jed
545 
546  !~ dxh = G%dxh(i,j)
547  !~ dyh = G%dyh(i,j)
548  !~ dxdyh = G%dxdyh(i,j)
549 
550  !~ if (hmask (i,j) .eq. 1) then
551  !~ ux = (u(i,j-1)-u(i-1,j-1)) / dxh
552  !~ vx = (v(i,j-1)-v(i-1,j-1)) / dxh
553  !~ uy = (u(i-1,j)-u(i-1,j-1)) / dyh
554  !~ vy = (v(i-1,j)-v(i-1,j-1)) / dyh
555 
556  !~ nu_lower(i,j) = A**(-1/n) * (ux**2+vy**2+ux*vy.25*(uy+vx)**2+eps_min**2) ** ((1-n)/(2*n)) * H(i,j)
557  !~ umid = 1./3 * (u(i-1,j-1)+u(i-1,j)+u(i,j-1))
558  !~ vmid = 1./3 * (v(i-1,j-1)+v(i-1,j)+v(i,j-1))
559  !~ unorm = sqrt (umid**2+vmid**2+(eps_min*dxh)**2) ; beta_eff_lower (i,j) = C_basal_friction * unorm ** (n_basal_friction-1)
560 
561  !~ ux = (u(i,j)-u(i-1,j)) / dxh
562  !~ vx = (v(i,j)-v(i-1,j)) / dxh
563  !~ uy = (u(i,j)-u(i,j-1)) / dyh
564  !~ vy = (u(i,j)-u(i,j-1)) / dyh
565 
566  !~ nu_upper(i,j) = A**(-1/n) * (ux**2+vy**2+ux*vy.25*(uy+vx)**2+eps_min**2) ** ((1-n)/(2*n)) * H(i,j)
567  !~ umid = 1./3 * (u(i,j)+u(i-1,j)+u(i,j-1))
568  !~ vmid = 1./3 * (v(i,j)+v(i-1,j)+v(i,j-1))
569  !~ unorm = sqrt (umid**2+vmid**2+(eps_min*dxh)**2) ; beta_eff_upper (i,j) = C_basal_friction * unorm ** (n_basal_friction-1)
570 
571  !~ endif
572  !~ enddo
573  !~ enddo
574 
575 !~ end subroutine calc_shelf_visc_triangular
576 
577 
578 !~ subroutine CG_action_triangular (uret, vret, u, v, umask, vmask, hmask, nu_upper, nu_lower, &
579  !~ beta_upper, beta_lower, dxh, dyh, dxdyh, is, ie, js, je, 0)
580 
581 !~ real, dimension (:,:), intent (inout) :: uret, vret
582 !~ real, dimension (:,:), intent (in) :: u, v
583 !~ real, dimension (:,:), intent (in) :: umask, vmask
584 !~ real, dimension (:,:), intent (in) :: hmask, nu_upper, nu_lower, beta_upper, beta_lower
585 !~ real, dimension (:,:), intent (in) :: dxh, dyh, dxdyh
586 !~ integer, intent(in) :: is, ie, js, je, 0
587 
588 !~ ! the linear action of the matrix on (u,v) with triangular finite elements
589 !~ ! as of now everything is passed in so no grid pointers or anything of the sort have to be dereferenced,
590 !~ ! but this may change pursuant to conversations with others
591 !~ !
592 !~ ! is & ie are the cells over which the iteration is done; this may change between calls to this subroutine
593 !~ ! in order to make less frequent halo updates
594 !~ ! isym = 1 if grid is symmetric, 0 o.w.
595 
596  !~ real :: ux, uy, vx, vy
597  !~ integer :: i,j
598 
599  !~ do i=is,ie
600  !~ do j=js,je
601 
602  !~ if (hmask(i,j) .eq. 1) then ! this cell's vertices contain degrees of freedom
603 
604  !~ ux = (u(i,j-1)-u(i-1,j-1))/dxh(i,j)
605  !~ vx = (v(i,j-1)-v(i-1,j-1))/dxh(i,j)
606  !~ uy = (u(i-1,j)-u(i-1,j-1))/dyh(i,j)
607  !~ vy = (v(i-1,j)-v(i-1,j-1))/dyh(i,j)
608 
609  !~ if (umask(i,j-1) .eq. 1) then ! this (bot right) is a degree of freedom node
610 
611  !~ uret(i,j-1) = uret(i,j-1) + &
612  !~ .5 * dxdyh(i,j) * nu_lower (i,j) * ((4*ux+2*vy) * (1./dxh(i,j)) + (uy+vy) * (0./dyh(i,j)))
613 
614  !~ vret(i,j-1) = vret(i,j-1) + &
615  !~ .5 * dxdyh(i,j) * nu_lower (i,j) * ((uy+vx) * (1./dxh(i,j)) + (4*vy+2*ux) * (0./dyh(i,j)))
616 
617  !~ uret(i,j-1) = uret(i,j-1) + &
618  !~ beta_lower(i,j) * dxdyh(i,j) * 1./24 * (u(i-1,j-1) + &
619  !~ u(i-1,j) + u(i,j-1))
620 
621  !~ vret(i,j-1) = vret(i,j-1) + &
622  !~ beta_lower(i,j) * dxdyh(i,j) * 1./24 * (v(i-1,j-1) + &
623  !~ v(i-1,j) + v(i,j-1))
624  !~ endif
625 
626  !~ if (umask(i-1,j) .eq. 1) then ! this (top left) is a degree of freedom node
627 
628  !~ uret(i-1,j) = uret(i-1,j) + &
629  !~ .5 * dxdyh(i,j) * nu_lower (i,j) * ((4*ux+2*vy) * (0./dxh(i,j)) + (uy+vy) * (1./dyh(i,j)))
630 
631  !~ vret(i-1,j) = vret(i-1,j) + &
632  !~ .5 * dxdyh(i,j) * nu_lower (i,j) * ((uy+vx) * (0./dxh(i,j)) + (4*vy+2*ux) * (1./dyh(i,j)))
633 
634  !~ uret(i,j-1) = uret(i,j-1) + &
635  !~ beta_lower(i,j) * dxdyh(i,j) * 1./24 * (u(i-1,j-1) + &
636  !~ u(i-1,j) + u(i,j-1))
637 
638  !~ vret(i,j-1) = vret(i,j-1) + &
639  !~ beta_lower(i,j) * dxdyh(i,j) * 1./24 * (v(i-1,j-1) + &
640  !~ v(i-1,j) + v(i,j-1))
641  !~ endif
642 
643  !~ if (umask(i-1,j-1) .eq. 1) then ! this (bot left) is a degree of freedom node
644 
645  !~ uret(i-1,j-1) = uret(i-1,j-1) + &
646  !~ .5 * dxdyh(i,j) * nu_upper (i,j) * ((4*ux+2*vy) * (-1./dxh(i,j)) + (uy+vy) * (-1./dyh(i,j)))
647 
648  !~ vret(i-1,j-1) = vret(i-1,j-1) + &
649  !~ .5 * dxdyh(i,j) * nu_upper (i,j) * ((uy+vx) * (-1./dxh(i,j)) + (4*vy+2*ux) * (-1./dyh(i,j)))
650 
651  !~ uret(i-1,j-1) = uret(i-1,j-1) + &
652  !~ beta_lower(i,j) * dxdyh(i,j) * 1./24 * (u(i-1,j-1) + &
653  !~ u(i-1,j) + u(i,j-1))
654 
655  !~ vret(i-1,j-1) = vret(i-1,j-1) + &
656  !~ beta_lower(i,j) * dxdyh(i,j) * 1./24 * (v(i-1,j-1) + &
657  !~ v(i-1,j) + v(i,j-1))
658  !~ endif
659 
660 
661  !~ ux = (u(i,j)-u(i-1,j))/dxh(i,j)
662  !~ vx = (v(i,j)-v(i-1,j))/dxh(i,j)
663  !~ uy = (u(i,j)-u(i,j-1))/dyh(i,j)
664  !~ vy = (v(i,j)-v(i,j-1))/dyh(i,j)
665 
666  !~ if (umask(i,j-1) .eq. 1) then ! this (bot right) is a degree of freedom node
667 
668  !~ uret(i,j-1) = uret(i,j-1) + &
669  !~ .5 * dxdyh(i,j) * nu_upper (i,j) * ((4*ux+2*vy) * (0./dxh(i,j)) + (uy+vy) * (-1./dyh(i,j)))
670 
671  !~ vret(i,j-1) = vret(i,j-1) + &
672  !~ .5 * dxdyh(i,j) * nu_upper (i,j) * ((uy+vx) * (0./dxh(i,j)) + (4*vy+2*ux) * (-1./dyh(i,j)))
673 
674  !~ uret(i,j-1) = uret(i,j-1) + &
675  !~ beta_upper(i,j) * dxdyh(i,j) * 1./24 * (u(i,j) + &
676  !~ u(i-1,j) + u(i,j-1))
677 
678  !~ vret(i,j-1) = vret(i,j-1) + &
679  !~ beta_upper(i,j) * dxdyh(i,j) * 1./24 * (u(i,j) + &
680  !~ u(i-1,j) + u(i,j-1))
681  !~ endif
682 
683  !~ if (umask(i-1,j) .eq. 1) then ! this (top left) is a degree of freedom node
684 
685  !~ uret(i-1,j) = uret(i-1,j) + &
686  !~ .5 * dxdyh(i,j) * nu_upper (i,j) * ((4*ux+2*vy) * (-1./dxh(i,j)) + (uy+vy) * (0./dyh(i,j)))
687 
688  !~ vret(i-1,j) = vret(i-1,j) + &
689  !~ .5 * dxdyh(i,j) * nu_upper (i,j) * ((uy+vx) * (-1./dxh(i,j)) + (4*vy+2*ux) * (0./dyh(i,j)))
690 
691  !~ uret(i,j-1) = uret(i,j-1) + &
692  !~ beta_upper(i,j) * dxdyh(i,j) * 1./24 * (u(i,j) + &
693  !~ u(i-1,j) + u(i,j-1))
694 
695  !~ vret(i,j-1) = vret(i,j-1) + &
696  !~ beta_upper(i,j) * dxdyh(i,j) * 1./24 * (u(i,j) + &
697  !~ u(i-1,j) + u(i,j-1))
698  !~ endif
699 
700  !~ if (umask(i,j) .eq. 1) then ! this (top right) is a degree of freedom node
701 
702  !~ uret(i,j) = uret(i,j) + &
703  !~ .5 * dxdyh(i,j) * nu_upper (i,j) * ((4*ux+2*vy) * (1./dxh(i,j)) + (uy+vy) * (1./dyh(i,j)))
704 
705  !~ vret(i,j) = vret(i,j) + &
706  !~ .5 * dxdyh(i,j) * nu_upper (i,j) * ((uy+vx) * (1./dxh(i,j)) + (4*vy+2*ux) * (1./dyh(i,j)))
707 
708  !~ uret(i,j) = uret(i,j) + &
709  !~ beta_upper(i,j) * dxdyh(i,j) * 1./24 * (u(i,j) + &
710  !~ u(i-1,j) + u(i,j-1))
711 
712  !~ vret(i,j) = vret(i,j) + &
713  !~ beta_upper(i,j) * dxdyh(i,j) * 1./24 * (u(i,j) + &
714  !~ u(i-1,j) + u(i,j-1))
715  !~ endif
716 
717  !~ endif
718 
719  !~ enddo
720  !~ enddo
721 
722 !~ end subroutine CG_action_triangular
723 
724 
725 END MODULE shelf_triangular_festuff
subroutine, public enable_averaging(time_int_in, time_end_in, diag_cs)
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Provides the ocean grid type.
Definition: MOM_grid.F90:2
Provides subroutines for quantities specific to the equation of state.
Definition: MOM_EOS.F90:2
subroutine matrix_diagonal_triangle(CS, u_diagonal, v_diagonal)
subroutine, public disable_averaging(diag_cs)
subroutine, public restart_init(param_file, CS, restart_root)
subroutine, public restore_state(filename, directory, day, G, CS)
A control structure for the equation of state.
Definition: MOM_EOS.F90:55