Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
MODULE icevar
!!======================================================================
!! *** MODULE icevar ***
!! sea-ice: series of functions to transform or compute ice variables
!!======================================================================
!! History : - ! 2006-01 (M. Vancoppenolle) Original code
!! 4.0 ! 2018 (many people) SI3 [aka Sea Ice cube]
!!----------------------------------------------------------------------
#if defined key_si3
!!----------------------------------------------------------------------
!! 'key_si3' SI3 sea-ice model
!!----------------------------------------------------------------------
!!
!! There are three sets of variables
!! VGLO : global variables of the model
!! - v_i (jpi,jpj,jpl)
!! - v_s (jpi,jpj,jpl)
!! - a_i (jpi,jpj,jpl)
!! - t_s (jpi,jpj,jpl)
!! - e_i (jpi,jpj,nlay_i,jpl)
!! - e_s (jpi,jpj,nlay_s,jpl)
!! - sv_i(jpi,jpj,jpl)
!! - oa_i(jpi,jpj,jpl)
!! VEQV : equivalent variables sometimes used in the model
!! - h_i(jpi,jpj,jpl)
!! - h_s(jpi,jpj,jpl)
!! - t_i(jpi,jpj,nlay_i,jpl)
!! ...
!! VAGG : aggregate variables, averaged/summed over all
!! thickness categories
!! - vt_i(jpi,jpj)
!! - vt_s(jpi,jpj)
!! - at_i(jpi,jpj)
!! - st_i(jpi,jpj)
!! - et_s(jpi,jpj) total snow heat content
!! - et_i(jpi,jpj) total ice thermal content
!! - sm_i(jpi,jpj) mean ice salinity
!! - tm_i(jpi,jpj) mean ice temperature
!! - tm_s(jpi,jpj) mean snw temperature
!!----------------------------------------------------------------------
!! ice_var_agg : integrate variables over layers and categories
!! ice_var_glo2eqv : transform from VGLO to VEQV
!! ice_var_eqv2glo : transform from VEQV to VGLO
!! ice_var_salprof : salinity profile in the ice
!! ice_var_salprof1d : salinity profile in the ice 1D
!! ice_var_zapsmall : remove very small area and volume
!! ice_var_zapneg : remove negative ice fields
!! ice_var_roundoff : remove negative values arising from roundoff erros
!! ice_var_bv : brine volume
!! ice_var_enthalpy : compute ice and snow enthalpies from temperature
!! ice_var_sshdyn : compute equivalent ssh in lead
!! ice_var_itd : convert N-cat to M-cat
!! ice_var_snwfra : fraction of ice covered by snow
!! ice_var_snwblow : distribute snow fall between ice and ocean
!!----------------------------------------------------------------------
USE dom_oce ! ocean space and time domain
USE phycst ! physical constants (ocean directory)
USE sbc_oce , ONLY : sss_m, ln_ice_embd, nn_fsbc
USE ice ! sea-ice: variables
USE ice1D ! sea-ice: thermodynamics variables
!
USE in_out_manager ! I/O manager
USE lib_mpp ! MPP library
USE lib_fortran ! fortran utilities (glob_sum + no signed zero)
IMPLICIT NONE
PRIVATE
PUBLIC ice_var_agg
PUBLIC ice_var_glo2eqv
PUBLIC ice_var_eqv2glo
PUBLIC ice_var_salprof
PUBLIC ice_var_salprof1d
PUBLIC ice_var_zapsmall
PUBLIC ice_var_zapneg
PUBLIC ice_var_roundoff
PUBLIC ice_var_bv
PUBLIC ice_var_enthalpy
PUBLIC ice_var_sshdyn
PUBLIC ice_var_itd
PUBLIC ice_var_snwfra
PUBLIC ice_var_snwblow
INTERFACE ice_var_itd
MODULE PROCEDURE ice_var_itd_1c1c, ice_var_itd_Nc1c, ice_var_itd_1cMc, ice_var_itd_NcMc
END INTERFACE
!! * Substitutions
# include "do_loop_substitute.h90"
INTERFACE ice_var_snwfra
MODULE PROCEDURE ice_var_snwfra_1d, ice_var_snwfra_2d, ice_var_snwfra_3d
END INTERFACE
INTERFACE ice_var_snwblow
MODULE PROCEDURE ice_var_snwblow_1d, ice_var_snwblow_2d
END INTERFACE
!!----------------------------------------------------------------------
!! NEMO/ICE 4.0 , NEMO Consortium (2018)
!! $Id: icevar.F90 15385 2021-10-15 13:52:48Z clem $
!! Software governed by the CeCILL license (see ./LICENSE)
!!----------------------------------------------------------------------
CONTAINS
SUBROUTINE ice_var_agg( kn )
!!-------------------------------------------------------------------
!! *** ROUTINE ice_var_agg ***
!!
!! ** Purpose : aggregates ice-thickness-category variables to
!! all-ice variables, i.e. it turns VGLO into VAGG
!!-------------------------------------------------------------------
INTEGER, INTENT( in ) :: kn ! =1 state variables only
! ! >1 state variables + others
!
INTEGER :: ji, jj, jk, jl ! dummy loop indices
REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: z1_at_i, z1_vt_i, z1_vt_s
!!-------------------------------------------------------------------
!
! ! integrated values
vt_i(:,:) = SUM( v_i (:,:,:) , dim=3 )
vt_s(:,:) = SUM( v_s (:,:,:) , dim=3 )
st_i(:,:) = SUM( sv_i(:,:,:) , dim=3 )
at_i(:,:) = SUM( a_i (:,:,:) , dim=3 )
et_s(:,:) = SUM( SUM( e_s (:,:,:,:), dim=4 ), dim=3 )
et_i(:,:) = SUM( SUM( e_i (:,:,:,:), dim=4 ), dim=3 )
!
at_ip(:,:) = SUM( a_ip(:,:,:), dim=3 ) ! melt ponds
vt_ip(:,:) = SUM( v_ip(:,:,:), dim=3 )
vt_il(:,:) = SUM( v_il(:,:,:), dim=3 )
!
ato_i(:,:) = 1._wp - at_i(:,:) ! open water fraction
!
!!GS: tm_su always needed by ABL over sea-ice
ALLOCATE( z1_at_i(jpi,jpj) )
WHERE( at_i(:,:) > epsi20 ) ; z1_at_i(:,:) = 1._wp / at_i(:,:)
ELSEWHERE ; z1_at_i(:,:) = 0._wp
END WHERE
tm_su(:,:) = SUM( t_su(:,:,:) * a_i(:,:,:) , dim=3 ) * z1_at_i(:,:)
WHERE( at_i(:,:)<=epsi20 ) tm_su(:,:) = rt0
!
! The following fields are calculated for diagnostics and outputs only
! ==> Do not use them for other purposes
IF( kn > 1 ) THEN
!
ALLOCATE( z1_vt_i(jpi,jpj) , z1_vt_s(jpi,jpj) )
WHERE( vt_i(:,:) > epsi20 ) ; z1_vt_i(:,:) = 1._wp / vt_i(:,:)
ELSEWHERE ; z1_vt_i(:,:) = 0._wp
END WHERE
WHERE( vt_s(:,:) > epsi20 ) ; z1_vt_s(:,:) = 1._wp / vt_s(:,:)
ELSEWHERE ; z1_vt_s(:,:) = 0._wp
END WHERE
!
! ! mean ice/snow thickness
hm_i(:,:) = vt_i(:,:) * z1_at_i(:,:)
hm_s(:,:) = vt_s(:,:) * z1_at_i(:,:)
!
! ! mean temperature (K), salinity and age
tm_si(:,:) = SUM( t_si(:,:,:) * a_i(:,:,:) , dim=3 ) * z1_at_i(:,:)
om_i (:,:) = SUM( oa_i(:,:,:) , dim=3 ) * z1_at_i(:,:)
sm_i (:,:) = st_i(:,:) * z1_vt_i(:,:)
!
tm_i(:,:) = 0._wp
tm_s(:,:) = 0._wp
DO jl = 1, jpl
DO jk = 1, nlay_i
tm_i(:,:) = tm_i(:,:) + r1_nlay_i * t_i (:,:,jk,jl) * v_i(:,:,jl) * z1_vt_i(:,:)
END DO
DO jk = 1, nlay_s
tm_s(:,:) = tm_s(:,:) + r1_nlay_s * t_s (:,:,jk,jl) * v_s(:,:,jl) * z1_vt_s(:,:)
END DO
END DO
!
! ! put rt0 where there is no ice
WHERE( at_i(:,:)<=epsi20 )
tm_si(:,:) = rt0
tm_i (:,:) = rt0
tm_s (:,:) = rt0
END WHERE
!
! ! mean melt pond depth
WHERE( at_ip(:,:) > epsi20 ) ; hm_ip(:,:) = vt_ip(:,:) / at_ip(:,:) ; hm_il(:,:) = vt_il(:,:) / at_ip(:,:)
ELSEWHERE ; hm_ip(:,:) = 0._wp ; hm_il(:,:) = 0._wp
END WHERE
!
DEALLOCATE( z1_vt_i , z1_vt_s )
!
ENDIF
!
DEALLOCATE( z1_at_i )
!
END SUBROUTINE ice_var_agg
SUBROUTINE ice_var_glo2eqv
!!-------------------------------------------------------------------
!! *** ROUTINE ice_var_glo2eqv ***
!!
!! ** Purpose : computes equivalent variables as function of
!! global variables, i.e. it turns VGLO into VEQV
!!-------------------------------------------------------------------
INTEGER :: ji, jj, jk, jl ! dummy loop indices
REAL(wp) :: ze_i ! local scalars
REAL(wp) :: ze_s, ztmelts, zbbb, zccc ! - -
REAL(wp) :: zhmax, z1_zhmax ! - -
REAL(wp) :: zlay_i, zlay_s ! - -
REAL(wp), PARAMETER :: zhl_max = 0.015_wp ! pond lid thickness above which the ponds disappear from the albedo calculation
REAL(wp), PARAMETER :: zhl_min = 0.005_wp ! pond lid thickness below which the full pond area is used in the albedo calculation
REAL(wp), DIMENSION(jpi,jpj,jpl) :: z1_a_i, z1_v_i, z1_a_ip, za_s_fra
!!-------------------------------------------------------------------
!!gm Question 2: It is possible to define existence of sea-ice in a common way between
!! ice area and ice volume ?
!! the idea is to be able to define one for all at the begining of this routine
!! a criteria for icy area (i.e. a_i > epsi20 and v_i > epsi20 )
!---------------------------------------------------------------
! Ice thickness, snow thickness, ice salinity, ice age and ponds
!---------------------------------------------------------------
! !--- inverse of the ice area
WHERE( a_i(:,:,:) > epsi20 ) ; z1_a_i(:,:,:) = 1._wp / a_i(:,:,:)
ELSEWHERE ; z1_a_i(:,:,:) = 0._wp
END WHERE
!
WHERE( v_i(:,:,:) > epsi20 ) ; z1_v_i(:,:,:) = 1._wp / v_i(:,:,:)
ELSEWHERE ; z1_v_i(:,:,:) = 0._wp
END WHERE
!
WHERE( a_ip(:,:,:) > epsi20 ) ; z1_a_ip(:,:,:) = 1._wp / a_ip(:,:,:)
ELSEWHERE ; z1_a_ip(:,:,:) = 0._wp
END WHERE
! !--- ice thickness
h_i(:,:,:) = v_i (:,:,:) * z1_a_i(:,:,:)
zhmax = hi_max(jpl)
z1_zhmax = 1._wp / hi_max(jpl)
WHERE( h_i(:,:,jpl) > zhmax ) ! bound h_i by hi_max (i.e. 99 m) with associated update of ice area
h_i (:,:,jpl) = zhmax
a_i (:,:,jpl) = v_i(:,:,jpl) * z1_zhmax
z1_a_i(:,:,jpl) = zhmax * z1_v_i(:,:,jpl)
END WHERE
! !--- snow thickness
h_s(:,:,:) = v_s (:,:,:) * z1_a_i(:,:,:)
! !--- ice age
o_i(:,:,:) = oa_i(:,:,:) * z1_a_i(:,:,:)
! !--- pond and lid thickness
h_ip(:,:,:) = v_ip(:,:,:) * z1_a_ip(:,:,:)
h_il(:,:,:) = v_il(:,:,:) * z1_a_ip(:,:,:)
! !--- melt pond effective area (used for albedo)
a_ip_frac(:,:,:) = a_ip(:,:,:) * z1_a_i(:,:,:)
WHERE ( h_il(:,:,:) <= zhl_min ) ; a_ip_eff(:,:,:) = a_ip_frac(:,:,:) ! lid is very thin. Expose all the pond
ELSEWHERE( h_il(:,:,:) >= zhl_max ) ; a_ip_eff(:,:,:) = 0._wp ! lid is very thick. Cover all the pond up with ice and snow
ELSEWHERE ; a_ip_eff(:,:,:) = a_ip_frac(:,:,:) * & ! lid is in between. Expose part of the pond
& ( zhl_max - h_il(:,:,:) ) / ( zhl_max - zhl_min )
END WHERE
!
CALL ice_var_snwfra( h_s, za_s_fra ) ! calculate ice fraction covered by snow
a_ip_eff = MIN( a_ip_eff, 1._wp - za_s_fra ) ! make sure (a_ip_eff + a_s_fra) <= 1
!
! !--- salinity (with a minimum value imposed everywhere)
IF( nn_icesal == 2 ) THEN
WHERE( v_i(:,:,:) > epsi20 ) ; s_i(:,:,:) = MAX( rn_simin , MIN( rn_simax, sv_i(:,:,:) * z1_v_i(:,:,:) ) )
ELSEWHERE ; s_i(:,:,:) = rn_simin
END WHERE
ENDIF
CALL ice_var_salprof ! salinity profile
!-------------------
! Ice temperature [K] (with a minimum value (rt0 - 100.))
!-------------------
zlay_i = REAL( nlay_i , wp ) ! number of layers
DO jl = 1, jpl
DO_3D( nn_hls, nn_hls, nn_hls, nn_hls, 1, nlay_i )
IF ( v_i(ji,jj,jl) > epsi20 ) THEN !--- icy area
!
ze_i = e_i (ji,jj,jk,jl) * z1_v_i(ji,jj,jl) * zlay_i ! Energy of melting e(S,T) [J.m-3]
ztmelts = - sz_i(ji,jj,jk,jl) * rTmlt ! Ice layer melt temperature [C]
! Conversion q(S,T) -> T (second order equation)
zbbb = ( rcp - rcpi ) * ztmelts + ze_i * r1_rhoi - rLfus
zccc = SQRT( MAX( zbbb * zbbb - 4._wp * rcpi * rLfus * ztmelts , 0._wp) )
t_i(ji,jj,jk,jl) = MAX( -100._wp , MIN( -( zbbb + zccc ) * 0.5_wp * r1_rcpi , ztmelts ) ) + rt0 ! [K] with bounds: -100 < t_i < ztmelts
!
ELSE !--- no ice
t_i(ji,jj,jk,jl) = rt0
ENDIF
END_3D
END DO
!--------------------
! Snow temperature [K] (with a minimum value (rt0 - 100.))
!--------------------
zlay_s = REAL( nlay_s , wp )
DO jk = 1, nlay_s
WHERE( v_s(:,:,:) > epsi20 ) !--- icy area
t_s(:,:,jk,:) = rt0 + MAX( -100._wp , &
& MIN( r1_rcpi * ( -r1_rhos * ( e_s(:,:,jk,:) / v_s(:,:,:) * zlay_s ) + rLfus ) , 0._wp ) )
ELSEWHERE !--- no ice
t_s(:,:,jk,:) = rt0
END WHERE
END DO
!
! integrated values
vt_i (:,:) = SUM( v_i , dim=3 )
vt_s (:,:) = SUM( v_s , dim=3 )
at_i (:,:) = SUM( a_i , dim=3 )
!
END SUBROUTINE ice_var_glo2eqv
SUBROUTINE ice_var_eqv2glo
!!-------------------------------------------------------------------
!! *** ROUTINE ice_var_eqv2glo ***
!!
!! ** Purpose : computes global variables as function of
!! equivalent variables, i.e. it turns VEQV into VGLO
!!-------------------------------------------------------------------
!
v_i (:,:,:) = h_i (:,:,:) * a_i (:,:,:)
v_s (:,:,:) = h_s (:,:,:) * a_i (:,:,:)
sv_i(:,:,:) = s_i (:,:,:) * v_i (:,:,:)
v_ip(:,:,:) = h_ip(:,:,:) * a_ip(:,:,:)
v_il(:,:,:) = h_il(:,:,:) * a_ip(:,:,:)
!
END SUBROUTINE ice_var_eqv2glo
SUBROUTINE ice_var_salprof
!!-------------------------------------------------------------------
!! *** ROUTINE ice_var_salprof ***
!!
!! ** Purpose : computes salinity profile in function of bulk salinity
!!
!! ** Method : If bulk salinity greater than zsi1,
!! the profile is assumed to be constant (S_inf)
!! If bulk salinity lower than zsi0,
!! the profile is linear with 0 at the surface (S_zero)
!! If it is between zsi0 and zsi1, it is a
!! alpha-weighted linear combination of s_inf and s_zero
!!
!! ** References : Vancoppenolle et al., 2007
!!-------------------------------------------------------------------
INTEGER :: ji, jj, jk, jl ! dummy loop index
REAL(wp) :: z1_dS
REAL(wp) :: ztmp1, ztmp2, zs0, zs
REAL(wp), ALLOCATABLE, DIMENSION(:,:) :: z_slope_s, zalpha ! case 2 only
REAL(wp), PARAMETER :: zsi0 = 3.5_wp
REAL(wp), PARAMETER :: zsi1 = 4.5_wp
!!-------------------------------------------------------------------
!!gm Question: Remove the option 3 ? How many years since it last use ?
SELECT CASE ( nn_icesal )
!
! !---------------------------------------!
CASE( 1 ) ! constant salinity in time and space !
! !---------------------------------------!
sz_i(:,:,:,:) = rn_icesal
s_i (:,:,:) = rn_icesal
!
! !---------------------------------------------!
CASE( 2 ) ! time varying salinity with linear profile !
! !---------------------------------------------!
z1_dS = 1._wp / ( zsi1 - zsi0 )
!
ALLOCATE( z_slope_s(jpi,jpj) , zalpha(jpi,jpj) )
!
DO jl = 1, jpl
DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
! ! Slope of the linear profile
IF( h_i(ji,jj,jl) > epsi20 ) THEN
z_slope_s(ji,jj) = 2._wp * s_i(ji,jj,jl) / h_i(ji,jj,jl)
ELSE
z_slope_s(ji,jj) = 0._wp
ENDIF
!
zalpha(ji,jj) = MAX( 0._wp , MIN( ( zsi1 - s_i(ji,jj,jl) ) * z1_dS , 1._wp ) )
! ! force a constant profile when SSS too low (Baltic Sea)
IF( 2._wp * s_i(ji,jj,jl) >= sss_m(ji,jj) ) zalpha(ji,jj) = 0._wp
END_2D
!
! Computation of the profile
DO_3D( nn_hls, nn_hls, nn_hls, nn_hls, 1, nlay_i )
! ! linear profile with 0 surface value
zs0 = z_slope_s(ji,jj) * ( REAL(jk,wp) - 0.5_wp ) * h_i(ji,jj,jl) * r1_nlay_i
zs = zalpha(ji,jj) * zs0 + ( 1._wp - zalpha(ji,jj) ) * s_i(ji,jj,jl) ! weighting the profile
sz_i(ji,jj,jk,jl) = MIN( rn_simax, MAX( zs, rn_simin ) )
END_3D
END DO
!
DEALLOCATE( z_slope_s , zalpha )
!
! !-------------------------------------------!
CASE( 3 ) ! constant salinity with a fix profile ! (Schwarzacher (1959) multiyear salinity profile
! !-------------------------------------------! (mean = 2.30)
!
s_i(:,:,:) = 2.30_wp
!!gm Remark: if we keep the case 3, then compute an store one for all time-step
!! a array S_prof(1:nlay_i) containing the calculation and just do:
! DO jk = 1, nlay_i
! sz_i(:,:,jk,:) = S_prof(jk)
! END DO
!!gm end
!
DO jl = 1, jpl
DO jk = 1, nlay_i
ztmp1 = ( REAL(jk,wp) - 0.5_wp ) * r1_nlay_i
ztmp2 = 1.6_wp * ( 1._wp - COS( rpi * ztmp1**(0.407_wp/(0.573_wp+ztmp1)) ) )
DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
sz_i(ji,jj,jk,jl) = ztmp2
END_2D
END DO
END DO
!
END SELECT
!
END SUBROUTINE ice_var_salprof
SUBROUTINE ice_var_salprof1d
!!-------------------------------------------------------------------
!! *** ROUTINE ice_var_salprof1d ***
!!
!! ** Purpose : 1d computation of the sea ice salinity profile
!! Works with 1d vectors and is used by thermodynamic modules
!!-------------------------------------------------------------------
INTEGER :: ji, jk ! dummy loop indices
REAL(wp) :: ztmp1, ztmp2, z1_dS ! local scalars
REAL(wp) :: zs, zs0 ! - -
!
REAL(wp), ALLOCATABLE, DIMENSION(:) :: z_slope_s, zalpha !
REAL(wp), PARAMETER :: zsi0 = 3.5_wp
REAL(wp), PARAMETER :: zsi1 = 4.5_wp
!!-------------------------------------------------------------------
!
SELECT CASE ( nn_icesal )
!
! !---------------------------------------!
CASE( 1 ) ! constant salinity in time and space !
! !---------------------------------------!
sz_i_1d(1:npti,:) = rn_icesal
!
! !---------------------------------------------!
CASE( 2 ) ! time varying salinity with linear profile !
! !---------------------------------------------!
z1_dS = 1._wp / ( zsi1 - zsi0 )
!
ALLOCATE( z_slope_s(jpij), zalpha(jpij) )
!
DO ji = 1, npti
! ! Slope of the linear profile
IF( h_i_1d(ji) > epsi20 ) THEN
z_slope_s(ji) = 2._wp * s_i_1d(ji) / h_i_1d(ji)
ELSE
z_slope_s(ji) = 0._wp
ENDIF
!
zalpha(ji) = MAX( 0._wp , MIN( ( zsi1 - s_i_1d(ji) ) * z1_dS , 1._wp ) )
! ! force a constant profile when SSS too low (Baltic Sea)
IF( 2._wp * s_i_1d(ji) >= sss_1d(ji) ) zalpha(ji) = 0._wp
!
END DO
!
! Computation of the profile
DO jk = 1, nlay_i
DO ji = 1, npti
! ! linear profile with 0 surface value
zs0 = z_slope_s(ji) * ( REAL(jk,wp) - 0.5_wp ) * h_i_1d(ji) * r1_nlay_i
zs = zalpha(ji) * zs0 + ( 1._wp - zalpha(ji) ) * s_i_1d(ji)
sz_i_1d(ji,jk) = MIN( rn_simax , MAX( zs , rn_simin ) )
END DO
END DO
!
DEALLOCATE( z_slope_s, zalpha )
! !-------------------------------------------!
CASE( 3 ) ! constant salinity with a fix profile ! (Schwarzacher (1959) multiyear salinity profile
! !-------------------------------------------! (mean = 2.30)
!
s_i_1d(1:npti) = 2.30_wp
!
!!gm cf remark in ice_var_salprof routine, CASE( 3 )
DO jk = 1, nlay_i
ztmp1 = ( REAL(jk,wp) - 0.5_wp ) * r1_nlay_i
ztmp2 = 1.6_wp * ( 1._wp - COS( rpi * ztmp1**( 0.407_wp / ( 0.573_wp + ztmp1 ) ) ) )
DO ji = 1, npti
sz_i_1d(ji,jk) = ztmp2
END DO
END DO
!
END SELECT
!
END SUBROUTINE ice_var_salprof1d
SUBROUTINE ice_var_zapsmall
!!-------------------------------------------------------------------
!! *** ROUTINE ice_var_zapsmall ***
!!
!! ** Purpose : Remove too small sea ice areas and correct fluxes
!!-------------------------------------------------------------------
INTEGER :: ji, jj, jl, jk ! dummy loop indices
REAL(wp), DIMENSION(jpi,jpj) :: zswitch
!!-------------------------------------------------------------------
!
DO jl = 1, jpl !== loop over the categories ==!
!
WHERE( a_i(:,:,jl) > epsi10 ) ; h_i(:,:,jl) = v_i(:,:,jl) / a_i(:,:,jl)
ELSEWHERE ; h_i(:,:,jl) = 0._wp
END WHERE
!
WHERE( a_i(:,:,jl) < epsi10 .OR. v_i(:,:,jl) < epsi10 .OR. h_i(:,:,jl) < epsi10 ) ; zswitch(:,:) = 0._wp
ELSEWHERE ; zswitch(:,:) = 1._wp
END WHERE
!
!-----------------------------------------------------------------
! Zap ice energy and use ocean heat to melt ice
!-----------------------------------------------------------------
DO_3D( nn_hls, nn_hls, nn_hls, nn_hls, 1, nlay_i )
! update exchanges with ocean
hfx_res(ji,jj) = hfx_res(ji,jj) - (1._wp - zswitch(ji,jj) ) * e_i(ji,jj,jk,jl) * r1_Dt_ice ! W.m-2 <0
e_i(ji,jj,jk,jl) = e_i(ji,jj,jk,jl) * zswitch(ji,jj)
t_i(ji,jj,jk,jl) = t_i(ji,jj,jk,jl) * zswitch(ji,jj) + rt0 * ( 1._wp - zswitch(ji,jj) )
END_3D
!
DO_3D( nn_hls, nn_hls, nn_hls, nn_hls, 1, nlay_s )
! update exchanges with ocean
hfx_res(ji,jj) = hfx_res(ji,jj) - (1._wp - zswitch(ji,jj) ) * e_s(ji,jj,jk,jl) * r1_Dt_ice ! W.m-2 <0
e_s(ji,jj,jk,jl) = e_s(ji,jj,jk,jl) * zswitch(ji,jj)
t_s(ji,jj,jk,jl) = t_s(ji,jj,jk,jl) * zswitch(ji,jj) + rt0 * ( 1._wp - zswitch(ji,jj) )
END_3D
!
!-----------------------------------------------------------------
! zap ice and snow volume, add water and salt to ocean
!-----------------------------------------------------------------
DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
! update exchanges with ocean
sfx_res(ji,jj) = sfx_res(ji,jj) + ( 1._wp - zswitch(ji,jj) ) * sv_i(ji,jj,jl) * rhoi * r1_Dt_ice
wfx_res(ji,jj) = wfx_res(ji,jj) + ( 1._wp - zswitch(ji,jj) ) * v_i (ji,jj,jl) * rhoi * r1_Dt_ice
wfx_res(ji,jj) = wfx_res(ji,jj) + ( 1._wp - zswitch(ji,jj) ) * v_s (ji,jj,jl) * rhos * r1_Dt_ice
wfx_pnd(ji,jj) = wfx_pnd(ji,jj) + ( 1._wp - zswitch(ji,jj) ) * ( v_ip(ji,jj,jl)+v_il(ji,jj,jl) ) * rhow * r1_Dt_ice
!
a_i (ji,jj,jl) = a_i (ji,jj,jl) * zswitch(ji,jj)
v_i (ji,jj,jl) = v_i (ji,jj,jl) * zswitch(ji,jj)
v_s (ji,jj,jl) = v_s (ji,jj,jl) * zswitch(ji,jj)
t_su (ji,jj,jl) = t_su(ji,jj,jl) * zswitch(ji,jj) + t_bo(ji,jj) * ( 1._wp - zswitch(ji,jj) )
oa_i (ji,jj,jl) = oa_i(ji,jj,jl) * zswitch(ji,jj)
sv_i (ji,jj,jl) = sv_i(ji,jj,jl) * zswitch(ji,jj)
!
h_i (ji,jj,jl) = h_i (ji,jj,jl) * zswitch(ji,jj)
h_s (ji,jj,jl) = h_s (ji,jj,jl) * zswitch(ji,jj)
!
a_ip (ji,jj,jl) = a_ip (ji,jj,jl) * zswitch(ji,jj)
v_ip (ji,jj,jl) = v_ip (ji,jj,jl) * zswitch(ji,jj)
v_il (ji,jj,jl) = v_il (ji,jj,jl) * zswitch(ji,jj)
h_ip (ji,jj,jl) = h_ip (ji,jj,jl) * zswitch(ji,jj)
h_il (ji,jj,jl) = h_il (ji,jj,jl) * zswitch(ji,jj)
!
END_2D
!
END DO
! to be sure that at_i is the sum of a_i(jl)
at_i (:,:) = SUM( a_i (:,:,:), dim=3 )
vt_i (:,:) = SUM( v_i (:,:,:), dim=3 )
!!clem add?
! vt_s (:,:) = SUM( v_s (:,:,:), dim=3 )
! st_i (:,:) = SUM( sv_i(:,:,:), dim=3 )
! et_s(:,:) = SUM( SUM( e_s (:,:,:,:), dim=4 ), dim=3 )
! et_i(:,:) = SUM( SUM( e_i (:,:,:,:), dim=4 ), dim=3 )
!!clem
! open water = 1 if at_i=0
WHERE( at_i(:,:) == 0._wp ) ato_i(:,:) = 1._wp
!
END SUBROUTINE ice_var_zapsmall
SUBROUTINE ice_var_zapneg( pdt, pato_i, pv_i, pv_s, psv_i, poa_i, pa_i, pa_ip, pv_ip, pv_il, pe_s, pe_i )
!!-------------------------------------------------------------------
!! *** ROUTINE ice_var_zapneg ***
!!
!! ** Purpose : Remove negative sea ice fields and correct fluxes
!!-------------------------------------------------------------------
REAL(wp) , INTENT(in ) :: pdt ! tracer time-step
REAL(wp), DIMENSION(:,:) , INTENT(inout) :: pato_i ! open water area
REAL(wp), DIMENSION(:,:,:) , INTENT(inout) :: pv_i ! ice volume
REAL(wp), DIMENSION(:,:,:) , INTENT(inout) :: pv_s ! snw volume
REAL(wp), DIMENSION(:,:,:) , INTENT(inout) :: psv_i ! salt content
REAL(wp), DIMENSION(:,:,:) , INTENT(inout) :: poa_i ! age content
REAL(wp), DIMENSION(:,:,:) , INTENT(inout) :: pa_i ! ice concentration
REAL(wp), DIMENSION(:,:,:) , INTENT(inout) :: pa_ip ! melt pond fraction
REAL(wp), DIMENSION(:,:,:) , INTENT(inout) :: pv_ip ! melt pond volume
REAL(wp), DIMENSION(:,:,:) , INTENT(inout) :: pv_il ! melt pond lid volume
REAL(wp), DIMENSION(:,:,:,:), INTENT(inout) :: pe_s ! snw heat content
REAL(wp), DIMENSION(:,:,:,:), INTENT(inout) :: pe_i ! ice heat content
!
INTEGER :: ji, jj, jl, jk ! dummy loop indices
REAL(wp) :: z1_dt
!!-------------------------------------------------------------------
!
z1_dt = 1._wp / pdt
!
DO jl = 1, jpl !== loop over the categories ==!
!
! make sure a_i=0 where v_i<=0
WHERE( pv_i(:,:,:) <= 0._wp ) pa_i(:,:,:) = 0._wp
!----------------------------------------
! zap ice energy and send it to the ocean
!----------------------------------------
DO_3D( nn_hls, nn_hls, nn_hls, nn_hls, 1, nlay_i )
IF( pe_i(ji,jj,jk,jl) < 0._wp .OR. pa_i(ji,jj,jl) <= 0._wp ) THEN
hfx_res(ji,jj) = hfx_res(ji,jj) - pe_i(ji,jj,jk,jl) * z1_dt ! W.m-2 >0
pe_i(ji,jj,jk,jl) = 0._wp
ENDIF
END_3D
!
DO_3D( nn_hls, nn_hls, nn_hls, nn_hls, 1, nlay_s )
IF( pe_s(ji,jj,jk,jl) < 0._wp .OR. pa_i(ji,jj,jl) <= 0._wp ) THEN
hfx_res(ji,jj) = hfx_res(ji,jj) - pe_s(ji,jj,jk,jl) * z1_dt ! W.m-2 <0
pe_s(ji,jj,jk,jl) = 0._wp
ENDIF
END_3D
!
!-----------------------------------------------------
! zap ice and snow volume, add water and salt to ocean
!-----------------------------------------------------
DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
IF( pv_i(ji,jj,jl) < 0._wp .OR. pa_i(ji,jj,jl) <= 0._wp ) THEN
wfx_res(ji,jj) = wfx_res(ji,jj) + pv_i (ji,jj,jl) * rhoi * z1_dt
pv_i (ji,jj,jl) = 0._wp
ENDIF
IF( pv_s(ji,jj,jl) < 0._wp .OR. pa_i(ji,jj,jl) <= 0._wp ) THEN
wfx_res(ji,jj) = wfx_res(ji,jj) + pv_s (ji,jj,jl) * rhos * z1_dt
pv_s (ji,jj,jl) = 0._wp
ENDIF
IF( psv_i(ji,jj,jl) < 0._wp .OR. pa_i(ji,jj,jl) <= 0._wp .OR. pv_i(ji,jj,jl) <= 0._wp ) THEN
sfx_res(ji,jj) = sfx_res(ji,jj) + psv_i(ji,jj,jl) * rhoi * z1_dt
psv_i (ji,jj,jl) = 0._wp
ENDIF
IF( pv_ip(ji,jj,jl) < 0._wp .OR. pv_il(ji,jj,jl) < 0._wp .OR. pa_ip(ji,jj,jl) <= 0._wp ) THEN
wfx_pnd(ji,jj) = wfx_pnd(ji,jj) + pv_il(ji,jj,jl) * rhow * z1_dt
pv_il (ji,jj,jl) = 0._wp
ENDIF
IF( pv_ip(ji,jj,jl) < 0._wp .OR. pa_ip(ji,jj,jl) <= 0._wp ) THEN
wfx_pnd(ji,jj) = wfx_pnd(ji,jj) + pv_ip(ji,jj,jl) * rhow * z1_dt
pv_ip (ji,jj,jl) = 0._wp
ENDIF
END_2D
!
END DO
!
WHERE( pato_i(:,:) < 0._wp ) pato_i(:,:) = 0._wp
WHERE( poa_i (:,:,:) < 0._wp ) poa_i (:,:,:) = 0._wp
WHERE( pa_i (:,:,:) < 0._wp ) pa_i (:,:,:) = 0._wp
WHERE( pa_ip (:,:,:) < 0._wp ) pa_ip (:,:,:) = 0._wp
!
END SUBROUTINE ice_var_zapneg
SUBROUTINE ice_var_roundoff( pa_i, pv_i, pv_s, psv_i, poa_i, pa_ip, pv_ip, pv_il, pe_s, pe_i )
!!-------------------------------------------------------------------
!! *** ROUTINE ice_var_roundoff ***
!!
!! ** Purpose : Remove negative sea ice values arising from roundoff errors
!!-------------------------------------------------------------------
REAL(wp), DIMENSION(:,:) , INTENT(inout) :: pa_i ! ice concentration
REAL(wp), DIMENSION(:,:) , INTENT(inout) :: pv_i ! ice volume
REAL(wp), DIMENSION(:,:) , INTENT(inout) :: pv_s ! snw volume
REAL(wp), DIMENSION(:,:) , INTENT(inout) :: psv_i ! salt content
REAL(wp), DIMENSION(:,:) , INTENT(inout) :: poa_i ! age content
REAL(wp), DIMENSION(:,:) , INTENT(inout) :: pa_ip ! melt pond fraction
REAL(wp), DIMENSION(:,:) , INTENT(inout) :: pv_ip ! melt pond volume
REAL(wp), DIMENSION(:,:) , INTENT(inout) :: pv_il ! melt pond lid volume
REAL(wp), DIMENSION(:,:,:), INTENT(inout) :: pe_s ! snw heat content
REAL(wp), DIMENSION(:,:,:), INTENT(inout) :: pe_i ! ice heat content
!!-------------------------------------------------------------------
!
WHERE( pa_i (1:npti,:) < 0._wp ) pa_i (1:npti,:) = 0._wp ! a_i must be >= 0
WHERE( pv_i (1:npti,:) < 0._wp ) pv_i (1:npti,:) = 0._wp ! v_i must be >= 0
WHERE( pv_s (1:npti,:) < 0._wp ) pv_s (1:npti,:) = 0._wp ! v_s must be >= 0
WHERE( psv_i(1:npti,:) < 0._wp ) psv_i(1:npti,:) = 0._wp ! sv_i must be >= 0
WHERE( poa_i(1:npti,:) < 0._wp ) poa_i(1:npti,:) = 0._wp ! oa_i must be >= 0
WHERE( pe_i (1:npti,:,:) < 0._wp ) pe_i (1:npti,:,:) = 0._wp ! e_i must be >= 0
WHERE( pe_s (1:npti,:,:) < 0._wp ) pe_s (1:npti,:,:) = 0._wp ! e_s must be >= 0
IF( ln_pnd_LEV .OR. ln_pnd_TOPO ) THEN
WHERE( pa_ip(1:npti,:) < 0._wp ) pa_ip(1:npti,:) = 0._wp ! a_ip must be >= 0
WHERE( pv_ip(1:npti,:) < 0._wp ) pv_ip(1:npti,:) = 0._wp ! v_ip must be >= 0
IF( ln_pnd_lids ) THEN
WHERE( pv_il(1:npti,:) < 0._wp .AND. pv_il(1:npti,:) > -epsi10 ) pv_il(1:npti,:) = 0._wp ! v_il must be >= 0
ENDIF
ENDIF
!
END SUBROUTINE ice_var_roundoff
SUBROUTINE ice_var_bv
!!-------------------------------------------------------------------
!! *** ROUTINE ice_var_bv ***
!!
!! ** Purpose : computes mean brine volume (%) in sea ice
!!
!! ** Method : e = - 0.054 * S (ppt) / T (C)
!!
!! References : Vancoppenolle et al., JGR, 2007
!!-------------------------------------------------------------------
INTEGER :: ji, jj, jk, jl ! dummy loop indices
!!-------------------------------------------------------------------
!
!!gm I prefere to use WHERE / ELSEWHERE to set it to zero only where needed <<<=== to be done
!! instead of setting everything to zero as just below
bv_i (:,:,:) = 0._wp
DO jl = 1, jpl
DO_3D( nn_hls, nn_hls, nn_hls, nn_hls, 1, nlay_i )
IF( t_i(ji,jj,jk,jl) < rt0 - epsi10 ) THEN
bv_i(ji,jj,jl) = bv_i(ji,jj,jl) - rTmlt * sz_i(ji,jj,jk,jl) * r1_nlay_i / ( t_i(ji,jj,jk,jl) - rt0 )
ENDIF
END_3D
END DO
WHERE( vt_i(:,:) > epsi20 ) ; bvm_i(:,:) = SUM( bv_i(:,:,:) * v_i(:,:,:) , dim=3 ) / vt_i(:,:)
ELSEWHERE ; bvm_i(:,:) = 0._wp
END WHERE
!
END SUBROUTINE ice_var_bv
SUBROUTINE ice_var_enthalpy
!!-------------------------------------------------------------------
!! *** ROUTINE ice_var_enthalpy ***
!!
!! ** Purpose : Computes sea ice energy of melting q_i (J.m-3) from temperature
!!
!! ** Method : Formula (Bitz and Lipscomb, 1999)
!!-------------------------------------------------------------------
INTEGER :: ji, jk ! dummy loop indices
REAL(wp) :: ztmelts ! local scalar
!!-------------------------------------------------------------------
!
DO jk = 1, nlay_i ! Sea ice energy of melting
DO ji = 1, npti
ztmelts = - rTmlt * sz_i_1d(ji,jk)
t_i_1d(ji,jk) = MIN( t_i_1d(ji,jk), ztmelts + rt0 ) ! Force t_i_1d to be lower than melting point => likely conservation issue
! (sometimes zdf scheme produces abnormally high temperatures)
e_i_1d(ji,jk) = rhoi * ( rcpi * ( ztmelts - ( t_i_1d(ji,jk) - rt0 ) ) &
& + rLfus * ( 1._wp - ztmelts / ( t_i_1d(ji,jk) - rt0 ) ) &
& - rcp * ztmelts )
END DO
END DO
DO jk = 1, nlay_s ! Snow energy of melting
DO ji = 1, npti
e_s_1d(ji,jk) = rhos * ( rcpi * ( rt0 - t_s_1d(ji,jk) ) + rLfus )
END DO
END DO
!
END SUBROUTINE ice_var_enthalpy
FUNCTION ice_var_sshdyn(pssh, psnwice_mass, psnwice_mass_b)
!!---------------------------------------------------------------------
!! *** ROUTINE ice_var_sshdyn ***
!!
!! ** Purpose : compute the equivalent ssh in lead when sea ice is embedded
!!
!! ** Method : ssh_lead = ssh + (Mice + Msnow) / rho0
!!
!! ** Reference : Jean-Michel Campin, John Marshall, David Ferreira,
!! Sea ice-ocean coupling using a rescaled vertical coordinate z*,
!! Ocean Modelling, Volume 24, Issues 1-2, 2008
!!----------------------------------------------------------------------
!
! input
REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pssh !: ssh [m]
REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: psnwice_mass !: mass of snow and ice at current ice time step [Kg/m2]
REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: psnwice_mass_b !: mass of snow and ice at previous ice time step [Kg/m2]
!
! output
REAL(wp), DIMENSION(jpi,jpj) :: ice_var_sshdyn ! equivalent ssh in lead [m]
!
! temporary
REAL(wp) :: zintn, zintb ! time interpolation weights []
!
! compute ice load used to define the equivalent ssh in lead
IF( ln_ice_embd ) THEN
!
! average interpolation coeff as used in dynspg = (1/nn_fsbc) * {SUM[n/nn_fsbc], n=0,nn_fsbc-1}
! = (1/nn_fsbc)^2 * {SUM[n] , n=0,nn_fsbc-1}
zintn = REAL( nn_fsbc - 1 ) / REAL( nn_fsbc ) * 0.5_wp
!
! average interpolation coeff as used in dynspg = (1/nn_fsbc) * {SUM[1-n/nn_fsbc], n=0,nn_fsbc-1}
! = (1/nn_fsbc)^2 * (nn_fsbc^2 - {SUM[n], n=0,nn_fsbc-1})
zintb = REAL( nn_fsbc + 1 ) / REAL( nn_fsbc ) * 0.5_wp
!
! compute equivalent ssh in lead
ice_var_sshdyn(:,:) = pssh(:,:) + ( zintn * psnwice_mass(:,:) + zintb * psnwice_mass_b(:,:) ) * r1_rho0
!
ELSE
! compute equivalent ssh in lead
ice_var_sshdyn(:,:) = pssh(:,:)
ENDIF
!
END FUNCTION ice_var_sshdyn
!!-------------------------------------------------------------------
!! *** INTERFACE ice_var_itd ***
!!
!! ** Purpose : converting N-cat ice to jpl ice categories
!!-------------------------------------------------------------------
SUBROUTINE ice_var_itd_1c1c( phti, phts, pati , ph_i, ph_s, pa_i, &
& ptmi, ptms, ptmsu, psmi, patip, phtip, phtil, pt_i, pt_s, pt_su, ps_i, pa_ip, ph_ip, ph_il )
!!-------------------------------------------------------------------
!! ** Purpose : converting 1-cat ice to 1 ice category
!!-------------------------------------------------------------------
REAL(wp), DIMENSION(:), INTENT(in) :: phti, phts, pati ! input ice/snow variables
REAL(wp), DIMENSION(:), INTENT(inout) :: ph_i, ph_s, pa_i ! output ice/snow variables
REAL(wp), DIMENSION(:), INTENT(in) :: ptmi, ptms, ptmsu, psmi, patip, phtip, phtil ! input ice/snow temp & sal & ponds
REAL(wp), DIMENSION(:), INTENT(inout) :: pt_i, pt_s, pt_su, ps_i, pa_ip, ph_ip, ph_il ! output ice/snow temp & sal & ponds
!!-------------------------------------------------------------------
! == thickness and concentration == !
ph_i(:) = phti(:)
ph_s(:) = phts(:)
pa_i(:) = pati(:)
!
! == temperature and salinity and ponds == !
pt_i (:) = ptmi (:)
pt_s (:) = ptms (:)
pt_su(:) = ptmsu(:)
ps_i (:) = psmi (:)
pa_ip(:) = patip(:)
ph_ip(:) = phtip(:)
ph_il(:) = phtil(:)
END SUBROUTINE ice_var_itd_1c1c
SUBROUTINE ice_var_itd_Nc1c( phti, phts, pati , ph_i, ph_s, pa_i, &
& ptmi, ptms, ptmsu, psmi, patip, phtip, phtil, pt_i, pt_s, pt_su, ps_i, pa_ip, ph_ip, ph_il )
!!-------------------------------------------------------------------
!! ** Purpose : converting N-cat ice to 1 ice category
!!-------------------------------------------------------------------
REAL(wp), DIMENSION(:,:), INTENT(in) :: phti, phts, pati ! input ice/snow variables
REAL(wp), DIMENSION(:) , INTENT(inout) :: ph_i, ph_s, pa_i ! output ice/snow variables
REAL(wp), DIMENSION(:,:), INTENT(in) :: ptmi, ptms, ptmsu, psmi, patip, phtip, phtil ! input ice/snow temp & sal & ponds
REAL(wp), DIMENSION(:) , INTENT(inout) :: pt_i, pt_s, pt_su, ps_i, pa_ip, ph_ip, ph_il ! output ice/snow temp & sal & ponds
!
REAL(wp), ALLOCATABLE, DIMENSION(:) :: z1_ai, z1_vi, z1_vs
!
INTEGER :: idim
!!-------------------------------------------------------------------
!
idim = SIZE( phti, 1 )
!
! == thickness and concentration == !
ALLOCATE( z1_ai(idim), z1_vi(idim), z1_vs(idim) )
!
pa_i(:) = SUM( pati(:,:), dim=2 )
WHERE( ( pa_i(:) ) /= 0._wp ) ; z1_ai(:) = 1._wp / pa_i(:)
ELSEWHERE ; z1_ai(:) = 0._wp
END WHERE
ph_i(:) = SUM( phti(:,:) * pati(:,:), dim=2 ) * z1_ai(:)
ph_s(:) = SUM( phts(:,:) * pati(:,:), dim=2 ) * z1_ai(:)
!
! == temperature and salinity == !
WHERE( ( pa_i(:) * ph_i(:) ) /= 0._wp ) ; z1_vi(:) = 1._wp / ( pa_i(:) * ph_i(:) )
ELSEWHERE ; z1_vi(:) = 0._wp
END WHERE
WHERE( ( pa_i(:) * ph_s(:) ) /= 0._wp ) ; z1_vs(:) = 1._wp / ( pa_i(:) * ph_s(:) )
ELSEWHERE ; z1_vs(:) = 0._wp
END WHERE
pt_i (:) = SUM( ptmi (:,:) * pati(:,:) * phti(:,:), dim=2 ) * z1_vi(:)
pt_s (:) = SUM( ptms (:,:) * pati(:,:) * phts(:,:), dim=2 ) * z1_vs(:)
pt_su(:) = SUM( ptmsu(:,:) * pati(:,:) , dim=2 ) * z1_ai(:)
ps_i (:) = SUM( psmi (:,:) * pati(:,:) * phti(:,:), dim=2 ) * z1_vi(:)
! == ponds == !
pa_ip(:) = SUM( patip(:,:), dim=2 )
WHERE( pa_ip(:) /= 0._wp )
ph_ip(:) = SUM( phtip(:,:) * patip(:,:), dim=2 ) / pa_ip(:)
ph_il(:) = SUM( phtil(:,:) * patip(:,:), dim=2 ) / pa_ip(:)
ELSEWHERE
ph_ip(:) = 0._wp
ph_il(:) = 0._wp
END WHERE
!
DEALLOCATE( z1_ai, z1_vi, z1_vs )
!
END SUBROUTINE ice_var_itd_Nc1c
SUBROUTINE ice_var_itd_1cMc( phti, phts, pati , ph_i, ph_s, pa_i, &
& ptmi, ptms, ptmsu, psmi, patip, phtip, phtil, pt_i, pt_s, pt_su, ps_i, pa_ip, ph_ip, ph_il )
!!-------------------------------------------------------------------
!!
!! ** Purpose : converting 1-cat ice to jpl ice categories
!!
!!
!! ** Method: ice thickness distribution follows a gamma function from Abraham et al. (2015)
!! it has the property of conserving total concentration and volume
!!
!!
!! ** Arguments : phti: 1-cat ice thickness
!! phts: 1-cat snow depth
!! pati: 1-cat ice concentration
!!
!! ** Output : jpl-cat
!!
!! Abraham, C., Steiner, N., Monahan, A. and Michel, C., 2015.
!! Effects of subgrid‐scale snow thickness variability on radiative transfer in sea ice.
!! Journal of Geophysical Research: Oceans, 120(8), pp.5597-5614
!!-------------------------------------------------------------------
REAL(wp), DIMENSION(:), INTENT(in) :: phti, phts, pati ! input ice/snow variables
REAL(wp), DIMENSION(:,:), INTENT(inout) :: ph_i, ph_s, pa_i ! output ice/snow variables
REAL(wp), DIMENSION(:) , INTENT(in) :: ptmi, ptms, ptmsu, psmi, patip, phtip, phtil ! input ice/snow temp & sal & ponds
REAL(wp), DIMENSION(:,:), INTENT(inout) :: pt_i, pt_s, pt_su, ps_i, pa_ip, ph_ip, ph_il ! output ice/snow temp & sal & ponds
!
REAL(wp), ALLOCATABLE, DIMENSION(:) :: zfra, z1_hti
INTEGER :: ji, jk, jl
INTEGER :: idim
REAL(wp) :: zv, zdh
!!-------------------------------------------------------------------
!
idim = SIZE( phti , 1 )
!
ph_i(1:idim,1:jpl) = 0._wp
ph_s(1:idim,1:jpl) = 0._wp
pa_i(1:idim,1:jpl) = 0._wp
!
ALLOCATE( z1_hti(idim) )
WHERE( phti(:) /= 0._wp ) ; z1_hti(:) = 1._wp / phti(:)
ELSEWHERE ; z1_hti(:) = 0._wp
END WHERE
!
! == thickness and concentration == !
! for categories 1:jpl-1, integrate the gamma function from hi_max(jl-1) to hi_max(jl)
DO jl = 1, jpl-1
DO ji = 1, idim
!
IF( phti(ji) > 0._wp ) THEN
! concentration : integrate ((4A/H^2)xexp(-2x/H))dx from x=hi_max(jl-1) to hi_max(jl)
pa_i(ji,jl) = pati(ji) * z1_hti(ji) * ( ( phti(ji) + 2.*hi_max(jl-1) ) * EXP( -2.*hi_max(jl-1)*z1_hti(ji) ) &
& - ( phti(ji) + 2.*hi_max(jl ) ) * EXP( -2.*hi_max(jl )*z1_hti(ji) ) )
!
! volume : integrate ((4A/H^2)x^2exp(-2x/H))dx from x=hi_max(jl-1) to hi_max(jl)
zv = pati(ji) * z1_hti(ji) * ( ( phti(ji)*phti(ji) + 2.*phti(ji)*hi_max(jl-1) + 2.*hi_max(jl-1)*hi_max(jl-1) ) &
& * EXP( -2.*hi_max(jl-1)*z1_hti(ji) ) &
& - ( phti(ji)*phti(ji) + 2.*phti(ji)*hi_max(jl) + 2.*hi_max(jl)*hi_max(jl) ) &
& * EXP(-2.*hi_max(jl)*z1_hti(ji)) )
! thickness
IF( pa_i(ji,jl) > epsi06 ) THEN
ph_i(ji,jl) = zv / pa_i(ji,jl)
ELSE
ph_i(ji,jl) = 0.
pa_i(ji,jl) = 0.
ENDIF
ENDIF
!
ENDDO
ENDDO
!
! for the last category (jpl), integrate the gamma function from hi_max(jpl-1) to infinity
DO ji = 1, idim
!
IF( phti(ji) > 0._wp ) THEN
! concentration : integrate ((4A/H^2)xexp(-2x/H))dx from x=hi_max(jpl-1) to infinity
pa_i(ji,jpl) = pati(ji) * z1_hti(ji) * ( phti(ji) + 2.*hi_max(jpl-1) ) * EXP( -2.*hi_max(jpl-1)*z1_hti(ji) )
! volume : integrate ((4A/H^2)x^2exp(-2x/H))dx from x=hi_max(jpl-1) to infinity
zv = pati(ji) * z1_hti(ji) * ( phti(ji)*phti(ji) + 2.*phti(ji)*hi_max(jpl-1) + 2.*hi_max(jpl-1)*hi_max(jpl-1) ) &
& * EXP( -2.*hi_max(jpl-1)*z1_hti(ji) )
! thickness
IF( pa_i(ji,jpl) > epsi06 ) THEN
ph_i(ji,jpl) = zv / pa_i(ji,jpl)
else
ph_i(ji,jpl) = 0.
pa_i(ji,jpl) = 0.
ENDIF
ENDIF
!
ENDDO
!
! Add Snow in each category where pa_i is not 0
DO jl = 1, jpl
DO ji = 1, idim
IF( pa_i(ji,jl) > 0._wp ) THEN
ph_s(ji,jl) = ph_i(ji,jl) * phts(ji) * z1_hti(ji)
! In case snow load is in excess that would lead to transformation from snow to ice
! Then, transfer the snow excess into the ice (different from icethd_dh)
zdh = MAX( 0._wp, ( rhos * ph_s(ji,jl) + ( rhoi - rho0 ) * ph_i(ji,jl) ) * r1_rho0 )
! recompute h_i, h_s avoiding out of bounds values
ph_i(ji,jl) = MIN( hi_max(jl), ph_i(ji,jl) + zdh )
ph_s(ji,jl) = MAX( 0._wp, ph_s(ji,jl) - zdh * rhoi * r1_rhos )
ENDIF
END DO
END DO
!
DEALLOCATE( z1_hti )
!
! == temperature and salinity == !