From 4e041290c37081c2c735b95310888be3b4d9825e Mon Sep 17 00:00:00 2001 From: clem <clement.rousset@locean.ipsl.fr> Date: Tue, 4 Oct 2022 20:52:52 +0200 Subject: [PATCH] first steps of improvements of memory footprint in ice routines --- src/ICE/ice1d.F90 | 6 + src/ICE/icecor.F90 | 7 +- src/ICE/icedyn_rdgrft.F90 | 200 ++++++++------------- src/ICE/iceitd.F90 | 118 ++++-------- src/ICE/icetab.F90 | 83 ++++++++- src/ICE/icethd_do.F90 | 28 +-- src/ICE/icethd_zdf_bl99.F90 | 347 +++++++++++++++--------------------- 7 files changed, 350 insertions(+), 439 deletions(-) diff --git a/src/ICE/ice1d.F90 b/src/ICE/ice1d.F90 index 8c610bf49..89ac7118f 100644 --- a/src/ICE/ice1d.F90 +++ b/src/ICE/ice1d.F90 @@ -166,6 +166,9 @@ MODULE ice1D REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: a_ib_2d REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:) :: h_ib_2d + + REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: e_i_2d + REAL(wp), PUBLIC, ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: e_s_2d !!---------------------------------------------------------------------- !! NEMO/ICE 4.0 , NEMO Consortium (2018) @@ -235,6 +238,9 @@ CONTAINS & v_i_2d (jpij,jpl) , v_s_2d (jpij,jpl) , oa_i_2d(jpij,jpl) , sv_i_2d(jpij,jpl) , & & a_ip_2d(jpij,jpl) , v_ip_2d(jpij,jpl) , t_su_2d(jpij,jpl) , v_il_2d(jpij,jpl) , & & STAT=ierr(ii) ) + ! + ii = ii + 1 + ALLOCATE( e_i_2d(jpij,nlay_i,jpl) , e_s_2d(jpij,nlay_s,jpl) , STAT=ierr(ii) ) ice1D_alloc = MAXVAL( ierr(:) ) IF( ice1D_alloc /= 0 ) CALL ctl_stop( 'STOP', 'ice1D_alloc: failed to allocate arrays.' ) diff --git a/src/ICE/icecor.F90 b/src/ICE/icecor.F90 index 0b7b53e6a..3c45c3aef 100644 --- a/src/ICE/icecor.F90 +++ b/src/ICE/icecor.F90 @@ -71,7 +71,10 @@ CONTAINS WHERE( a_i(:,:,:) >= epsi20 ) ; h_i(:,:,:) = v_i(:,:,:) / a_i(:,:,:) ELSEWHERE ; h_i(:,:,:) = 0._wp END WHERE - WHERE( h_i(:,:,:) < rn_himin ) a_i(:,:,:) = a_i(:,:,:) * h_i(:,:,:) / rn_himin + IF( ln_pnd_LEV .OR. ln_pnd_TOPO ) THEN + WHERE( h_i(:,:,:) < rn_himin ) a_ip(:,:,:) = a_ip(:,:,:) * h_i(:,:,:) / rn_himin + ENDIF + WHERE( h_i(:,:,:) < rn_himin ) a_i(:,:,:) = a_i (:,:,:) * h_i(:,:,:) / rn_himin ! ! !----------------------------------------------------- ! ! ice concentration should not exceed amax ! @@ -83,7 +86,7 @@ CONTAINS ! !----------------------------------------------------- ! ! Rebin categories with thickness out of bounds ! ! !----------------------------------------------------- - IF ( jpl > 1 ) CALL ice_itd_reb( kt ) + IF( jpl > 1 ) CALL ice_itd_reb( kt ) ! ! !----------------------------------------------------- IF ( nn_icesal == 2 ) THEN ! salinity must stay in bounds [Simin,Simax] ! diff --git a/src/ICE/icedyn_rdgrft.F90 b/src/ICE/icedyn_rdgrft.F90 index 0f6afe0fb..e083da9c5 100644 --- a/src/ICE/icedyn_rdgrft.F90 +++ b/src/ICE/icedyn_rdgrft.F90 @@ -56,8 +56,6 @@ MODULE icedyn_rdgrft REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: hi_hrdg ! thickness of ridging ice / mean ridge thickness REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: aridge ! participating ice ridging REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:) :: araft ! participating ice rafting - REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: ze_i_2d - REAL(wp), ALLOCATABLE, SAVE, DIMENSION(:,:,:) :: ze_s_2d ! REAL(wp), PARAMETER :: hrdg_hi_min = 1.1_wp ! min ridge thickness multiplier: min(hrdg/hi) REAL(wp), PARAMETER :: hi_hrft = 0.5_wp ! rafting multiplier: (hi/hraft) @@ -103,7 +101,7 @@ CONTAINS ALLOCATE( closing_net(jpij) , opning(jpij) , closing_gross(jpij), & & apartf(jpij,0:jpl), hrmin (jpij,jpl), hraft(jpij,jpl) , aridge(jpij,jpl), & & hrmax (jpij,jpl) , hrexp (jpij,jpl), hi_hrdg(jpij,jpl) , araft(jpij,jpl) , & - & ze_i_2d(jpij,nlay_i,jpl), ze_s_2d(jpij,nlay_s,jpl), STAT=ice_dyn_rdgrft_alloc ) + & STAT=ice_dyn_rdgrft_alloc ) CALL mpp_sum ( 'icedyn_rdgrft', ice_dyn_rdgrft_alloc ) IF( ice_dyn_rdgrft_alloc /= 0 ) CALL ctl_stop( 'STOP', 'ice_dyn_rdgrft_alloc: failed to allocate arrays' ) @@ -573,9 +571,9 @@ CONTAINS REAL(wp), DIMENSION(jpij) :: airdg2, oirdg2, aprdg2, virdg2, sirdg2, vsrdg, vprdg, vlrdg ! area etc of new ridges REAL(wp), DIMENSION(jpij) :: airft2, oirft2, aprft2, virft , sirft , vsrft, vprft, vlrft ! area etc of rafted ice ! - REAL(wp), DIMENSION(jpij) :: ersw ! enth of water trapped into ridges - REAL(wp), DIMENSION(jpij) :: zswitch, fvol ! new ridge volume going to jl2 - REAL(wp), DIMENSION(jpij) :: z1_ai ! 1 / a + REAL(wp) :: ersw ! enthalpy of water trapped into ridges + REAL(wp) :: zswitch, fvol ! new ridge volume going to jl2 + REAL(wp) :: z1_ai ! 1 / a REAL(wp), DIMENSION(jpij) :: zvti ! sum(v_i) ! REAL(wp), DIMENSION(jpij,nlay_s) :: esrft ! snow energy of rafting ice @@ -612,8 +610,8 @@ CONTAINS IF( ll_shift(ji) ) THEN ! only if ice is ridging - IF( a_i_2d(ji,jl1) > epsi10 ) THEN ; z1_ai(ji) = 1._wp / a_i_2d(ji,jl1) - ELSE ; z1_ai(ji) = 0._wp + IF( a_i_2d(ji,jl1) > epsi10 ) THEN ; z1_ai = 1._wp / a_i_2d(ji,jl1) + ELSE ; z1_ai = 0._wp ENDIF ! area of ridging / rafting ice (airdg1) and of new ridge (airdg2) @@ -624,15 +622,15 @@ CONTAINS airft2(ji) = airft1 * hi_hrft ! ridging /rafting fractions - afrdg = airdg1 * z1_ai(ji) - afrft = airft1 * z1_ai(ji) + afrdg = airdg1 * z1_ai + afrft = airft1 * z1_ai ! volume and enthalpy (J/m2, >0) of seawater trapped into ridges IF ( zvti(ji) <= 10. ) THEN ; vsw = v_i_2d(ji,jl1) * afrdg * rn_porordg ! v <= 10m then porosity = rn_porordg ELSEIF( zvti(ji) >= 20. ) THEN ; vsw = 0._wp ! v >= 20m then porosity = 0 ELSE ; vsw = v_i_2d(ji,jl1) * afrdg * rn_porordg * MAX( 0._wp, 2._wp - 0.1_wp * zvti(ji) ) ! v > 10m and v < 20m then porosity = linear transition to 0 ENDIF - ersw(ji) = -rhoi * vsw * rcp * sst_1d(ji) ! clem: if sst>0, then ersw <0 (is that possible?) + ersw = -rhoi * vsw * rcp * sst_1d(ji) ! clem: if sst>0, then ersw <0 (is that possible?) ! volume etc of ridging / rafting ice and new ridges (vi, vs, sm, oi, es, ei) virdg1 = v_i_2d (ji,jl1) * afrdg @@ -661,16 +659,29 @@ CONTAINS vlrft (ji) = v_il_2d(ji,jl1) * afrft ENDIF ENDIF + + DO jk = 1, nlay_s + esrdg(ji,jk) = e_s_2d (ji,jk,jl1) * afrdg + esrft(ji,jk) = e_s_2d (ji,jk,jl1) * afrft + END DO + DO jk = 1, nlay_i + eirdg(ji,jk) = e_i_2d (ji,jk,jl1) * afrdg + ersw * r1_nlay_i + eirft(ji,jk) = e_i_2d (ji,jk,jl1) * afrft + END DO ! Ice-ocean exchanges associated with ice porosity wfx_dyn_1d(ji) = wfx_dyn_1d(ji) - vsw * rhoi * r1_Dt_ice ! increase in ice volume due to seawater frozen in voids sfx_dyn_1d(ji) = sfx_dyn_1d(ji) - vsw * sss_1d(ji) * rhoi * r1_Dt_ice - hfx_dyn_1d(ji) = hfx_dyn_1d(ji) + ersw(ji) * r1_Dt_ice ! > 0 [W.m-2] + hfx_dyn_1d(ji) = hfx_dyn_1d(ji) + ersw * r1_Dt_ice ! > 0 [W.m-2] ! Put the snow lost by ridging into the ocean ! Note that esrdg > 0; the ocean must cool to melt snow. If the ocean temp = Tf already, new ice must grow. wfx_snw_dyn_1d(ji) = wfx_snw_dyn_1d(ji) + ( rhos * vsrdg(ji) * ( 1._wp - rn_fsnwrdg ) & ! fresh water source for ocean & + rhos * vsrft(ji) * ( 1._wp - rn_fsnwrft ) ) * r1_Dt_ice + DO jk = 1, nlay_s + hfx_dyn_1d(ji) = hfx_dyn_1d(ji) + ( - esrdg(ji,jk) * ( 1._wp - rn_fsnwrdg ) & ! heat sink for ocean (<0, W.m-2) + & - esrft(ji,jk) * ( 1._wp - rn_fsnwrft ) ) * r1_Dt_ice + END DO ! virtual salt flux to keep salinity constant IF( nn_icesal /= 2 ) THEN @@ -693,49 +704,18 @@ CONTAINS v_il_2d(ji,jl1) = v_il_2d(ji,jl1) - vlrdg(ji) - vlrft(ji) ENDIF ENDIF + DO jk = 1, nlay_s + e_s_2d(ji,jk,jl1) = e_s_2d(ji,jk,jl1) * ( 1._wp - afrdg - afrft ) + END DO + DO jk = 1, nlay_i + e_i_2d(ji,jk,jl1) = e_i_2d(ji,jk,jl1) * ( 1._wp - afrdg - afrft ) + END DO + ENDIF - + END DO ! ji - - ! special loop for e_s because of layers jk - DO jk = 1, nlay_s - DO ji = 1, npti - IF( ll_shift(ji) ) THEN - ! Compute ridging /rafting fractions - afrdg = aridge(ji,jl1) * closing_gross(ji) * rDt_ice * z1_ai(ji) - afrft = araft (ji,jl1) * closing_gross(ji) * rDt_ice * z1_ai(ji) - ! Compute ridging /rafting ice and new ridges for es - esrdg(ji,jk) = ze_s_2d (ji,jk,jl1) * afrdg - esrft(ji,jk) = ze_s_2d (ji,jk,jl1) * afrft - ! Put the snow lost by ridging into the ocean - hfx_dyn_1d(ji) = hfx_dyn_1d(ji) + ( - esrdg(ji,jk) * ( 1._wp - rn_fsnwrdg ) & ! heat sink for ocean (<0, W.m-2) - & - esrft(ji,jk) * ( 1._wp - rn_fsnwrft ) ) * r1_Dt_ice - ! - ! Remove energy of new ridge to each category jl1 - !------------------------------------------------- - ze_s_2d(ji,jk,jl1) = ze_s_2d(ji,jk,jl1) * ( 1._wp - afrdg - afrft ) - ENDIF - END DO - END DO - - ! special loop for e_i because of layers jk - DO jk = 1, nlay_i - DO ji = 1, npti - IF( ll_shift(ji) ) THEN - ! Compute ridging /rafting fractions - afrdg = aridge(ji,jl1) * closing_gross(ji) * rDt_ice * z1_ai(ji) - afrft = araft (ji,jl1) * closing_gross(ji) * rDt_ice * z1_ai(ji) - ! Compute ridging ice and new ridges for ei - eirdg(ji,jk) = ze_i_2d (ji,jk,jl1) * afrdg + ersw(ji) * r1_nlay_i - eirft(ji,jk) = ze_i_2d (ji,jk,jl1) * afrft - ! - ! Remove energy of new ridge to each category jl1 - !------------------------------------------------- - ze_i_2d(ji,jk,jl1) = ze_i_2d(ji,jk,jl1) * ( 1._wp - afrdg - afrft ) - ENDIF - END DO - END DO - + + ! 3) compute categories in which ice is added (jl2) !-------------------------------------------------- itest_rdg(1:npti) = 0 @@ -752,13 +732,13 @@ CONTAINS IF( hrmin(ji,jl1) <= hi_max(jl2) .AND. hrmax(ji,jl1) > hi_max(jl2-1) ) THEN hL = MAX( hrmin(ji,jl1), hi_max(jl2-1) ) hR = MIN( hrmax(ji,jl1), hi_max(jl2) ) - farea = ( hR - hL ) / ( hrmax(ji,jl1) - hrmin(ji,jl1) ) - fvol(ji) = ( hR * hR - hL * hL ) / ( hrmax(ji,jl1) * hrmax(ji,jl1) - hrmin(ji,jl1) * hrmin(ji,jl1) ) + farea = ( hR - hL ) / ( hrmax(ji,jl1) - hrmin(ji,jl1) ) + fvol = ( hR * hR - hL * hL ) / ( hrmax(ji,jl1) * hrmax(ji,jl1) - hrmin(ji,jl1) * hrmin(ji,jl1) ) ! itest_rdg(ji) = 1 ! test for conservation ELSE - farea = 0._wp - fvol(ji) = 0._wp + farea = 0._wp + fvol = 0._wp ENDIF ! ELSEIF( ln_distf_exp ) THEN ! Lipscomb et al. (2007) exponential formulation @@ -766,24 +746,24 @@ CONTAINS IF( jl2 < jpl ) THEN ! IF( hrmin(ji,jl1) <= hi_max(jl2) ) THEN - hL = MAX( hrmin(ji,jl1), hi_max(jl2-1) ) - hR = hi_max(jl2) - expL = EXP( -( hL - hrmin(ji,jl1) ) / hrexp(ji,jl1) ) - expR = EXP( -( hR - hrmin(ji,jl1) ) / hrexp(ji,jl1) ) - farea = expL - expR - fvol(ji) = ( ( hL + hrexp(ji,jl1) ) * expL & - - ( hR + hrexp(ji,jl1) ) * expR ) / ( hrmin(ji,jl1) + hrexp(ji,jl1) ) + hL = MAX( hrmin(ji,jl1), hi_max(jl2-1) ) + hR = hi_max(jl2) + expL = EXP( -( hL - hrmin(ji,jl1) ) / hrexp(ji,jl1) ) + expR = EXP( -( hR - hrmin(ji,jl1) ) / hrexp(ji,jl1) ) + farea = expL - expR + fvol = ( ( hL + hrexp(ji,jl1) ) * expL & + & - ( hR + hrexp(ji,jl1) ) * expR ) / ( hrmin(ji,jl1) + hrexp(ji,jl1) ) ELSE - farea = 0._wp - fvol(ji) = 0._wp + farea = 0._wp + fvol = 0._wp END IF ! ELSE ! jl2 = jpl ! - hL = MAX( hrmin(ji,jl1), hi_max(jl2-1) ) - expL = EXP(-( hL - hrmin(ji,jl1) ) / hrexp(ji,jl1) ) - farea = expL - fvol(ji) = ( hL + hrexp(ji,jl1) ) * expL / ( hrmin(ji,jl1) + hrexp(ji,jl1) ) + hL = MAX( hrmin(ji,jl1), hi_max(jl2-1) ) + expL = EXP(-( hL - hrmin(ji,jl1) ) / hrexp(ji,jl1) ) + farea = expL + fvol = ( hL + hrexp(ji,jl1) ) * expL / ( hrmin(ji,jl1) + hrexp(ji,jl1) ) ! END IF ! jl2 < jpl ! @@ -793,59 +773,49 @@ CONTAINS ! Compute the fraction of rafted ice area and volume going to thickness category jl2 IF( hraft(ji,jl1) <= hi_max(jl2) .AND. hraft(ji,jl1) > hi_max(jl2-1) ) THEN - zswitch(ji) = 1._wp + zswitch = 1._wp ! itest_rft(ji) = 1 ! test for conservation ELSE - zswitch(ji) = 0._wp + zswitch = 0._wp ENDIF ! ! Patch to ensure perfect conservation if ice thickness goes mad ! Sometimes thickness is larger than hi_max(jpl) because of advection scheme (for very small areas) ! Then ice volume is removed from one category but the ridging/rafting scheme ! does not know where to move it, leading to a conservation issue. - IF( itest_rdg(ji) == 0 .AND. jl2 == jpl ) THEN ; farea = 1._wp ; fvol(ji) = 1._wp ; ENDIF - IF( itest_rft(ji) == 0 .AND. jl2 == jpl ) zswitch(ji) = 1._wp + IF( itest_rdg(ji) == 0 .AND. jl2 == jpl ) THEN ; farea = 1._wp ; fvol = 1._wp ; ENDIF + IF( itest_rft(ji) == 0 .AND. jl2 == jpl ) zswitch = 1._wp ! ! Add area, volume of new ridge to category jl2 !---------------------------------------------- - a_i_2d (ji,jl2) = a_i_2d (ji,jl2) + ( airdg2(ji) * farea + airft2(ji) * zswitch(ji) ) - oa_i_2d(ji,jl2) = oa_i_2d(ji,jl2) + ( oirdg2(ji) * farea + oirft2(ji) * zswitch(ji) ) - v_i_2d (ji,jl2) = v_i_2d (ji,jl2) + ( virdg2(ji) * fvol(ji) + virft (ji) * zswitch(ji) ) - sv_i_2d(ji,jl2) = sv_i_2d(ji,jl2) + ( sirdg2(ji) * fvol(ji) + sirft (ji) * zswitch(ji) ) - v_s_2d (ji,jl2) = v_s_2d (ji,jl2) + ( vsrdg (ji) * rn_fsnwrdg * fvol(ji) + & - & vsrft (ji) * rn_fsnwrft * zswitch(ji) ) + a_i_2d (ji,jl2) = a_i_2d (ji,jl2) + ( airdg2(ji) * farea + airft2(ji) * zswitch ) + oa_i_2d(ji,jl2) = oa_i_2d(ji,jl2) + ( oirdg2(ji) * farea + oirft2(ji) * zswitch ) + v_i_2d (ji,jl2) = v_i_2d (ji,jl2) + ( virdg2(ji) * fvol + virft (ji) * zswitch ) + sv_i_2d(ji,jl2) = sv_i_2d(ji,jl2) + ( sirdg2(ji) * fvol + sirft (ji) * zswitch ) + v_s_2d (ji,jl2) = v_s_2d (ji,jl2) + ( vsrdg (ji) * rn_fsnwrdg * fvol + & + & vsrft (ji) * rn_fsnwrft * zswitch ) IF ( ln_pnd_LEV .OR. ln_pnd_TOPO ) THEN - v_ip_2d (ji,jl2) = v_ip_2d(ji,jl2) + ( vprdg (ji) * rn_fpndrdg * fvol (ji) & - & + vprft (ji) * rn_fpndrft * zswitch(ji) ) - a_ip_2d (ji,jl2) = a_ip_2d(ji,jl2) + ( aprdg2(ji) * rn_fpndrdg * farea & - & + aprft2(ji) * rn_fpndrft * zswitch(ji) ) + v_ip_2d (ji,jl2) = v_ip_2d(ji,jl2) + ( vprdg (ji) * rn_fpndrdg * fvol & + & + vprft (ji) * rn_fpndrft * zswitch ) + a_ip_2d (ji,jl2) = a_ip_2d(ji,jl2) + ( aprdg2(ji) * rn_fpndrdg * farea & + & + aprft2(ji) * rn_fpndrft * zswitch ) IF ( ln_pnd_lids ) THEN - v_il_2d (ji,jl2) = v_il_2d(ji,jl2) + ( vlrdg(ji) * rn_fpndrdg * fvol (ji) & - & + vlrft(ji) * rn_fpndrft * zswitch(ji) ) + v_il_2d (ji,jl2) = v_il_2d(ji,jl2) + ( vlrdg(ji) * rn_fpndrdg * fvol & + & + vlrft(ji) * rn_fpndrft * zswitch ) ENDIF ENDIF - + DO jk = 1, nlay_s + e_s_2d(ji,jk,jl2) = e_s_2d(ji,jk,jl2) + ( esrdg(ji,jk) * rn_fsnwrdg * fvol + & + & esrft(ji,jk) * rn_fsnwrft * zswitch ) + END DO + DO jk = 1, nlay_i + e_i_2d(ji,jk,jl2) = e_i_2d(ji,jk,jl2) + eirdg(ji,jk) * fvol + eirft(ji,jk) * zswitch + END DO + ENDIF END DO - ! Add snow energy of new ridge to category jl2 - !--------------------------------------------- - DO jk = 1, nlay_s - DO ji = 1, npti - IF( ll_shift(ji) ) & - & ze_s_2d(ji,jk,jl2) = ze_s_2d(ji,jk,jl2) + ( esrdg(ji,jk) * rn_fsnwrdg * fvol(ji) + & - & esrft(ji,jk) * rn_fsnwrft * zswitch(ji) ) - END DO - END DO - ! Add ice energy of new ridge to category jl2 - !-------------------------------------------- - DO jk = 1, nlay_i - DO ji = 1, npti - IF( ll_shift(ji) ) & - & ze_i_2d(ji,jk,jl2) = ze_i_2d(ji,jk,jl2) + eirdg(ji,jk) * fvol(ji) + eirft(ji,jk) * zswitch(ji) - END DO - END DO ! END DO ! jl2 ! @@ -854,7 +824,7 @@ CONTAINS ! roundoff errors !---------------- ! In case ridging/rafting lead to very small negative values (sometimes it happens) - CALL ice_var_roundoff( a_i_2d, v_i_2d, v_s_2d, sv_i_2d, oa_i_2d, a_ip_2d, v_ip_2d, v_il_2d, ze_s_2d, ze_i_2d ) + CALL ice_var_roundoff( a_i_2d, v_i_2d, v_s_2d, sv_i_2d, oa_i_2d, a_ip_2d, v_ip_2d, v_il_2d, e_s_2d, e_i_2d ) ! END SUBROUTINE rdgrft_shift @@ -1036,14 +1006,8 @@ CONTAINS CALL tab_3d_2d( npti, nptidx(1:npti), a_ip_2d(1:npti,1:jpl), a_ip(:,:,:) ) CALL tab_3d_2d( npti, nptidx(1:npti), v_ip_2d(1:npti,1:jpl), v_ip(:,:,:) ) CALL tab_3d_2d( npti, nptidx(1:npti), v_il_2d(1:npti,1:jpl), v_il(:,:,:) ) - DO jl = 1, jpl - DO jk = 1, nlay_s - CALL tab_2d_1d( npti, nptidx(1:npti), ze_s_2d(1:npti,jk,jl), e_s(:,:,jk,jl) ) - END DO - DO jk = 1, nlay_i - CALL tab_2d_1d( npti, nptidx(1:npti), ze_i_2d(1:npti,jk,jl), e_i(:,:,jk,jl) ) - END DO - END DO + CALL tab_4d_3d( npti, nptidx(1:npti), e_s_2d (1:npti,:,:) , e_s ) + CALL tab_4d_3d( npti, nptidx(1:npti), e_i_2d (1:npti,:,:) , e_i ) CALL tab_2d_1d( npti, nptidx(1:npti), sfx_dyn_1d (1:npti), sfx_dyn (:,:) ) CALL tab_2d_1d( npti, nptidx(1:npti), sfx_bri_1d (1:npti), sfx_bri (:,:) ) CALL tab_2d_1d( npti, nptidx(1:npti), wfx_dyn_1d (1:npti), wfx_dyn (:,:) ) @@ -1063,14 +1027,8 @@ CONTAINS CALL tab_2d_3d( npti, nptidx(1:npti), a_ip_2d(1:npti,1:jpl), a_ip(:,:,:) ) CALL tab_2d_3d( npti, nptidx(1:npti), v_ip_2d(1:npti,1:jpl), v_ip(:,:,:) ) CALL tab_2d_3d( npti, nptidx(1:npti), v_il_2d(1:npti,1:jpl), v_il(:,:,:) ) - DO jl = 1, jpl - DO jk = 1, nlay_s - CALL tab_1d_2d( npti, nptidx(1:npti), ze_s_2d(1:npti,jk,jl), e_s(:,:,jk,jl) ) - END DO - DO jk = 1, nlay_i - CALL tab_1d_2d( npti, nptidx(1:npti), ze_i_2d(1:npti,jk,jl), e_i(:,:,jk,jl) ) - END DO - END DO + CALL tab_3d_4d( npti, nptidx(1:npti), e_s_2d (1:npti,:,:) , e_s ) + CALL tab_3d_4d( npti, nptidx(1:npti), e_i_2d (1:npti,:,:) , e_i ) CALL tab_1d_2d( npti, nptidx(1:npti), sfx_dyn_1d (1:npti), sfx_dyn (:,:) ) CALL tab_1d_2d( npti, nptidx(1:npti), sfx_bri_1d (1:npti), sfx_bri (:,:) ) CALL tab_1d_2d( npti, nptidx(1:npti), wfx_dyn_1d (1:npti), wfx_dyn (:,:) ) diff --git a/src/ICE/iceitd.F90 b/src/ICE/iceitd.F90 index caa37df09..e5ed9a341 100644 --- a/src/ICE/iceitd.F90 +++ b/src/ICE/iceitd.F90 @@ -306,25 +306,6 @@ CONTAINS ! 6) Shift ice between categories !---------------------------------------------------------------------------------------------- CALL itd_shiftice ( jdonor(1:npti,:), zdaice(1:npti,:), zdvice(1:npti,:) ) - - !---------------------------------------------------------------------------------------------- - ! 7) Make sure h_i >= minimum ice thickness hi_min - !---------------------------------------------------------------------------------------------- - CALL tab_2d_1d( npti, nptidx(1:npti), h_i_1d (1:npti), h_i (:,:,1) ) - CALL tab_2d_1d( npti, nptidx(1:npti), a_i_1d (1:npti), a_i (:,:,1) ) - CALL tab_2d_1d( npti, nptidx(1:npti), a_ip_1d(1:npti), a_ip(:,:,1) ) - ! - DO ji = 1, npti - IF ( a_i_1d(ji) > epsi10 .AND. h_i_1d(ji) < rn_himin ) THEN - a_i_1d(ji) = a_i_1d(ji) * h_i_1d(ji) / rn_himin - IF( ln_pnd_LEV .OR. ln_pnd_TOPO ) a_ip_1d(ji) = a_ip_1d(ji) * h_i_1d(ji) / rn_himin - h_i_1d(ji) = rn_himin - ENDIF - END DO - ! - CALL tab_1d_2d( npti, nptidx(1:npti), h_i_1d (1:npti), h_i (:,:,1) ) - CALL tab_1d_2d( npti, nptidx(1:npti), a_i_1d (1:npti), a_i (:,:,1) ) - CALL tab_1d_2d( npti, nptidx(1:npti), a_ip_1d(1:npti), a_ip(:,:,1) ) ! ENDIF ! @@ -415,11 +396,9 @@ CONTAINS ! INTEGER :: ji, jl, jk ! dummy loop indices INTEGER :: jl2, jl1 ! local integers - REAL(wp) :: ztrans ! ice/snow transferred - REAL(wp), DIMENSION(jpij) :: zworka, zworkv ! workspace + REAL(wp) :: zworka, zworkv, ztrans ! ice/snow transferred + REAL(wp), DIMENSION(jpij) :: ztmp ! workspace REAL(wp), DIMENSION(jpij,jpl) :: zaTsfn ! - - - REAL(wp), DIMENSION(jpij,nlay_i,jpl) :: ze_i_2d - REAL(wp), DIMENSION(jpij,nlay_s,jpl) :: ze_s_2d !!------------------------------------------------------------------ CALL tab_3d_2d( npti, nptidx(1:npti), h_i_2d (1:npti,1:jpl), h_i ) @@ -432,14 +411,8 @@ CONTAINS CALL tab_3d_2d( npti, nptidx(1:npti), v_ip_2d(1:npti,1:jpl), v_ip ) CALL tab_3d_2d( npti, nptidx(1:npti), v_il_2d(1:npti,1:jpl), v_il ) CALL tab_3d_2d( npti, nptidx(1:npti), t_su_2d(1:npti,1:jpl), t_su ) - DO jl = 1, jpl - DO jk = 1, nlay_s - CALL tab_2d_1d( npti, nptidx(1:npti), ze_s_2d(1:npti,jk,jl), e_s(:,:,jk,jl) ) - END DO - DO jk = 1, nlay_i - CALL tab_2d_1d( npti, nptidx(1:npti), ze_i_2d(1:npti,jk,jl), e_i(:,:,jk,jl) ) - END DO - END DO + CALL tab_4d_3d( npti, nptidx(1:npti), e_s_2d (1:npti,:,:) , e_s ) + CALL tab_4d_3d( npti, nptidx(1:npti), e_i_2d (1:npti,:,:) , e_i ) ! to correct roundoff errors on a_i CALL tab_2d_1d( npti, nptidx(1:npti), rn_amax_1d(1:npti), rn_amax_2d ) @@ -466,11 +439,11 @@ CONTAINS ELSE ; jl2 = jl ENDIF ! - IF( v_i_2d(ji,jl1) >= epsi10 ) THEN ; zworkv(ji) = pdvice(ji,jl) / v_i_2d(ji,jl1) - ELSE ; zworkv(ji) = 0._wp + IF( v_i_2d(ji,jl1) >= epsi10 ) THEN ; zworkv = pdvice(ji,jl) / v_i_2d(ji,jl1) + ELSE ; zworkv = 0._wp ENDIF - IF( a_i_2d(ji,jl1) >= epsi10 ) THEN ; zworka(ji) = pdaice(ji,jl) / a_i_2d(ji,jl1) - ELSE ; zworka(ji) = 0._wp + IF( a_i_2d(ji,jl1) >= epsi10 ) THEN ; zworka = pdaice(ji,jl) / a_i_2d(ji,jl1) + ELSE ; zworka = 0._wp ENDIF ! a_i_2d(ji,jl1) = a_i_2d(ji,jl1) - pdaice(ji,jl) ! Ice areas @@ -479,71 +452,50 @@ CONTAINS v_i_2d(ji,jl1) = v_i_2d(ji,jl1) - pdvice(ji,jl) ! Ice volumes v_i_2d(ji,jl2) = v_i_2d(ji,jl2) + pdvice(ji,jl) ! - ztrans = v_s_2d(ji,jl1) * zworkv(ji) ! Snow volumes + ztrans = v_s_2d(ji,jl1) * zworkv ! Snow volumes v_s_2d(ji,jl1) = v_s_2d(ji,jl1) - ztrans v_s_2d(ji,jl2) = v_s_2d(ji,jl2) + ztrans ! - ztrans = oa_i_2d(ji,jl1) * zworka(ji) ! Ice age + ztrans = oa_i_2d(ji,jl1) * zworka ! Ice age oa_i_2d(ji,jl1) = oa_i_2d(ji,jl1) - ztrans oa_i_2d(ji,jl2) = oa_i_2d(ji,jl2) + ztrans ! - ztrans = sv_i_2d(ji,jl1) * zworkv(ji) ! Ice salinity + ztrans = sv_i_2d(ji,jl1) * zworkv ! Ice salinity sv_i_2d(ji,jl1) = sv_i_2d(ji,jl1) - ztrans sv_i_2d(ji,jl2) = sv_i_2d(ji,jl2) + ztrans ! - ztrans = zaTsfn(ji,jl1) * zworka(ji) ! Surface temperature + ztrans = zaTsfn(ji,jl1) * zworka ! Surface temperature zaTsfn(ji,jl1) = zaTsfn(ji,jl1) - ztrans zaTsfn(ji,jl2) = zaTsfn(ji,jl2) + ztrans ! IF ( ln_pnd_LEV .OR. ln_pnd_TOPO ) THEN - ztrans = a_ip_2d(ji,jl1) * zworka(ji) ! Pond fraction + ztrans = a_ip_2d(ji,jl1) * zworka ! Pond fraction a_ip_2d(ji,jl1) = a_ip_2d(ji,jl1) - ztrans a_ip_2d(ji,jl2) = a_ip_2d(ji,jl2) + ztrans ! - ztrans = v_ip_2d(ji,jl1) * zworkv(ji) ! Pond volume + ztrans = v_ip_2d(ji,jl1) * zworkv ! Pond volume v_ip_2d(ji,jl1) = v_ip_2d(ji,jl1) - ztrans v_ip_2d(ji,jl2) = v_ip_2d(ji,jl2) + ztrans ! IF ( ln_pnd_lids ) THEN ! Pond lid volume - ztrans = v_il_2d(ji,jl1) * zworkv(ji) + ztrans = v_il_2d(ji,jl1) * zworkv v_il_2d(ji,jl1) = v_il_2d(ji,jl1) - ztrans v_il_2d(ji,jl2) = v_il_2d(ji,jl2) + ztrans ENDIF ENDIF ! - ENDIF ! jl1 >0 - END DO - ! - DO jk = 1, nlay_s !--- Snow heat content - DO ji = 1, npti - ! - jl1 = kdonor(ji,jl) + DO jk = 1, nlay_s ! Snow heat content + ztrans = e_s_2d(ji,jk,jl1) * zworkv + e_s_2d(ji,jk,jl1) = e_s_2d(ji,jk,jl1) - ztrans + e_s_2d(ji,jk,jl2) = e_s_2d(ji,jk,jl2) + ztrans + ENDDO + DO jk = 1, nlay_i ! Ice heat content + ztrans = e_i_2d(ji,jk,jl1) * zworkv + e_i_2d(ji,jk,jl1) = e_i_2d(ji,jk,jl1) - ztrans + e_i_2d(ji,jk,jl2) = e_i_2d(ji,jk,jl2) + ztrans + ENDDO ! - IF( jl1 > 0 ) THEN - IF(jl1 == jl) THEN ; jl2 = jl+1 - ELSE ; jl2 = jl - ENDIF - ztrans = ze_s_2d(ji,jk,jl1) * zworkv(ji) - ze_s_2d(ji,jk,jl1) = ze_s_2d(ji,jk,jl1) - ztrans - ze_s_2d(ji,jk,jl2) = ze_s_2d(ji,jk,jl2) + ztrans - ENDIF - END DO - END DO - ! - DO jk = 1, nlay_i !--- Ice heat content - DO ji = 1, npti - ! - jl1 = kdonor(ji,jl) - ! - IF( jl1 > 0 ) THEN - IF(jl1 == jl) THEN ; jl2 = jl+1 - ELSE ; jl2 = jl - ENDIF - ztrans = ze_i_2d(ji,jk,jl1) * zworkv(ji) - ze_i_2d(ji,jk,jl1) = ze_i_2d(ji,jk,jl1) - ztrans - ze_i_2d(ji,jk,jl2) = ze_i_2d(ji,jk,jl2) + ztrans - ENDIF - END DO + ENDIF ! jl1 >0 END DO ! END DO ! boundaries, 1 to jpl-1 @@ -553,13 +505,13 @@ CONTAINS !------------------- ! clem: The transfer between one category to another can lead to very small negative values (-1.e-20) ! because of truncation error ( i.e. 1. - 1. /= 0 ) - CALL ice_var_roundoff( a_i_2d, v_i_2d, v_s_2d, sv_i_2d, oa_i_2d, a_ip_2d, v_ip_2d, v_il_2d, ze_s_2d, ze_i_2d ) + CALL ice_var_roundoff( a_i_2d, v_i_2d, v_s_2d, sv_i_2d, oa_i_2d, a_ip_2d, v_ip_2d, v_il_2d, e_s_2d, e_i_2d ) ! at_i must be <= rn_amax - zworka(1:npti) = SUM( a_i_2d(1:npti,:), dim=2 ) + ztmp(1:npti) = SUM( a_i_2d(1:npti,:), dim=2 ) DO jl = 1, jpl - WHERE( zworka(1:npti) > rn_amax_1d(1:npti) ) & - & a_i_2d(1:npti,jl) = a_i_2d(1:npti,jl) * rn_amax_1d(1:npti) / zworka(1:npti) + WHERE( ztmp(1:npti) > rn_amax_1d(1:npti) ) & + & a_i_2d(1:npti,jl) = a_i_2d(1:npti,jl) * rn_amax_1d(1:npti) / ztmp(1:npti) END DO !------------------------------------------------------------------------------- @@ -587,14 +539,8 @@ CONTAINS CALL tab_2d_3d( npti, nptidx(1:npti), v_ip_2d(1:npti,1:jpl), v_ip ) CALL tab_2d_3d( npti, nptidx(1:npti), v_il_2d(1:npti,1:jpl), v_il ) CALL tab_2d_3d( npti, nptidx(1:npti), t_su_2d(1:npti,1:jpl), t_su ) - DO jl = 1, jpl - DO jk = 1, nlay_s - CALL tab_1d_2d( npti, nptidx(1:npti), ze_s_2d(1:npti,jk,jl), e_s(:,:,jk,jl) ) - END DO - DO jk = 1, nlay_i - CALL tab_1d_2d( npti, nptidx(1:npti), ze_i_2d(1:npti,jk,jl), e_i(:,:,jk,jl) ) - END DO - END DO + CALL tab_3d_4d( npti, nptidx(1:npti), e_s_2d (1:npti,:,:) , e_s ) + CALL tab_3d_4d( npti, nptidx(1:npti), e_i_2d (1:npti,:,:) , e_i ) ! END SUBROUTINE itd_shiftice diff --git a/src/ICE/icetab.F90 b/src/ICE/icetab.F90 index 02d3501ea..5db21b305 100644 --- a/src/ICE/icetab.F90 +++ b/src/ICE/icetab.F90 @@ -20,8 +20,10 @@ MODULE icetab IMPLICIT NONE PRIVATE + PUBLIC tab_4d_3d PUBLIC tab_3d_2d PUBLIC tab_2d_1d + PUBLIC tab_3d_4d PUBLIC tab_2d_3d PUBLIC tab_1d_2d @@ -32,6 +34,39 @@ MODULE icetab !!---------------------------------------------------------------------- CONTAINS + SUBROUTINE tab_4d_3d( ndim1d, tab_ind, tab1d, tab2d ) + !!---------------------------------------------------------------------- + !! *** ROUTINE tab_2d_1d *** + !!---------------------------------------------------------------------- + INTEGER , INTENT(in ) :: ndim1d ! 1d size + INTEGER , DIMENSION(ndim1d) , INTENT(in ) :: tab_ind ! input index + REAL(wp), DIMENSION(:,:,:,:), INTENT(in ) :: tab2d ! input 2D field + REAL(wp), DIMENSION(:,:,:) , INTENT(inout) :: tab1d ! output 1D field + ! + INTEGER :: ipi, ipj, ipk, ji0, jj0, jk, jl, jn, jid, jjd + !!---------------------------------------------------------------------- + ipi = SIZE(tab2d,1) ! 1st dimension + ipj = SIZE(tab2d,2) ! 2nd dimension + ipk = SIZE(tab2d,3) ! 3d dimension + ! + IF( ipi == jpi .AND. ipj == jpj ) THEN ! full arrays then no need to change index jid and jjd + ji0 = 0 ; jj0 = 0 + ELSE ! reduced arrays then need to shift index by nn_hls + ji0 = nn_hls ; jj0 = nn_hls ! since tab2d is shifted by nn_hls + ENDIF ! (i.e. from hls+1:jpi-hls to 1:jpi-2*hls) + ! + DO jn = 1, ndim1d + jid = MOD( tab_ind(jn) - 1 , jpi ) + 1 - ji0 + jjd = ( tab_ind(jn) - 1 ) / jpi + 1 - jj0 + DO jl = 1, jpl + DO jk = 1, ipk + tab1d(jn,jk,jl) = tab2d(jid,jjd,jk,jl) + END DO + END DO + END DO + ! + END SUBROUTINE tab_4d_3d + SUBROUTINE tab_3d_2d( ndim1d, tab_ind, tab1d, tab2d ) !!---------------------------------------------------------------------- !! *** ROUTINE tab_2d_1d *** @@ -52,10 +87,10 @@ CONTAINS ji0 = nn_hls ; jj0 = nn_hls ! since tab2d is shifted by nn_hls ENDIF ! (i.e. from hls+1:jpi-hls to 1:jpi-2*hls) ! - DO jl = 1, jpl - DO jn = 1, ndim1d - jid = MOD( tab_ind(jn) - 1 , jpi ) + 1 - ji0 - jjd = ( tab_ind(jn) - 1 ) / jpi + 1 - jj0 + DO jn = 1, ndim1d + jid = MOD( tab_ind(jn) - 1 , jpi ) + 1 - ji0 + jjd = ( tab_ind(jn) - 1 ) / jpi + 1 - jj0 + DO jl = 1, jpl tab1d(jn,jl) = tab2d(jid,jjd,jl) END DO END DO @@ -89,6 +124,38 @@ CONTAINS END DO END SUBROUTINE tab_2d_1d + SUBROUTINE tab_3d_4d( ndim1d, tab_ind, tab1d, tab2d ) + !!---------------------------------------------------------------------- + !! *** ROUTINE tab_2d_1d *** + !!---------------------------------------------------------------------- + INTEGER , INTENT(in ) :: ndim1d ! 1D size + INTEGER , DIMENSION(ndim1d) , INTENT(in ) :: tab_ind ! input index + REAL(wp), DIMENSION(:,:,:) , INTENT(in ) :: tab1d ! input 1D field + REAL(wp), DIMENSION(:,:,:,:), INTENT(inout) :: tab2d ! output 2D field + ! + INTEGER :: ipi, ipj, ipk, ji0, jj0, jk, jl, jn, jid, jjd + !!---------------------------------------------------------------------- + ipi = SIZE(tab2d,1) ! 1st dimension + ipj = SIZE(tab2d,2) ! 2nd dimension + ipk = SIZE(tab2d,3) ! 3d dimension + ! + IF( ipi == jpi .AND. ipj == jpj ) THEN ! full arrays then no need to change index jid and jjd + ji0 = 0 ; jj0 = 0 + ELSE ! reduced arrays then need to shift index by nn_hls + ji0 = nn_hls ; jj0 = nn_hls ! since tab2d is shifted by nn_hls + ENDIF ! (i.e. from hls+1:jpi-hls to 1:jpi-2*hls) + ! + DO jn = 1, ndim1d + jid = MOD( tab_ind(jn) - 1 , jpi ) + 1 - ji0 + jjd = ( tab_ind(jn) - 1 ) / jpi + 1 - jj0 + DO jl = 1, jpl + DO jk = 1, ipk + tab2d(jid,jjd,jk,jl) = tab1d(jn,jk,jl) + END DO + END DO + END DO + ! + END SUBROUTINE tab_3d_4d SUBROUTINE tab_2d_3d( ndim1d, tab_ind, tab1d, tab2d ) !!---------------------------------------------------------------------- @@ -110,10 +177,10 @@ CONTAINS ji0 = nn_hls ; jj0 = nn_hls ! since tab2d is shifted by nn_hls ENDIF ! (i.e. from hls+1:jpi-hls to 1:jpi-2*hls) ! - DO jl = 1, jpl - DO jn = 1, ndim1d - jid = MOD( tab_ind(jn) - 1 , jpi ) + 1 - ji0 - jjd = ( tab_ind(jn) - 1 ) / jpi + 1 - jj0 + DO jn = 1, ndim1d + jid = MOD( tab_ind(jn) - 1 , jpi ) + 1 - ji0 + jjd = ( tab_ind(jn) - 1 ) / jpi + 1 - jj0 + DO jl = 1, jpl tab2d(jid,jjd,jl) = tab1d(jn,jl) END DO END DO diff --git a/src/ICE/icethd_do.F90 b/src/ICE/icethd_do.F90 index 690af0e21..8af4064e8 100644 --- a/src/ICE/icethd_do.F90 +++ b/src/ICE/icethd_do.F90 @@ -97,8 +97,6 @@ CONTAINS REAL(wp), DIMENSION(jpij,jpl) :: zv_b ! old volume of ice in category jl REAL(wp), DIMENSION(jpij,jpl) :: za_b ! old area of ice in category jl ! - REAL(wp), DIMENSION(jpij,nlay_i,jpl) :: ze_i_2d !: 1-D version of e_i - ! !!-----------------------------------------------------------------------! IF( ln_icediachk ) CALL ice_cons_hsm( 0, 'icethd_do', rdiag_v, rdiag_s, rdiag_t, rdiag_fv, rdiag_fs, rdiag_ft ) @@ -126,11 +124,7 @@ CONTAINS CALL tab_3d_2d( npti, nptidx(1:npti), a_i_2d (1:npti,1:jpl), a_i (:,:,:) ) CALL tab_3d_2d( npti, nptidx(1:npti), v_i_2d (1:npti,1:jpl), v_i (:,:,:) ) CALL tab_3d_2d( npti, nptidx(1:npti), sv_i_2d(1:npti,1:jpl), sv_i(:,:,:) ) - DO jl = 1, jpl - DO jk = 1, nlay_i - CALL tab_2d_1d( npti, nptidx(1:npti), ze_i_2d(1:npti,jk,jl), e_i(:,:,jk,jl) ) - END DO - END DO + CALL tab_4d_3d( npti, nptidx(1:npti), e_i_2d (1:npti,:,:) , e_i ) CALL tab_2d_1d( npti, nptidx(1:npti), qlead_1d (1:npti) , qlead ) CALL tab_2d_1d( npti, nptidx(1:npti), t_bo_1d (1:npti) , t_bo ) CALL tab_2d_1d( npti, nptidx(1:npti), sfx_opw_1d (1:npti) , sfx_opw ) @@ -147,9 +141,9 @@ CONTAINS DO jl = 1, jpl DO jk = 1, nlay_i WHERE( v_i_2d(1:npti,jl) > 0._wp ) - ze_i_2d(1:npti,jk,jl) = ze_i_2d(1:npti,jk,jl) / v_i_2d(1:npti,jl) * REAL( nlay_i ) + e_i_2d(1:npti,jk,jl) = e_i_2d(1:npti,jk,jl) / v_i_2d(1:npti,jl) * REAL( nlay_i ) ELSEWHERE - ze_i_2d(1:npti,jk,jl) = 0._wp + e_i_2d(1:npti,jk,jl) = 0._wp END WHERE END DO END DO @@ -261,8 +255,8 @@ CONTAINS DO ji = 1, npti jl = jcat(ji) rswitch = MAX( 0._wp, SIGN( 1._wp , v_i_2d(ji,jl) - epsi20 ) ) - ze_i_2d(ji,jk,jl) = zswinew(ji) * ze_newice(ji) + & - & ( 1.0 - zswinew(ji) ) * ( ze_newice(ji) * zv_newice(ji) + ze_i_2d(ji,jk,jl) * zv_b(ji,jl) ) & + e_i_2d(ji,jk,jl) = zswinew(ji) * ze_newice(ji) + & + & ( 1.0 - zswinew(ji) ) * ( ze_newice(ji) * zv_newice(ji) + e_i_2d(ji,jk,jl) * zv_b(ji,jl) ) & & * rswitch / MAX( v_i_2d(ji,jl), epsi20 ) END DO END DO @@ -276,7 +270,7 @@ CONTAINS DO jk = 1, nlay_i DO ji = 1, npti h_i_old (ji,jk) = v_i_2d(ji,jl) * r1_nlay_i - eh_i_old(ji,jk) = ze_i_2d(ji,jk,jl) * h_i_old(ji,jk) + eh_i_old(ji,jk) = e_i_2d(ji,jk,jl) * h_i_old(ji,jk) END DO END DO @@ -291,7 +285,7 @@ CONTAINS eh_i_old(ji,nlay_i+1) = ze_newice(ji) * zv_newfra END DO ! --- Ice enthalpy remapping --- ! - CALL ice_thd_ent( ze_i_2d(1:npti,:,jl) ) + CALL ice_thd_ent( e_i_2d(1:npti,:,jl) ) END DO ! --- Update salinity --- ! @@ -304,7 +298,7 @@ CONTAINS ! Change units for e_i DO jl = 1, jpl DO jk = 1, nlay_i - ze_i_2d(1:npti,jk,jl) = ze_i_2d(1:npti,jk,jl) * v_i_2d(1:npti,jl) * r1_nlay_i + e_i_2d(1:npti,jk,jl) = e_i_2d(1:npti,jk,jl) * v_i_2d(1:npti,jl) * r1_nlay_i END DO END DO @@ -312,11 +306,7 @@ CONTAINS CALL tab_2d_3d( npti, nptidx(1:npti), a_i_2d (1:npti,1:jpl), a_i (:,:,:) ) CALL tab_2d_3d( npti, nptidx(1:npti), v_i_2d (1:npti,1:jpl), v_i (:,:,:) ) CALL tab_2d_3d( npti, nptidx(1:npti), sv_i_2d(1:npti,1:jpl), sv_i(:,:,:) ) - DO jl = 1, jpl - DO jk = 1, nlay_i - CALL tab_1d_2d( npti, nptidx(1:npti), ze_i_2d(1:npti,jk,jl), e_i(:,:,jk,jl) ) - END DO - END DO + CALL tab_3d_4d( npti, nptidx(1:npti), e_i_2d (1:npti,:,:) , e_i ) CALL tab_1d_2d( npti, nptidx(1:npti), sfx_opw_1d(1:npti), sfx_opw ) CALL tab_1d_2d( npti, nptidx(1:npti), wfx_opw_1d(1:npti), wfx_opw ) CALL tab_1d_2d( npti, nptidx(1:npti), hfx_thd_1d(1:npti), hfx_thd ) diff --git a/src/ICE/icethd_zdf_bl99.F90 b/src/ICE/icethd_zdf_bl99.F90 index 493435f3f..9bae2473e 100644 --- a/src/ICE/icethd_zdf_bl99.F90 +++ b/src/ICE/icethd_zdf_bl99.F90 @@ -105,22 +105,21 @@ CONTAINS REAL(wp), DIMENSION(jpij) :: zh_i, z1_h_i ! ice layer thickness REAL(wp), DIMENSION(jpij) :: zh_s, z1_h_s ! snow layer thickness REAL(wp), DIMENSION(jpij) :: zqns_ice_b ! solar radiation absorbed at the surface - REAL(wp), DIMENSION(jpij) :: zfnet ! surface flux function REAL(wp), DIMENSION(jpij) :: zdqns_ice_b ! derivative of the surface flux function - ! - REAL(wp), DIMENSION(jpij ) :: ztsuold ! Old surface temperature in the ice + REAL(wp), DIMENSION(jpij,0:nlay_s) :: zradtr_s ! Radiation transmited through the snow + REAL(wp), DIMENSION(jpij,0:nlay_s) :: zradab_s ! Radiation absorbed in the snow + REAL(wp), DIMENSION(jpij,0:nlay_i) :: zradtr_i ! Radiation transmitted through the ice + REAL(wp), DIMENSION(jpij,0:nlay_i) :: zradab_i ! Radiation absorbed in the ice + REAL(wp), DIMENSION(jpij,0:nlay_i) :: ztcond_i ! Ice thermal conductivity + REAL(wp), DIMENSION(jpij,0:nlay_i) :: ztcond_i_cp ! copy REAL(wp), DIMENSION(jpij,nlay_i) :: ztiold ! Old temperature in the ice REAL(wp), DIMENSION(jpij,nlay_s) :: ztsold ! Old temperature in the snow + ! + REAL(wp), DIMENSION(jpij) :: zfnet ! surface flux function REAL(wp), DIMENSION(jpij,nlay_i) :: ztib ! Temporary temperature in the ice to check the convergence REAL(wp), DIMENSION(jpij,nlay_s) :: ztsb ! Temporary temperature in the snow to check the convergence - REAL(wp), DIMENSION(jpij,0:nlay_i) :: ztcond_i ! Ice thermal conductivity - REAL(wp), DIMENSION(jpij,0:nlay_i) :: ztcond_i_cp ! copy - REAL(wp), DIMENSION(jpij,0:nlay_i) :: zradtr_i ! Radiation transmitted through the ice - REAL(wp), DIMENSION(jpij,0:nlay_i) :: zradab_i ! Radiation absorbed in the ice REAL(wp), DIMENSION(jpij,0:nlay_i) :: zkappa_i ! Kappa factor in the ice REAL(wp), DIMENSION(jpij,0:nlay_i) :: zeta_i ! Eta factor in the ice - REAL(wp), DIMENSION(jpij,0:nlay_s) :: zradtr_s ! Radiation transmited through the snow - REAL(wp), DIMENSION(jpij,0:nlay_s) :: zradab_s ! Radiation absorbed in the snow REAL(wp), DIMENSION(jpij,0:nlay_s) :: zkappa_s ! Kappa factor in the snow REAL(wp), DIMENSION(jpij,0:nlay_s) :: zeta_s ! Eta factor in the snow REAL(wp), DIMENSION(jpij) :: zkappa_comb ! Combined snow and ice surface conductivity @@ -195,7 +194,6 @@ CONTAINS ! Store initial temperatures and non solar heat fluxes IF( k_cnd == np_cnd_OFF .OR. k_cnd == np_cnd_EMU ) THEN ztsub (1:npti) = t_su_1d(1:npti) ! surface temperature at iteration n-1 - ztsuold (1:npti) = t_su_1d(1:npti) ! surface temperature initial value t_su_1d (1:npti) = MIN( t_su_1d(1:npti), rt0 - ztsu_err ) ! required to leave the choice between melting or not zdqns_ice_b(1:npti) = dqns_ice_1d(1:npti) ! derivative of incoming nonsolar flux zqns_ice_b (1:npti) = qns_ice_1d(1:npti) ! store previous qns_ice_1d value @@ -209,19 +207,18 @@ CONTAINS ! 2) Radiation !------------- ! --- Transmission/absorption of solar radiation in the ice --- ! - zradtr_s(1:npti,0) = qtr_ice_top_1d(1:npti) - DO jk = 1, nlay_s - DO ji = 1, npti + DO ji = 1, npti + ! + zradtr_s(ji,0) = qtr_ice_top_1d(ji) + DO jk = 1, nlay_s ! ! radiation transmitted below the layer-th snow layer zradtr_s(ji,jk) = zradtr_s(ji,0) * EXP( - zraext_s(ji) * MAX( 0._wp, zh_s(ji) * REAL(jk) - zhs_ssl ) ) ! ! radiation absorbed by the layer-th snow layer zradab_s(ji,jk) = zradtr_s(ji,jk-1) - zradtr_s(ji,jk) END DO - END DO - ! - zradtr_i(1:npti,0) = zradtr_s(1:npti,nlay_s) * za_s_fra(1:npti) + qtr_ice_top_1d(1:npti) * ( 1._wp - za_s_fra(1:npti) ) - DO jk = 1, nlay_i - DO ji = 1, npti + ! + zradtr_i(ji,0) = zradtr_s(ji,nlay_s) * za_s_fra(ji) + qtr_ice_top_1d(ji) * ( 1._wp - za_s_fra(ji) ) + DO jk = 1, nlay_i ! ! radiation transmitted below the layer-th ice layer zradtr_i(ji,jk) = za_s_fra(ji) * zradtr_s(ji,nlay_s) & ! part covered by snow & * EXP( - rn_kappa_i * MAX( 0._wp, zh_i(ji) * REAL(jk) - zh_min ) ) & @@ -230,9 +227,11 @@ CONTAINS ! ! radiation absorbed by the layer-th ice layer zradab_i(ji,jk) = zradtr_i(ji,jk-1) - zradtr_i(ji,jk) END DO + ! + qtr_ice_bot_1d(ji) = zradtr_i(ji,nlay_i) ! record radiation transmitted below the ice + ! END DO ! - qtr_ice_bot_1d(1:npti) = zradtr_i(1:npti,nlay_i) ! record radiation transmitted below the ice ! iconv = 0 ! number of iterations ! @@ -257,9 +256,7 @@ CONTAINS DO ji = 1, npti ztcond_i_cp(ji,0) = rcnd_i + zbeta * sz_i_1d(ji,1) / MIN( -epsi10, t_i_1d(ji,1) - rt0 ) ztcond_i_cp(ji,nlay_i) = rcnd_i + zbeta * sz_i_1d(ji,nlay_i) / MIN( -epsi10, t_bo_1d(ji) - rt0 ) - END DO - DO jk = 1, nlay_i-1 - DO ji = 1, npti + DO jk = 1, nlay_i-1 ztcond_i_cp(ji,jk) = rcnd_i + zbeta * 0.5_wp * ( sz_i_1d(ji,jk) + sz_i_1d(ji,jk+1) ) / & & MIN( -epsi10, 0.5_wp * ( t_i_1d(ji,jk) + t_i_1d(ji,jk+1) ) - rt0 ) END DO @@ -272,9 +269,7 @@ CONTAINS & - 0.011_wp * ( t_i_1d(ji,1) - rt0 ) ztcond_i_cp(ji,nlay_i) = rcnd_i + 0.09_wp * sz_i_1d(ji,nlay_i) / MIN( -epsi10, t_bo_1d(ji) - rt0 ) & & - 0.011_wp * ( t_bo_1d(ji) - rt0 ) - END DO - DO jk = 1, nlay_i-1 - DO ji = 1, npti + DO jk = 1, nlay_i-1 ztcond_i_cp(ji,jk) = rcnd_i + 0.09_wp * 0.5_wp * ( sz_i_1d(ji,jk) + sz_i_1d(ji,jk+1) ) / & & MIN( -epsi10, 0.5_wp * ( t_i_1d(ji,jk) + t_i_1d(ji,jk+1) ) - rt0 ) & & - 0.011_wp * ( 0.5_wp * ( t_i_1d(ji,jk) + t_i_1d(ji,jk+1) ) - rt0 ) @@ -308,119 +303,98 @@ CONTAINS ! ENDIF ! - !----------------- - ! 4) kappa factors - !----------------- - !--- Snow - ! Variable used after iterations - ! Value must be frozen after convergence for MPP independance reason - DO jk = 0, nlay_s-1 - DO ji = 1, npti - IF ( .NOT. l_T_converged(ji) ) & + DO ji = 1, npti + !----------------- + ! 4) kappa factors + !----------------- + IF ( .NOT. l_T_converged(ji) ) THEN + !--- Snow + ! Variable used after iterations + ! Value must be frozen after convergence for MPP independance reason + DO jk = 0, nlay_s-1 zkappa_s(ji,jk) = zghe(ji) * rn_cnd_s * z1_h_s(ji) - END DO - END DO - DO ji = 1, npti ! Snow-ice interface - IF ( .NOT. l_T_converged(ji) ) & - zkappa_s(ji,nlay_s) = isnow(ji) * zghe(ji) * rn_cnd_s * ztcond_i(ji,0) & + END DO + zkappa_s(ji,nlay_s) = isnow(ji) * zghe(ji) * rn_cnd_s * ztcond_i(ji,0) & ! Snow-ice interface & / ( 0.5_wp * ( ztcond_i(ji,0) * zh_s(ji) + rn_cnd_s * zh_i(ji) ) ) - END DO - - !--- Ice - ! Variable used after iterations - ! Value must be frozen after convergence for MPP independance reason - DO jk = 0, nlay_i - DO ji = 1, npti - IF ( .NOT. l_T_converged(ji) ) & + ! + !--- Ice + ! Variable used after iterations + ! Value must be frozen after convergence for MPP independance reason + DO jk = 0, nlay_i zkappa_i(ji,jk) = zghe(ji) * ztcond_i(ji,jk) * z1_h_i(ji) - END DO - END DO - DO ji = 1, npti ! Snow-ice interface - IF ( .NOT. l_T_converged(ji) ) THEN + END DO ! Calculate combined surface snow and ice conductivity to pass through the coupler (met-office) zkappa_comb(ji) = isnow_comb(ji) * zkappa_s(ji,0) + ( 1._wp - isnow_comb(ji) ) * zkappa_i(ji,0) ! If there is snow then use the same snow-ice interface conductivity for the top layer of ice - IF( h_s_1d(ji) > 0._wp ) zkappa_i(ji,0) = zkappa_s(ji,nlay_s) - ENDIF - END DO - ! - !-------------------------------------- - ! 5) Sea ice specific heat, eta factors - !-------------------------------------- - DO jk = 1, nlay_i - DO ji = 1, npti + IF( h_s_1d(ji) > 0._wp ) zkappa_i(ji,0) = zkappa_s(ji,nlay_s) ! Snow-ice interface + ENDIF + ! + !-------------------------------------- + ! 5) Sea ice specific heat, eta factors + !-------------------------------------- + DO jk = 1, nlay_i zcpi = rcpi + zgamma * sz_i_1d(ji,jk) / MAX( ( t_i_1d(ji,jk) - rt0 ) * ( ztiold(ji,jk) - rt0 ), epsi10 ) zeta_i(ji,jk) = rDt_ice * r1_rhoi * z1_h_i(ji) / zcpi END DO - END DO - - DO jk = 1, nlay_s - DO ji = 1, npti + DO jk = 1, nlay_s zeta_s(ji,jk) = rDt_ice * r1_rhos * r1_rcpi * z1_h_s(ji) END DO END DO ! - !----------------------------------------! - ! ! - ! Conduction flux is off or emulated ! - ! ! - !----------------------------------------! ! IF( k_cnd == np_cnd_OFF .OR. k_cnd == np_cnd_EMU ) THEN + !----------------------------------------! + ! ! + ! Conduction flux is off or emulated ! + ! ! + !----------------------------------------! ! ! ==> The original BL99 temperature computation is used ! (with qsr_ice, qns_ice and dqns_ice as inputs) ! - !---------------------------- - ! 6) surface flux computation - !---------------------------- - ! update of the non solar flux according to the update in T_su DO ji = 1, npti + !---------------------------- + ! 6) surface flux computation + !---------------------------- + ! update of the non solar flux according to the update in T_su ! Variable used after iterations ! Value must be frozen after convergence for MPP independance reason IF ( .NOT. l_T_converged(ji) ) & qns_ice_1d(ji) = qns_ice_1d(ji) + dqns_ice_1d(ji) * ( t_su_1d(ji) - ztsub(ji) ) - END DO - - DO ji = 1, npti + ! zfnet(ji) = qsr_ice_1d(ji) - qtr_ice_top_1d(ji) + qns_ice_1d(ji) ! net heat flux = net - transmitted solar + non solar - END DO - ! - !---------------------------- - ! 7) tridiagonal system terms - !---------------------------- - ! layer denotes the number of the layer in the snow or in the ice - ! jm denotes the reference number of the equation in the tridiagonal - ! system, terms of tridiagonal system are indexed as following : - ! 1 is subdiagonal term, 2 is diagonal and 3 is superdiagonal one - - ! ice interior terms (top equation has the same form as the others) - ztrid (1:npti,:,:) = 0._wp - zindterm(1:npti,:) = 0._wp - zindtbis(1:npti,:) = 0._wp - zdiagbis(1:npti,:) = 0._wp - - DO jm = nlay_s + 2, nlay_s + nlay_i - DO ji = 1, npti + ! + ! + !---------------------------- + ! 7) tridiagonal system terms + !---------------------------- + ! layer denotes the number of the layer in the snow or in the ice + ! jm denotes the reference number of the equation in the tridiagonal + ! system, terms of tridiagonal system are indexed as following : + ! 1 is subdiagonal term, 2 is diagonal and 3 is superdiagonal one + + ! ice interior terms (top equation has the same form as the others) + ztrid (ji,:,:) = 0._wp + zindterm(ji,:) = 0._wp + zindtbis(ji,:) = 0._wp + zdiagbis(ji,:) = 0._wp + + DO jm = nlay_s + 2, nlay_s + nlay_i jk = jm - nlay_s - 1 ztrid (ji,jm,1) = - zeta_i(ji,jk) * zkappa_i(ji,jk-1) ztrid (ji,jm,2) = 1._wp + zeta_i(ji,jk) * ( zkappa_i(ji,jk-1) + zkappa_i(ji,jk) ) ztrid (ji,jm,3) = - zeta_i(ji,jk) * zkappa_i(ji,jk) zindterm(ji,jm) = ztiold(ji,jk) + zeta_i(ji,jk) * zradab_i(ji,jk) END DO - END DO - jm = nlay_s + nlay_i + 1 - DO ji = 1, npti + jm = nlay_s + nlay_i + 1 ! ice bottom term ztrid (ji,jm,1) = - zeta_i(ji,nlay_i) * zkappa_i(ji,nlay_i-1) ztrid (ji,jm,2) = 1._wp + zeta_i(ji,nlay_i) * ( zkappa_i(ji,nlay_i-1) + zkappa_i(ji,nlay_i) * zg1 ) ztrid (ji,jm,3) = 0._wp zindterm(ji,jm) = ztiold(ji,nlay_i) + zeta_i(ji,nlay_i) * & & ( zradab_i(ji,nlay_i) + zkappa_i(ji,nlay_i) * zg1 * t_bo_1d(ji) ) - END DO - DO ji = 1, npti ! !---------------------! IF( h_s_1d(ji) > 0._wp ) THEN ! snow-covered cells ! ! !---------------------! @@ -518,20 +492,19 @@ CONTAINS zindterm(ji,jm_min(ji)) = ztiold(ji,1) + zeta_i(ji,1) * ( zradab_i(ji,1) + zkappa_i(ji,1) * t_bo_1d(ji) ) & & + t_su_1d(ji) * zeta_i(ji,1) * zkappa_i(ji,0) * 2._wp ENDIF - + ENDIF ENDIF ! zindtbis(ji,jm_min(ji)) = zindterm(ji,jm_min(ji)) zdiagbis(ji,jm_min(ji)) = ztrid (ji,jm_min(ji),2) ! - END DO - ! - !------------------------------ - ! 8) tridiagonal system solving - !------------------------------ - ! Solve the tridiagonal system with Gauss elimination method. - ! Thomas algorithm, from Computational fluid Dynamics, J.D. ANDERSON, McGraw-Hill 1984 + ! + !------------------------------ + ! 8) tridiagonal system solving + !------------------------------ + ! Solve the tridiagonal system with Gauss elimination method. + ! Thomas algorithm, from Computational fluid Dynamics, J.D. ANDERSON, McGraw-Hill 1984 !!$ jm_maxt = 0 !!$ jm_mint = nlay_i+5 !!$ DO ji = 1, npti @@ -547,50 +520,39 @@ CONTAINS !!$ zindtbis(ji,jm) = zindterm(ji,jm ) - ztrid(ji,jm,1) * zindtbis(ji,jm-1 ) / zdiagbis(ji,jm-1) !!$ END DO !!$ END DO - ! clem: maybe one should find a way to reverse this loop for mpi performance - DO ji = 1, npti + ! clem: maybe one should find a way to reverse this loop for mpi performance jm_mint = jm_min(ji) jm_maxt = jm_max(ji) DO jm = jm_mint+1, jm_maxt zdiagbis(ji,jm) = ztrid (ji,jm,2) - ztrid(ji,jm,1) * ztrid (ji,jm-1,3) / zdiagbis(ji,jm-1) zindtbis(ji,jm) = zindterm(ji,jm ) - ztrid(ji,jm,1) * zindtbis(ji,jm-1 ) / zdiagbis(ji,jm-1) END DO - END DO - ! ice temperatures - DO ji = 1, npti + ! ice temperatures ! Variable used after iterations ! Value must be frozen after convergence for MPP independance reason IF ( .NOT. l_T_converged(ji) ) & t_i_1d(ji,nlay_i) = zindtbis(ji,jm_max(ji)) / zdiagbis(ji,jm_max(ji)) - END DO - - DO jm = nlay_i + nlay_s, nlay_s + 2, -1 - DO ji = 1, npti + + DO jm = nlay_i + nlay_s, nlay_s + 2, -1 jk = jm - nlay_s - 1 IF ( .NOT. l_T_converged(ji) ) & t_i_1d(ji,jk) = ( zindtbis(ji,jm) - ztrid(ji,jm,3) * t_i_1d(ji,jk+1) ) / zdiagbis(ji,jm) END DO - END DO - ! snow temperatures - DO ji = 1, npti + ! snow temperatures ! Variables used after iterations ! Value must be frozen after convergence for MPP independance reason IF ( .NOT. l_T_converged(ji) .AND. h_s_1d(ji) > 0._wp ) & & t_s_1d(ji,nlay_s) = ( zindtbis(ji,nlay_s+1) - ztrid(ji,nlay_s+1,3) * t_i_1d(ji,1) ) / zdiagbis(ji,nlay_s+1) - END DO - !!clem SNWLAY - DO jm = nlay_s, 2, -1 - DO ji = 1, npti + !!clem SNWLAY + DO jm = nlay_s, 2, -1 jk = jm - 1 IF ( .NOT. l_T_converged(ji) .AND. h_s_1d(ji) > 0._wp ) & & t_s_1d(ji,jk) = ( zindtbis(ji,jm) - ztrid(ji,jm,3) * t_s_1d(ji,jk+1) ) / zdiagbis(ji,jm) END DO - END DO - ! surface temperature - DO ji = 1, npti + ! surface temperature IF( .NOT. l_T_converged(ji) ) THEN ztsub(ji) = t_su_1d(ji) IF( t_su_1d(ji) < rt0 ) THEN @@ -598,20 +560,17 @@ CONTAINS & ( isnow(ji) * t_s_1d(ji,1) + ( 1._wp - isnow(ji) ) * t_i_1d(ji,1) ) ) / zdiagbis(ji,jm_min(ji)) ENDIF ENDIF - END DO - ! - !-------------------------------------------------------------- - ! 9) Has the scheme converged?, end of the iterative procedure - !-------------------------------------------------------------- - ! check that nowhere it has started to melt - ! zdti_max is a measure of error, it has to be under zdti_bnd - - DO ji = 1, npti - + ! + !-------------------------------------------------------------- + ! 9) Has the scheme converged?, end of the iterative procedure + !-------------------------------------------------------------- + ! check that nowhere it has started to melt + ! zdti_max is a measure of error, it has to be under zdti_bnd + zdti_max = 0._wp IF ( .NOT. l_T_converged(ji) ) THEN - + t_su_1d(ji) = MAX( MIN( t_su_1d(ji) , rt0 ) , rt0 - 100._wp ) zdti_max = MAX( zdti_max, ABS( t_su_1d(ji) - ztsub(ji) ) ) @@ -633,58 +592,53 @@ CONTAINS tice_cvgerr_1d(ji) = zdti_max tice_cvgstp_1d(ji) = REAL(iconv) ENDIF - + IF( zdti_max < zdti_bnd ) l_T_converged(ji) = .TRUE. - + ENDIF - - END DO - - !----------------------------------------! - ! ! - ! Conduction flux is on ! - ! ! - !----------------------------------------! - ! + + END DO + ! ELSEIF( k_cnd == np_cnd_ON ) THEN + !----------------------------------------! + ! ! + ! Conduction flux is on ! + ! ! + !----------------------------------------! ! ! ==> we use a modified BL99 solver with conduction flux (qcn_ice) as forcing term ! - !---------------------------- - ! 7) tridiagonal system terms - !---------------------------- - ! layer denotes the number of the layer in the snow or in the ice - ! jm denotes the reference number of the equation in the tridiagonal - ! system, terms of tridiagonal system are indexed as following : - ! 1 is subdiagonal term, 2 is diagonal and 3 is superdiagonal one - - ! ice interior terms (top equation has the same form as the others) - ztrid (1:npti,:,:) = 0._wp - zindterm(1:npti,:) = 0._wp - zindtbis(1:npti,:) = 0._wp - zdiagbis(1:npti,:) = 0._wp - - DO jm = nlay_s + 2, nlay_s + nlay_i - DO ji = 1, npti + DO ji = 1, npti + !---------------------------- + ! 7) tridiagonal system terms + !---------------------------- + ! layer denotes the number of the layer in the snow or in the ice + ! jm denotes the reference number of the equation in the tridiagonal + ! system, terms of tridiagonal system are indexed as following : + ! 1 is subdiagonal term, 2 is diagonal and 3 is superdiagonal one + + ! ice interior terms (top equation has the same form as the others) + ztrid (ji,:,:) = 0._wp + zindterm(ji,:) = 0._wp + zindtbis(ji,:) = 0._wp + zdiagbis(ji,:) = 0._wp + + DO jm = nlay_s + 2, nlay_s + nlay_i jk = jm - nlay_s - 1 ztrid (ji,jm,1) = - zeta_i(ji,jk) * zkappa_i(ji,jk-1) ztrid (ji,jm,2) = 1._wp + zeta_i(ji,jk) * ( zkappa_i(ji,jk-1) + zkappa_i(ji,jk) ) ztrid (ji,jm,3) = - zeta_i(ji,jk) * zkappa_i(ji,jk) zindterm(ji,jm) = ztiold(ji,jk) + zeta_i(ji,jk) * zradab_i(ji,jk) END DO - ENDDO - jm = nlay_s + nlay_i + 1 - DO ji = 1, npti ! ice bottom term + jm = nlay_s + nlay_i + 1 ztrid (ji,jm,1) = - zeta_i(ji,nlay_i) * zkappa_i(ji,nlay_i-1) ztrid (ji,jm,2) = 1._wp + zeta_i(ji,nlay_i) * ( zkappa_i(ji,nlay_i-1) + zkappa_i(ji,nlay_i) * zg1 ) ztrid (ji,jm,3) = 0._wp zindterm(ji,jm) = ztiold(ji,nlay_i) + zeta_i(ji,nlay_i) * & & ( zradab_i(ji,nlay_i) + zkappa_i(ji,nlay_i) * zg1 * t_bo_1d(ji) ) - ENDDO - DO ji = 1, npti ! !---------------------! IF( h_s_1d(ji) > 0._wp ) THEN ! snow-covered cells ! ! !---------------------! @@ -738,13 +692,12 @@ CONTAINS zindtbis(ji,jm_min(ji)) = zindterm(ji,jm_min(ji)) zdiagbis(ji,jm_min(ji)) = ztrid (ji,jm_min(ji),2) ! - END DO - ! - !------------------------------ - ! 8) tridiagonal system solving - !------------------------------ - ! Solve the tridiagonal system with Gauss elimination method. - ! Thomas algorithm, from Computational fluid Dynamics, J.D. ANDERSON, McGraw-Hill 1984 + ! + !------------------------------ + ! 8) tridiagonal system solving + !------------------------------ + ! Solve the tridiagonal system with Gauss elimination method. + ! Thomas algorithm, from Computational fluid Dynamics, J.D. ANDERSON, McGraw-Hill 1984 !!$ jm_maxt = 0 !!$ jm_mint = nlay_i+5 !!$ DO ji = 1, npti @@ -759,61 +712,49 @@ CONTAINS !!$ zindtbis(ji,jm) = zindterm(ji,jm) - ztrid(ji,jm,1) * zindtbis(ji,jm-1) / zdiagbis(ji,jm-1) !!$ END DO !!$ END DO - ! clem: maybe one should find a way to reverse this loop for mpi performance - DO ji = 1, npti + ! clem: maybe one should find a way to reverse this loop for mpi performance jm_mint = jm_min(ji) jm_maxt = jm_max(ji) DO jm = jm_mint+1, jm_maxt zdiagbis(ji,jm) = ztrid (ji,jm,2) - ztrid(ji,jm,1) * ztrid (ji,jm-1,3) / zdiagbis(ji,jm-1) zindtbis(ji,jm) = zindterm(ji,jm ) - ztrid(ji,jm,1) * zindtbis(ji,jm-1 ) / zdiagbis(ji,jm-1) END DO - END DO - ! ice temperatures - DO ji = 1, npti + ! ice temperatures ! Variable used after iterations ! Value must be frozen after convergence for MPP independance reason IF ( .NOT. l_T_converged(ji) ) & t_i_1d(ji,nlay_i) = zindtbis(ji,jm_max(ji)) / zdiagbis(ji,jm_max(ji)) - END DO - DO jm = nlay_i + nlay_s, nlay_s + 2, -1 - DO ji = 1, npti + DO jm = nlay_i + nlay_s, nlay_s + 2, -1 IF ( .NOT. l_T_converged(ji) ) THEN jk = jm - nlay_s - 1 t_i_1d(ji,jk) = ( zindtbis(ji,jm) - ztrid(ji,jm,3) * t_i_1d(ji,jk+1) ) / zdiagbis(ji,jm) ENDIF END DO - END DO - ! snow temperatures - DO ji = 1, npti + ! snow temperatures ! Variables used after iterations ! Value must be frozen after convergence for MPP independance reason IF ( .NOT. l_T_converged(ji) .AND. h_s_1d(ji) > 0._wp ) & & t_s_1d(ji,nlay_s) = ( zindtbis(ji,nlay_s+1) - ztrid(ji,nlay_s+1,3) * t_i_1d(ji,1) ) / zdiagbis(ji,nlay_s+1) - END DO - !!clem SNWLAY - DO jm = nlay_s, 2, -1 - DO ji = 1, npti + !!clem SNWLAY + DO jm = nlay_s, 2, -1 jk = jm - 1 IF ( .NOT. l_T_converged(ji) .AND. h_s_1d(ji) > 0._wp ) & & t_s_1d(ji,jk) = ( zindtbis(ji,jm) - ztrid(ji,jm,3) * t_s_1d(ji,jk+1) ) / zdiagbis(ji,jm) END DO - END DO - ! - !-------------------------------------------------------------- - ! 9) Has the scheme converged?, end of the iterative procedure - !-------------------------------------------------------------- - ! check that nowhere it has started to melt - ! zdti_max is a measure of error, it has to be under zdti_bnd - - DO ji = 1, npti - + ! + !-------------------------------------------------------------- + ! 9) Has the scheme converged?, end of the iterative procedure + !-------------------------------------------------------------- + ! check that nowhere it has started to melt + ! zdti_max is a measure of error, it has to be under zdti_bnd + zdti_max = 0._wp - + IF ( .NOT. l_T_converged(ji) ) THEN - + IF( h_s_1d(ji) > 0._wp ) THEN DO jk = 1, nlay_s t_s_1d(ji,jk) = MAX( MIN( t_s_1d(ji,jk), rt0 ), rt0 - 100._wp ) -- GitLab