[10376] | 1 | MODULE trcsink |
---|
| 2 | !!====================================================================== |
---|
| 3 | !! *** MODULE trcsink *** |
---|
| 4 | !! TOP : vertical flux of particulate matter due to gravitational sinking |
---|
| 5 | !!====================================================================== |
---|
| 6 | !! History : 1.0 ! 2004 (O. Aumont) Original code |
---|
| 7 | !! 2.0 ! 2007-12 (C. Ethe, G. Madec) F90 |
---|
| 8 | !! 3.4 ! 2011-06 (O. Aumont, C. Ethe) Change aggregation formula |
---|
| 9 | !! 3.5 ! 2012-07 (O. Aumont) Introduce potential time-splitting |
---|
| 10 | !! 4.0 ! 2018-12 (O. Aumont) Generalize the PISCES code to make it usable by any model |
---|
| 11 | !!---------------------------------------------------------------------- |
---|
| 12 | !! trc_sink : Compute vertical flux of particulate matter due to gravitational sinking |
---|
| 13 | !!---------------------------------------------------------------------- |
---|
| 14 | USE oce_trc ! shared variables between ocean and passive tracers |
---|
| 15 | USE trc ! passive tracers common variables |
---|
| 16 | USE lib_mpp |
---|
| 17 | |
---|
| 18 | IMPLICIT NONE |
---|
| 19 | PRIVATE |
---|
| 20 | |
---|
| 21 | PUBLIC trc_sink |
---|
| 22 | PUBLIC trc_sink_ini |
---|
| 23 | |
---|
| 24 | INTEGER, PUBLIC :: nitermax !: Maximum number of iterations for sinking |
---|
| 25 | |
---|
[12377] | 26 | !! * Substitutions |
---|
| 27 | # include "do_loop_substitute.h90" |
---|
[13237] | 28 | # include "domzgr_substitute.h90" |
---|
[10376] | 29 | !!---------------------------------------------------------------------- |
---|
| 30 | !! NEMO/TOP 4.0 , NEMO Consortium (2018) |
---|
| 31 | !! $Id: trcsink.F90 10069 2018-08-28 14:12:24Z nicolasmartin $ |
---|
| 32 | !! Software governed by the CeCILL license (see ./LICENSE) |
---|
| 33 | !!---------------------------------------------------------------------- |
---|
| 34 | CONTAINS |
---|
| 35 | |
---|
| 36 | !!---------------------------------------------------------------------- |
---|
| 37 | !! 'standard sinking parameterisation' ??? |
---|
| 38 | !!---------------------------------------------------------------------- |
---|
| 39 | |
---|
[12377] | 40 | SUBROUTINE trc_sink ( kt, Kbb, Kmm, pwsink, psinkflx, jp_tra, rsfact ) |
---|
[10376] | 41 | !!--------------------------------------------------------------------- |
---|
| 42 | !! *** ROUTINE trc_sink *** |
---|
| 43 | !! |
---|
| 44 | !! ** Purpose : Compute vertical flux of particulate matter due to |
---|
| 45 | !! gravitational sinking |
---|
| 46 | !! |
---|
| 47 | !! ** Method : - ??? |
---|
| 48 | !!--------------------------------------------------------------------- |
---|
| 49 | INTEGER , INTENT(in) :: kt |
---|
[12377] | 50 | INTEGER , INTENT(in) :: Kbb, Kmm |
---|
[10376] | 51 | INTEGER , INTENT(in) :: jp_tra ! tracer index index |
---|
| 52 | REAL(wp), INTENT(in) :: rsfact ! time step duration |
---|
| 53 | REAL(wp), INTENT(in) , DIMENSION(jpi,jpj,jpk) :: pwsink |
---|
| 54 | REAL(wp), INTENT(inout), DIMENSION(jpi,jpj,jpk) :: psinkflx |
---|
| 55 | INTEGER :: ji, jj, jk |
---|
| 56 | INTEGER, DIMENSION(jpi, jpj) :: iiter |
---|
| 57 | REAL(wp) :: zfact, zwsmax, zmax |
---|
| 58 | REAL(wp), DIMENSION(jpi,jpj,jpk) :: zwsink |
---|
| 59 | !!--------------------------------------------------------------------- |
---|
| 60 | ! |
---|
| 61 | IF( ln_timing ) CALL timing_start('trc_sink') |
---|
| 62 | ! |
---|
| 63 | ! |
---|
| 64 | ! OA This is (I hope) a temporary solution for the problem that may |
---|
| 65 | ! OA arise in specific situation where the CFL criterion is broken |
---|
| 66 | ! OA for vertical sedimentation of particles. To avoid this, a time |
---|
| 67 | ! OA splitting algorithm has been coded. A specific maximum |
---|
| 68 | ! OA iteration number is provided and may be specified in the namelist |
---|
| 69 | ! OA This is to avoid very large iteration number when explicit free |
---|
| 70 | ! OA surface is used (for instance). When niter?max is set to 1, |
---|
| 71 | ! OA this computation is skipped. The crude old threshold method is |
---|
| 72 | ! OA then applied. This also happens when niter exceeds nitermax. |
---|
| 73 | IF( nitermax == 1 ) THEN |
---|
| 74 | iiter(:,:) = 1 |
---|
| 75 | ELSE |
---|
[15090] | 76 | DO_2D( nn_hls, nn_hls, nn_hls, nn_hls ) |
---|
[12377] | 77 | iiter(ji,jj) = 1 |
---|
| 78 | DO jk = 1, jpkm1 |
---|
| 79 | IF( tmask(ji,jj,jk) == 1.0 ) THEN |
---|
| 80 | zwsmax = 0.5 * e3t(ji,jj,jk,Kmm) * rday / rsfact |
---|
[15325] | 81 | iiter(ji,jj) = MAX( iiter(ji,jj), INT( pwsink(ji,jj,jk) / zwsmax ) + 1 ) |
---|
[12377] | 82 | ENDIF |
---|
[10376] | 83 | END DO |
---|
[12377] | 84 | END_2D |
---|
[10788] | 85 | iiter(:,:) = MIN( iiter(:,:), nitermax ) |
---|
[10376] | 86 | ENDIF |
---|
| 87 | |
---|
[15090] | 88 | DO_3D( nn_hls, nn_hls, nn_hls, nn_hls, 1, jpkm1 ) |
---|
[12377] | 89 | IF( tmask(ji,jj,jk) == 1.0 ) THEN |
---|
| 90 | zwsmax = 0.5 * e3t(ji,jj,jk,Kmm) * rday / rsfact |
---|
| 91 | zwsink(ji,jj,jk) = MIN( pwsink(ji,jj,jk), zwsmax * REAL( iiter(ji,jj), wp ) ) |
---|
| 92 | ELSE |
---|
| 93 | ! provide a default value so there is no use of undefinite value in trc_sink2 for zwsink2 initialization |
---|
| 94 | zwsink(ji,jj,jk) = 0. |
---|
| 95 | ENDIF |
---|
| 96 | END_3D |
---|
[10376] | 97 | |
---|
| 98 | ! Initializa to zero all the sinking arrays |
---|
| 99 | ! ----------------------------------------- |
---|
| 100 | psinkflx(:,:,:) = 0.e0 |
---|
| 101 | |
---|
| 102 | ! Compute the sedimentation term using trc_sink2 for the considered sinking particle |
---|
| 103 | ! ----------------------------------------------------- |
---|
[12377] | 104 | CALL trc_sink2( Kbb, Kmm, zwsink, psinkflx, jp_tra, iiter, rsfact ) |
---|
[10376] | 105 | ! |
---|
| 106 | IF( ln_timing ) CALL timing_stop('trc_sink') |
---|
| 107 | ! |
---|
| 108 | END SUBROUTINE trc_sink |
---|
| 109 | |
---|
[12377] | 110 | SUBROUTINE trc_sink2( Kbb, Kmm, pwsink, psinkflx, jp_tra, kiter, rsfact ) |
---|
[10376] | 111 | !!--------------------------------------------------------------------- |
---|
| 112 | !! *** ROUTINE trc_sink2 *** |
---|
| 113 | !! |
---|
| 114 | !! ** Purpose : Compute the sedimentation terms for the various sinking |
---|
| 115 | !! particles. The scheme used to compute the trends is based |
---|
| 116 | !! on MUSCL. |
---|
| 117 | !! |
---|
| 118 | !! ** Method : - this ROUTINE compute not exactly the advection but the |
---|
| 119 | !! transport term, i.e. div(u*tra). |
---|
| 120 | !!--------------------------------------------------------------------- |
---|
[12377] | 121 | INTEGER, INTENT(in ) :: Kbb, Kmm ! time level indices |
---|
[10376] | 122 | INTEGER, INTENT(in ) :: jp_tra ! tracer index index |
---|
| 123 | REAL(wp), INTENT(in ) :: rsfact ! duration of time step |
---|
| 124 | INTEGER, INTENT(in ), DIMENSION(jpi,jpj) :: kiter ! number of iterations for time-splitting |
---|
| 125 | REAL(wp), INTENT(in ), DIMENSION(jpi,jpj,jpk) :: pwsink ! sinking speed |
---|
| 126 | REAL(wp), INTENT(inout), DIMENSION(jpi,jpj,jpk) :: psinkflx ! sinking fluxe |
---|
| 127 | ! |
---|
[15325] | 128 | INTEGER :: ji, jj, jk, jn, jt |
---|
[10376] | 129 | REAL(wp) :: zigma,zew,zign, zflx, zstep |
---|
[15325] | 130 | REAL(wp), DIMENSION(jpi,jpj,jpk) :: ztraz, zakz, zwsink2, ztrb, psinking |
---|
[10376] | 131 | !!--------------------------------------------------------------------- |
---|
| 132 | ! |
---|
| 133 | IF( ln_timing ) CALL timing_start('trc_sink2') |
---|
| 134 | ! |
---|
| 135 | DO jk = 1, jpkm1 |
---|
| 136 | zwsink2(:,:,jk+1) = -pwsink(:,:,jk) / rday * tmask(:,:,jk+1) |
---|
| 137 | END DO |
---|
| 138 | zwsink2(:,:,1) = 0.e0 |
---|
| 139 | |
---|
[15325] | 140 | DO_2D( nn_hls, nn_hls, nn_hls, nn_hls ) |
---|
| 141 | ! Vertical advective flux |
---|
| 142 | zstep = rsfact / REAL( kiter(ji,jj), wp ) / 2. |
---|
| 143 | DO jt = 1, kiter(ji,jj) |
---|
| 144 | ztraz(ji,jj,:) = 0.e0 |
---|
| 145 | zakz (ji,jj,:) = 0.e0 |
---|
| 146 | ztrb (ji,jj,:) = tr(ji,jj,:,jp_tra,Kbb) |
---|
| 147 | DO jn = 1, 2 |
---|
| 148 | ! |
---|
| 149 | DO jk = 2, jpkm1 |
---|
| 150 | ztraz(ji,jj,jk) = ( tr(ji,jj,jk-1,jp_tra,Kbb) - tr(ji,jj,jk,jp_tra,Kbb) ) * tmask(ji,jj,jk) |
---|
| 151 | END DO |
---|
| 152 | ztraz(ji,jj,1 ) = 0.0 |
---|
| 153 | ztraz(ji,jj,jpk) = 0.0 |
---|
[10376] | 154 | |
---|
[15325] | 155 | ! slopes |
---|
| 156 | DO jk = 2, jpkm1 |
---|
| 157 | zign = 0.25 + SIGN( 0.25_wp, ztraz(ji,jj,jk) * ztraz(ji,jj,jk+1) ) |
---|
| 158 | zakz(ji,jj,jk) = ( ztraz(ji,jj,jk) + ztraz(ji,jj,jk+1) ) * zign |
---|
| 159 | END DO |
---|
[12377] | 160 | |
---|
[15325] | 161 | ! Slopes limitation |
---|
| 162 | DO jk = 2, jpkm1 |
---|
| 163 | zakz(ji,jj,jk) = SIGN( 1.0_wp, zakz(ji,jj,jk) ) * & |
---|
| 164 | & MIN( ABS( zakz(ji,jj,jk) ), 2. * ABS(ztraz(ji,jj,jk+1)), 2. * ABS(ztraz(ji,jj,jk) ) ) |
---|
| 165 | END DO |
---|
| 166 | |
---|
| 167 | ! vertical advective flux |
---|
| 168 | DO jk = 1, jpkm1 |
---|
| 169 | zigma = zwsink2(ji,jj,jk+1) * zstep / e3w(ji,jj,jk+1,Kmm) |
---|
| 170 | zew = zwsink2(ji,jj,jk+1) |
---|
| 171 | psinking(ji,jj,jk+1) = -zew * ( tr(ji,jj,jk,jp_tra,Kbb) - 0.5 * ( 1 + zigma ) * zakz(ji,jj,jk) ) * zstep |
---|
| 172 | END DO |
---|
| 173 | ! |
---|
| 174 | ! Boundary conditions |
---|
| 175 | psinking(ji,jj,1 ) = 0.e0 |
---|
| 176 | psinking(ji,jj,jpk) = 0.e0 |
---|
| 177 | |
---|
| 178 | DO jk = 1, jpkm1 |
---|
| 179 | zflx = ( psinking(ji,jj,jk) - psinking(ji,jj,jk+1) ) / e3t(ji,jj,jk,Kmm) |
---|
| 180 | tr(ji,jj,jk,jp_tra,Kbb) = tr(ji,jj,jk,jp_tra,Kbb) + zflx |
---|
| 181 | END DO |
---|
[12377] | 182 | END DO |
---|
| 183 | DO jk = 1, jpkm1 |
---|
[15325] | 184 | zflx = ( psinking(ji,jj,jk) - psinking(ji,jj,jk+1) ) / e3t(ji,jj,jk,Kmm) |
---|
| 185 | ztrb(ji,jj,jk) = ztrb(ji,jj,jk) + 2. * zflx |
---|
[12377] | 186 | END DO |
---|
[10376] | 187 | |
---|
[15325] | 188 | tr(ji,jj,:,jp_tra,Kbb) = ztrb(ji,jj,:) |
---|
| 189 | psinkflx(ji,jj,:) = psinkflx(ji,jj,:) + 2. * psinking(ji,jj,:) |
---|
| 190 | END DO |
---|
| 191 | END_2D |
---|
[10376] | 192 | ! |
---|
| 193 | IF( ln_timing ) CALL timing_stop('trc_sink2') |
---|
| 194 | ! |
---|
| 195 | END SUBROUTINE trc_sink2 |
---|
| 196 | |
---|
| 197 | SUBROUTINE trc_sink_ini |
---|
| 198 | !!--------------------------------------------------------------------- |
---|
| 199 | !! *** ROUTINE trc_sink_ini *** |
---|
| 200 | !! |
---|
| 201 | !! ** Purpose : read namelist options |
---|
| 202 | !!---------------------------------------------------------------------- |
---|
| 203 | INTEGER :: ios ! Local integer output status for namelist read |
---|
| 204 | !! |
---|
| 205 | NAMELIST/namtrc_snk/ nitermax |
---|
| 206 | !!---------------------------------------------------------------------- |
---|
| 207 | ! |
---|
| 208 | READ ( numnat_ref, namtrc_snk, IOSTAT = ios, ERR = 907) |
---|
[11536] | 209 | 907 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namtrc_snk in reference namelist' ) |
---|
[10376] | 210 | READ ( numnat_cfg, namtrc_snk, IOSTAT = ios, ERR = 908 ) |
---|
[11536] | 211 | 908 IF( ios > 0 ) CALL ctl_nam ( ios , 'namtrc_snk in configuration namelist' ) |
---|
[10376] | 212 | IF(lwm) WRITE( numont, namtrc_snk ) |
---|
| 213 | |
---|
| 214 | IF(lwp) THEN ! ! Control print |
---|
| 215 | WRITE(numout,*) |
---|
| 216 | WRITE(numout,*) 'trc_sink : Sedimentation of particles ' |
---|
| 217 | WRITE(numout,*) '~~~~~~~ ' |
---|
| 218 | WRITE(numout,*) ' Namelist namtrc_snk : sedimentation of particles' |
---|
| 219 | WRITE(numout,*) ' Maximum number of iterations nitermax = ', nitermax |
---|
| 220 | WRITE(numout,*) |
---|
| 221 | ENDIF |
---|
| 222 | |
---|
| 223 | END SUBROUTINE trc_sink_ini |
---|
| 224 | |
---|
| 225 | !!====================================================================== |
---|
| 226 | END MODULE trcsink |
---|