[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 | |
---|
| 26 | !!---------------------------------------------------------------------- |
---|
| 27 | !! NEMO/TOP 4.0 , NEMO Consortium (2018) |
---|
| 28 | !! $Id: trcsink.F90 10069 2018-08-28 14:12:24Z nicolasmartin $ |
---|
| 29 | !! Software governed by the CeCILL license (see ./LICENSE) |
---|
| 30 | !!---------------------------------------------------------------------- |
---|
| 31 | CONTAINS |
---|
| 32 | |
---|
| 33 | !!---------------------------------------------------------------------- |
---|
| 34 | !! 'standard sinking parameterisation' ??? |
---|
| 35 | !!---------------------------------------------------------------------- |
---|
| 36 | |
---|
| 37 | SUBROUTINE trc_sink ( kt, pwsink, psinkflx, jp_tra, rsfact ) |
---|
| 38 | !!--------------------------------------------------------------------- |
---|
| 39 | !! *** ROUTINE trc_sink *** |
---|
| 40 | !! |
---|
| 41 | !! ** Purpose : Compute vertical flux of particulate matter due to |
---|
| 42 | !! gravitational sinking |
---|
| 43 | !! |
---|
| 44 | !! ** Method : - ??? |
---|
| 45 | !!--------------------------------------------------------------------- |
---|
| 46 | INTEGER , INTENT(in) :: kt |
---|
| 47 | INTEGER , INTENT(in) :: jp_tra ! tracer index index |
---|
| 48 | REAL(wp), INTENT(in) :: rsfact ! time step duration |
---|
| 49 | REAL(wp), INTENT(in) , DIMENSION(jpi,jpj,jpk) :: pwsink |
---|
| 50 | REAL(wp), INTENT(inout), DIMENSION(jpi,jpj,jpk) :: psinkflx |
---|
| 51 | INTEGER :: ji, jj, jk |
---|
| 52 | INTEGER, DIMENSION(jpi, jpj) :: iiter |
---|
| 53 | REAL(wp) :: zfact, zwsmax, zmax |
---|
| 54 | REAL(wp), DIMENSION(jpi,jpj,jpk) :: zwsink |
---|
| 55 | !!--------------------------------------------------------------------- |
---|
| 56 | ! |
---|
| 57 | IF( ln_timing ) CALL timing_start('trc_sink') |
---|
| 58 | ! |
---|
| 59 | ! |
---|
| 60 | ! OA This is (I hope) a temporary solution for the problem that may |
---|
| 61 | ! OA arise in specific situation where the CFL criterion is broken |
---|
| 62 | ! OA for vertical sedimentation of particles. To avoid this, a time |
---|
| 63 | ! OA splitting algorithm has been coded. A specific maximum |
---|
| 64 | ! OA iteration number is provided and may be specified in the namelist |
---|
| 65 | ! OA This is to avoid very large iteration number when explicit free |
---|
| 66 | ! OA surface is used (for instance). When niter?max is set to 1, |
---|
| 67 | ! OA this computation is skipped. The crude old threshold method is |
---|
| 68 | ! OA then applied. This also happens when niter exceeds nitermax. |
---|
| 69 | IF( nitermax == 1 ) THEN |
---|
| 70 | iiter(:,:) = 1 |
---|
| 71 | ELSE |
---|
| 72 | DO jj = 1, jpj |
---|
| 73 | DO ji = 1, jpi |
---|
| 74 | iiter(ji,jj) = 1 |
---|
| 75 | DO jk = 1, jpkm1 |
---|
| 76 | IF( tmask(ji,jj,jk) == 1.0 ) THEN |
---|
| 77 | zwsmax = 0.5 * e3t_n(ji,jj,jk) * rday / rsfact |
---|
| 78 | iiter(ji,jj) = MAX( iiter(ji,jj), INT( pwsink(ji,jj,jk) / zwsmax ) ) |
---|
| 79 | ENDIF |
---|
| 80 | END DO |
---|
| 81 | END DO |
---|
| 82 | END DO |
---|
[10780] | 83 | iiter(:,:) = MIN( iiter(:,:), nitermax ) |
---|
[10376] | 84 | ENDIF |
---|
| 85 | |
---|
| 86 | DO jk = 1,jpkm1 |
---|
| 87 | DO jj = 1, jpj |
---|
| 88 | DO ji = 1, jpi |
---|
| 89 | IF( tmask(ji,jj,jk) == 1 ) THEN |
---|
| 90 | zwsmax = 0.5 * e3t_n(ji,jj,jk) * rday / rsfact |
---|
| 91 | zwsink(ji,jj,jk) = MIN( pwsink(ji,jj,jk), zwsmax * REAL( iiter(ji,jj), wp ) ) |
---|
| 92 | ENDIF |
---|
| 93 | END DO |
---|
| 94 | END DO |
---|
| 95 | END DO |
---|
| 96 | |
---|
| 97 | ! Initializa to zero all the sinking arrays |
---|
| 98 | ! ----------------------------------------- |
---|
| 99 | psinkflx(:,:,:) = 0.e0 |
---|
| 100 | |
---|
| 101 | ! Compute the sedimentation term using trc_sink2 for the considered sinking particle |
---|
| 102 | ! ----------------------------------------------------- |
---|
| 103 | CALL trc_sink2( zwsink, psinkflx, jp_tra, iiter, rsfact ) |
---|
| 104 | ! |
---|
| 105 | IF( ln_timing ) CALL timing_stop('trc_sink') |
---|
| 106 | ! |
---|
| 107 | END SUBROUTINE trc_sink |
---|
| 108 | |
---|
| 109 | SUBROUTINE trc_sink2( pwsink, psinkflx, jp_tra, kiter, rsfact ) |
---|
| 110 | !!--------------------------------------------------------------------- |
---|
| 111 | !! *** ROUTINE trc_sink2 *** |
---|
| 112 | !! |
---|
| 113 | !! ** Purpose : Compute the sedimentation terms for the various sinking |
---|
| 114 | !! particles. The scheme used to compute the trends is based |
---|
| 115 | !! on MUSCL. |
---|
| 116 | !! |
---|
| 117 | !! ** Method : - this ROUTINE compute not exactly the advection but the |
---|
| 118 | !! transport term, i.e. div(u*tra). |
---|
| 119 | !!--------------------------------------------------------------------- |
---|
| 120 | INTEGER, INTENT(in ) :: jp_tra ! tracer index index |
---|
| 121 | REAL(wp), INTENT(in ) :: rsfact ! duration of time step |
---|
| 122 | INTEGER, INTENT(in ), DIMENSION(jpi,jpj) :: kiter ! number of iterations for time-splitting |
---|
| 123 | REAL(wp), INTENT(in ), DIMENSION(jpi,jpj,jpk) :: pwsink ! sinking speed |
---|
| 124 | REAL(wp), INTENT(inout), DIMENSION(jpi,jpj,jpk) :: psinkflx ! sinking fluxe |
---|
| 125 | ! |
---|
| 126 | INTEGER :: ji, jj, jk, jn |
---|
| 127 | REAL(wp) :: zigma,zew,zign, zflx, zstep |
---|
| 128 | REAL(wp), DIMENSION(jpi,jpj,jpk) :: ztraz, zakz, zwsink2, ztrb |
---|
| 129 | !!--------------------------------------------------------------------- |
---|
| 130 | ! |
---|
| 131 | IF( ln_timing ) CALL timing_start('trc_sink2') |
---|
| 132 | ! |
---|
| 133 | ztraz(:,:,:) = 0.e0 |
---|
| 134 | zakz (:,:,:) = 0.e0 |
---|
| 135 | ztrb (:,:,:) = trb(:,:,:,jp_tra) |
---|
| 136 | |
---|
| 137 | DO jk = 1, jpkm1 |
---|
| 138 | zwsink2(:,:,jk+1) = -pwsink(:,:,jk) / rday * tmask(:,:,jk+1) |
---|
| 139 | END DO |
---|
| 140 | zwsink2(:,:,1) = 0.e0 |
---|
| 141 | |
---|
| 142 | |
---|
| 143 | ! Vertical advective flux |
---|
| 144 | DO jn = 1, 2 |
---|
| 145 | ! first guess of the slopes interior values |
---|
| 146 | DO jj = 1, jpj |
---|
| 147 | DO ji = 1, jpi |
---|
| 148 | ! |
---|
| 149 | zstep = rsfact / REAL( kiter(ji,jj), wp ) / 2. |
---|
| 150 | ! |
---|
| 151 | DO jk = 2, jpkm1 |
---|
| 152 | ztraz(ji,jj,jk) = ( trb(ji,jj,jk-1,jp_tra) - trb(ji,jj,jk,jp_tra) ) * tmask(ji,jj,jk) |
---|
| 153 | END DO |
---|
| 154 | ztraz(ji,jj,1 ) = 0.0 |
---|
| 155 | ztraz(ji,jj,jpk) = 0.0 |
---|
| 156 | |
---|
| 157 | ! slopes |
---|
| 158 | DO jk = 2, jpkm1 |
---|
| 159 | zign = 0.25 + SIGN( 0.25, ztraz(ji,jj,jk) * ztraz(ji,jj,jk+1) ) |
---|
| 160 | zakz(ji,jj,jk) = ( ztraz(ji,jj,jk) + ztraz(ji,jj,jk+1) ) * zign |
---|
| 161 | END DO |
---|
| 162 | |
---|
| 163 | ! Slopes limitation |
---|
| 164 | DO jk = 2, jpkm1 |
---|
| 165 | zakz(ji,jj,jk) = SIGN( 1., zakz(ji,jj,jk) ) * & |
---|
| 166 | & MIN( ABS( zakz(ji,jj,jk) ), 2. * ABS(ztraz(ji,jj,jk+1)), 2. * ABS(ztraz(ji,jj,jk) ) ) |
---|
| 167 | END DO |
---|
| 168 | |
---|
| 169 | ! vertical advective flux |
---|
| 170 | DO jk = 1, jpkm1 |
---|
| 171 | zigma = zwsink2(ji,jj,jk+1) * zstep / e3w_n(ji,jj,jk+1) |
---|
| 172 | zew = zwsink2(ji,jj,jk+1) |
---|
| 173 | psinkflx(ji,jj,jk+1) = -zew * ( trb(ji,jj,jk,jp_tra) - 0.5 * ( 1 + zigma ) * zakz(ji,jj,jk) ) * zstep |
---|
| 174 | END DO |
---|
| 175 | ! |
---|
| 176 | ! Boundary conditions |
---|
| 177 | psinkflx(ji,jj,1 ) = 0.e0 |
---|
| 178 | psinkflx(ji,jj,jpk) = 0.e0 |
---|
| 179 | |
---|
| 180 | DO jk=1,jpkm1 |
---|
| 181 | zflx = ( psinkflx(ji,jj,jk) - psinkflx(ji,jj,jk+1) ) / e3t_n(ji,jj,jk) |
---|
| 182 | trb(ji,jj,jk,jp_tra) = trb(ji,jj,jk,jp_tra) + zflx |
---|
| 183 | END DO |
---|
| 184 | END DO |
---|
| 185 | END DO |
---|
| 186 | END DO |
---|
| 187 | |
---|
| 188 | DO jk = 1,jpkm1 |
---|
| 189 | DO jj = 1,jpj |
---|
| 190 | DO ji = 1, jpi |
---|
| 191 | zflx = ( psinkflx(ji,jj,jk) - psinkflx(ji,jj,jk+1) ) / e3t_n(ji,jj,jk) |
---|
| 192 | ztrb(ji,jj,jk) = ztrb(ji,jj,jk) + 2. * zflx |
---|
| 193 | END DO |
---|
| 194 | END DO |
---|
| 195 | END DO |
---|
| 196 | |
---|
| 197 | trb(:,:,:,jp_tra) = ztrb(:,:,:) |
---|
| 198 | psinkflx(:,:,:) = 2. * psinkflx(:,:,:) |
---|
| 199 | ! |
---|
| 200 | IF( ln_timing ) CALL timing_stop('trc_sink2') |
---|
| 201 | ! |
---|
| 202 | END SUBROUTINE trc_sink2 |
---|
| 203 | |
---|
| 204 | SUBROUTINE trc_sink_ini |
---|
| 205 | !!--------------------------------------------------------------------- |
---|
| 206 | !! *** ROUTINE trc_sink_ini *** |
---|
| 207 | !! |
---|
| 208 | !! ** Purpose : read namelist options |
---|
| 209 | !!---------------------------------------------------------------------- |
---|
| 210 | INTEGER :: ios ! Local integer output status for namelist read |
---|
| 211 | !! |
---|
| 212 | NAMELIST/namtrc_snk/ nitermax |
---|
| 213 | !!---------------------------------------------------------------------- |
---|
| 214 | ! |
---|
| 215 | REWIND( numnat_ref ) ! namtrc_rad in reference namelist |
---|
| 216 | READ ( numnat_ref, namtrc_snk, IOSTAT = ios, ERR = 907) |
---|
| 217 | 907 IF( ios /= 0 ) CALL ctl_nam ( ios , 'namtrc_snk in reference namelist', lwp ) |
---|
| 218 | REWIND( numnat_cfg ) ! namtrc_rad in configuration namelist |
---|
| 219 | READ ( numnat_cfg, namtrc_snk, IOSTAT = ios, ERR = 908 ) |
---|
| 220 | 908 IF( ios > 0 ) CALL ctl_nam ( ios , 'namtrc_snk in configuration namelist', lwp ) |
---|
| 221 | IF(lwm) WRITE( numont, namtrc_snk ) |
---|
| 222 | |
---|
| 223 | IF(lwp) THEN ! ! Control print |
---|
| 224 | WRITE(numout,*) |
---|
| 225 | WRITE(numout,*) 'trc_sink : Sedimentation of particles ' |
---|
| 226 | WRITE(numout,*) '~~~~~~~ ' |
---|
| 227 | WRITE(numout,*) ' Namelist namtrc_snk : sedimentation of particles' |
---|
| 228 | WRITE(numout,*) ' Maximum number of iterations nitermax = ', nitermax |
---|
| 229 | WRITE(numout,*) |
---|
| 230 | ENDIF |
---|
| 231 | |
---|
| 232 | END SUBROUTINE trc_sink_ini |
---|
| 233 | |
---|
| 234 | !!====================================================================== |
---|
| 235 | END MODULE trcsink |
---|