| Directory: | ./ |
|---|---|
| File: | dyn3d_common/disvert.f90 |
| Date: | 2022-01-11 19:19:34 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 46 | 170 | 27.1% |
| Branches: | 21 | 95 | 22.1% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | ! $Id: disvert.F90 2786 2017-01-30 10:24:47Z emillour $ | ||
| 2 | |||
| 3 | 52 | SUBROUTINE disvert() | |
| 4 | |||
| 5 | use ioipsl, only: getin | ||
| 6 | use new_unit_m, only: new_unit | ||
| 7 | use assert_m, only: assert | ||
| 8 | USE comvert_mod, ONLY: ap, bp, aps, bps, nivsigs, nivsig, dpres, presnivs, & | ||
| 9 | pseudoalt, pa, preff, scaleheight | ||
| 10 | USE logic_mod, ONLY: ok_strato | ||
| 11 | |||
| 12 | IMPLICIT NONE | ||
| 13 | |||
| 14 | include "dimensions.h" | ||
| 15 | include "paramet.h" | ||
| 16 | include "iniprint.h" | ||
| 17 | |||
| 18 | !------------------------------------------------------------------------------- | ||
| 19 | ! Purpose: Vertical distribution functions for LMDZ. | ||
| 20 | ! Triggered by the levels number llm. | ||
| 21 | !------------------------------------------------------------------------------- | ||
| 22 | ! Read in "comvert_mod": | ||
| 23 | |||
| 24 | ! pa !--- vertical coordinate is close to a PRESSURE COORDINATE FOR P | ||
| 25 | ! < 0.3 * pa (relative variation of p on a model level is < 0.1 %) | ||
| 26 | |||
| 27 | ! preff !--- REFERENCE PRESSURE (101325 Pa) | ||
| 28 | ! Written in "comvert_mod": | ||
| 29 | ! ap(llm+1), bp(llm+1) !--- Ap, Bp HYBRID COEFFICIENTS AT INTERFACES | ||
| 30 | ! aps(llm), bps(llm) !--- Ap, Bp HYBRID COEFFICIENTS AT MID-LAYERS | ||
| 31 | ! dpres(llm) !--- PRESSURE DIFFERENCE FOR EACH LAYER | ||
| 32 | ! presnivs(llm) !--- PRESSURE AT EACH MID-LAYER | ||
| 33 | ! scaleheight !--- VERTICAL SCALE HEIGHT (Earth: 8kms) | ||
| 34 | ! nivsig(llm+1) !--- SIGMA INDEX OF EACH LAYER INTERFACE | ||
| 35 | ! nivsigs(llm) !--- SIGMA INDEX OF EACH MID-LAYER | ||
| 36 | !------------------------------------------------------------------------------- | ||
| 37 | ! Local variables: | ||
| 38 | REAL sig(llm+1), dsig(llm) | ||
| 39 | REAL sig0(llm+1), zz(llm+1) | ||
| 40 | REAL zk, zkm1, dzk1, dzk2, z, k0, k1 | ||
| 41 | |||
| 42 | INTEGER l, unit | ||
| 43 | REAL dsigmin | ||
| 44 | REAL vert_scale,vert_dzmin,vert_dzlow,vert_z0low,vert_dzmid,vert_z0mid,vert_h_mid,vert_dzhig,vert_z0hig,vert_h_hig | ||
| 45 | |||
| 46 | REAL alpha, beta, deltaz | ||
| 47 | REAL x | ||
| 48 | character(len=*),parameter :: modname="disvert" | ||
| 49 | |||
| 50 | character(len=24):: vert_sampling | ||
| 51 | ! (allowed values are "param", "tropo", "strato" and "read") | ||
| 52 | |||
| 53 | !----------------------------------------------------------------------- | ||
| 54 | |||
| 55 | 1 | WRITE(lunout,*) TRIM(modname)//" starts" | |
| 56 | |||
| 57 | ! default scaleheight is 8km for earth | ||
| 58 | 1 | scaleheight=8. | |
| 59 | |||
| 60 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | vert_sampling = merge("strato", "tropo ", ok_strato) ! default value |
| 61 | 1 | call getin('vert_sampling', vert_sampling) | |
| 62 | 1 | WRITE(lunout,*) TRIM(modname)//' vert_sampling = ' // vert_sampling | |
| 63 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (llm==39 .and. vert_sampling=="strato") then |
| 64 | 1 | dsigmin=0.3 ! Vieille option par défaut pour CMIP5 | |
| 65 | else | ||
| 66 | ✗ | dsigmin=1. | |
| 67 | endif | ||
| 68 | 1 | call getin('dsigmin', dsigmin) | |
| 69 | 1 | WRITE(LUNOUT,*) trim(modname), 'Discretisation verticale DSIGMIN=',dsigmin | |
| 70 | |||
| 71 | |||
| 72 | ✗ | select case (vert_sampling) | |
| 73 | case ("param") | ||
| 74 | ! On lit les options dans sigma.def: | ||
| 75 | ✗ | OPEN(99, file='sigma.def', status='old', form='formatted') | |
| 76 | ✗ | READ(99, *) scaleheight ! hauteur d'echelle 8. | |
| 77 | ✗ | READ(99, *) deltaz ! epaiseur de la premiere couche 0.04 | |
| 78 | ✗ | READ(99, *) beta ! facteur d'acroissement en haut 1.3 | |
| 79 | ✗ | READ(99, *) k0 ! nombre de couches dans la transition surf | |
| 80 | ✗ | READ(99, *) k1 ! nombre de couches dans la transition haute | |
| 81 | ✗ | CLOSE(99) | |
| 82 | ✗ | alpha=deltaz/(llm*scaleheight) | |
| 83 | ✗ | write(lunout, *)trim(modname),':scaleheight, alpha, k0, k1, beta', & | |
| 84 | ✗ | scaleheight, alpha, k0, k1, beta | |
| 85 | |||
| 86 | ✗ | alpha=deltaz/tanh(1./k0)*2. | |
| 87 | zkm1=0. | ||
| 88 | ✗ | sig(1)=1. | |
| 89 | ✗ | do l=1, llm | |
| 90 | sig(l+1)=(cosh(l/k0))**(-alpha*k0/scaleheight) & | ||
| 91 | *exp(-alpha/scaleheight*tanh((llm-k1)/k0) & | ||
| 92 | ✗ | *beta**(l-(llm-k1))/log(beta)) | |
| 93 | ✗ | zk=-scaleheight*log(sig(l+1)) | |
| 94 | |||
| 95 | ✗ | dzk1=alpha*tanh(l/k0) | |
| 96 | ✗ | dzk2=alpha*tanh((llm-k1)/k0)*beta**(l-(llm-k1))/log(beta) | |
| 97 | ✗ | write(lunout, *)l, sig(l+1), zk, zk-zkm1, dzk1, dzk2 | |
| 98 | ✗ | zkm1=zk | |
| 99 | enddo | ||
| 100 | |||
| 101 | ✗ | sig(llm+1)=0. | |
| 102 | |||
| 103 | ✗ | bp(: llm) = EXP(1. - 1. / sig(: llm)**2) | |
| 104 | ✗ | bp(llmp1) = 0. | |
| 105 | |||
| 106 | ✗ | ap = pa * (sig - bp) | |
| 107 | case("sigma") | ||
| 108 | ✗ | DO l = 1, llm | |
| 109 | ✗ | x = 2*asin(1.) * (l - 0.5) / (llm + 1) | |
| 110 | ✗ | dsig(l) = dsigmin + 7.0 * SIN(x)**2 | |
| 111 | ENDDO | ||
| 112 | ✗ | dsig = dsig / sum(dsig) | |
| 113 | ✗ | sig(llm+1) = 0. | |
| 114 | ✗ | DO l = llm, 1, -1 | |
| 115 | ✗ | sig(l) = sig(l+1) + dsig(l) | |
| 116 | ENDDO | ||
| 117 | |||
| 118 | ✗ | bp(1)=1. | |
| 119 | ✗ | bp(2: llm) = sig(2:llm) | |
| 120 | ✗ | bp(llmp1) = 0. | |
| 121 | ✗ | ap(:)=0. | |
| 122 | case("tropo") | ||
| 123 | ✗ | DO l = 1, llm | |
| 124 | ✗ | x = 2*asin(1.) * (l - 0.5) / (llm + 1) | |
| 125 | ✗ | dsig(l) = dsigmin + 7.0 * SIN(x)**2 | |
| 126 | ENDDO | ||
| 127 | ✗ | dsig = dsig / sum(dsig) | |
| 128 | ✗ | sig(llm+1) = 0. | |
| 129 | ✗ | DO l = llm, 1, -1 | |
| 130 | ✗ | sig(l) = sig(l+1) + dsig(l) | |
| 131 | ENDDO | ||
| 132 | |||
| 133 | ✗ | bp(1)=1. | |
| 134 | ✗ | bp(2: llm) = EXP(1. - 1. / sig(2: llm)**2) | |
| 135 | ✗ | bp(llmp1) = 0. | |
| 136 | |||
| 137 | ✗ | ap(1)=0. | |
| 138 | ✗ | ap(2: llm + 1) = pa * (sig(2: llm + 1) - bp(2: llm + 1)) | |
| 139 | case("strato") | ||
| 140 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 1 times.
|
40 | DO l = 1, llm |
| 141 | 39 | x = 2*asin(1.) * (l - 0.5) / (llm + 1) | |
| 142 | dsig(l) =(dsigmin + 7. * SIN(x)**2) & | ||
| 143 | 40 | *(0.5*(1.-tanh(1.*(x-asin(1.))/asin(1.))))**2 | |
| 144 | ENDDO | ||
| 145 |
4/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 1 times.
|
80 | dsig = dsig / sum(dsig) |
| 146 | 1 | sig(llm+1) = 0. | |
| 147 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 1 times.
|
40 | DO l = llm, 1, -1 |
| 148 | 40 | sig(l) = sig(l+1) + dsig(l) | |
| 149 | ENDDO | ||
| 150 | |||
| 151 | 1 | bp(1)=1. | |
| 152 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 1 times.
|
39 | bp(2: llm) = EXP(1. - 1. / sig(2: llm)**2) |
| 153 | 1 | bp(llmp1) = 0. | |
| 154 | |||
| 155 | 1 | ap(1)=0. | |
| 156 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 1 times.
|
40 | ap(2: llm + 1) = pa * (sig(2: llm + 1) - bp(2: llm + 1)) |
| 157 | case("strato_correct") | ||
| 158 | !================================================================== | ||
| 159 | ! Fredho 2014/05/18, Saint-Louis du Senegal | ||
| 160 | ! Cette version de la discretisation strato est corrige au niveau | ||
| 161 | ! du passage des sig aux ap, bp | ||
| 162 | ! la version precedente donne un coude dans l'epaisseur des couches | ||
| 163 | ! vers la tropopause | ||
| 164 | !================================================================== | ||
| 165 | |||
| 166 | |||
| 167 | ✗ | DO l = 1, llm | |
| 168 | ✗ | x = 2*asin(1.) * (l - 0.5) / (llm + 1) | |
| 169 | dsig(l) =(dsigmin + 7. * SIN(x)**2) & | ||
| 170 | ✗ | *(0.5*(1.-tanh(1.*(x-asin(1.))/asin(1.))))**2 | |
| 171 | ENDDO | ||
| 172 | ✗ | dsig = dsig / sum(dsig) | |
| 173 | ✗ | sig0(llm+1) = 0. | |
| 174 | ✗ | DO l = llm, 1, -1 | |
| 175 | ✗ | sig0(l) = sig0(l+1) + dsig(l) | |
| 176 | ENDDO | ||
| 177 | ✗ | sig=racinesig(sig0) | |
| 178 | |||
| 179 | ✗ | bp(1)=1. | |
| 180 | ✗ | bp(2:llm)=EXP(1.-1./sig(2: llm)**2) | |
| 181 | ✗ | bp(llmp1)=0. | |
| 182 | |||
| 183 | ✗ | ap(1)=0. | |
| 184 | ✗ | ap(2:llm)=pa*(sig(2:llm)-bp(2:llm)) | |
| 185 | ✗ | ap(llm+1)=0. | |
| 186 | |||
| 187 | CASE("strato_custom0") | ||
| 188 | !======================================================= | ||
| 189 | ! Version Transitoire | ||
| 190 | ! custumize strato distribution with specific alpha & beta values and function | ||
| 191 | ! depending on llm (experimental and temporary)! | ||
| 192 | SELECT CASE (llm) | ||
| 193 | CASE(55) | ||
| 194 | alpha=0.45 | ||
| 195 | beta=4.0 | ||
| 196 | CASE(63) | ||
| 197 | alpha=0.45 | ||
| 198 | beta=5.0 | ||
| 199 | CASE(71) | ||
| 200 | alpha=3.05 | ||
| 201 | beta=65. | ||
| 202 | CASE(79) | ||
| 203 | alpha=3.20 | ||
| 204 | ! alpha=2.05 ! FLOTT 79 (PLANTE) | ||
| 205 | beta=70. | ||
| 206 | END SELECT | ||
| 207 | ! Or used values provided by user in def file: | ||
| 208 | ✗ | CALL getin("strato_alpha",alpha) | |
| 209 | ✗ | CALL getin("strato_beta",beta) | |
| 210 | |||
| 211 | ! Build geometrical distribution | ||
| 212 | ✗ | scaleheight=7. | |
| 213 | ✗ | zz(1)=0. | |
| 214 | IF (llm==55.OR.llm==63) THEN | ||
| 215 | DO l=1,llm | ||
| 216 | z=zz(l)/scaleheight | ||
| 217 | zz(l+1)=zz(l)+0.03+z*1.5*(1.-TANH(z-0.5))+alpha*(1.+TANH(z-1.5)) & | ||
| 218 | +5.0*EXP((l-llm)/beta) | ||
| 219 | ENDDO | ||
| 220 | ELSEIF (llm==71) THEN !.OR.llm==79) THEN ! FLOTT 79 (PLANTE) | ||
| 221 | DO l=1,llm | ||
| 222 | z=zz(l) | ||
| 223 | zz(l+1)=zz(l)+0.02+0.88*TANH(z/2.5)+alpha*(1.+TANH((z-beta)/15.)) | ||
| 224 | ENDDO | ||
| 225 | ELSEIF (llm==79) THEN | ||
| 226 | DO l=1,llm | ||
| 227 | z=zz(l) | ||
| 228 | zz(l+1)=zz(l)+0.02+0.80*TANH(z/3.8)+alpha*(1+TANH((z-beta)/17.)) & | ||
| 229 | +0.03*TANH(z/.25) | ||
| 230 | ENDDO | ||
| 231 | ENDIF ! of IF (llm==55.OR.llm==63) ... | ||
| 232 | |||
| 233 | |||
| 234 | ! Build sigma distribution | ||
| 235 | ✗ | sig0=EXP(-zz(:)/scaleheight) | |
| 236 | ✗ | sig0(llm+1)=0. | |
| 237 | ! sig=ridders(sig0) | ||
| 238 | ✗ | sig=racinesig(sig0) | |
| 239 | |||
| 240 | ! Compute ap() and bp() | ||
| 241 | ✗ | bp(1)=1. | |
| 242 | ✗ | bp(2:llm)=EXP(1.-1./sig(2:llm)**2) | |
| 243 | ✗ | bp(llm+1)=0. | |
| 244 | ✗ | ap=pa*(sig-bp) | |
| 245 | |||
| 246 | CASE("strato_custom") | ||
| 247 | !=================================================================== | ||
| 248 | ! David Cugnet, François Lott, Lionel Guez, Ehouoarn Millour, Fredho | ||
| 249 | ! 2014/05 | ||
| 250 | ! custumize strato distribution | ||
| 251 | ! Al the parameter are given in km assuming a given scalehigh | ||
| 252 | ✗ | vert_scale=7. ! scale hight | |
| 253 | ✗ | vert_dzmin=0.02 ! width of first layer | |
| 254 | ✗ | vert_dzlow=1. ! dz in the low atmosphere | |
| 255 | ✗ | vert_z0low=8. ! height at which resolution recches dzlow | |
| 256 | ✗ | vert_dzmid=3. ! dz in the mid atmsophere | |
| 257 | ✗ | vert_z0mid=70. ! height at which resolution recches dzmid | |
| 258 | ✗ | vert_h_mid=20. ! width of the transition | |
| 259 | ✗ | vert_dzhig=11. ! dz in the high atmsophere | |
| 260 | ✗ | vert_z0hig=80. ! height at which resolution recches dz | |
| 261 | ✗ | vert_h_hig=20. ! width of the transition | |
| 262 | !=================================================================== | ||
| 263 | |||
| 264 | ✗ | call getin('vert_scale',vert_scale) | |
| 265 | ✗ | call getin('vert_dzmin',vert_dzmin) | |
| 266 | ✗ | call getin('vert_dzlow',vert_dzlow) | |
| 267 | ✗ | call getin('vert_z0low',vert_z0low) | |
| 268 | ✗ | CALL getin('vert_dzmid',vert_dzmid) | |
| 269 | ✗ | CALL getin('vert_z0mid',vert_z0mid) | |
| 270 | ✗ | call getin('vert_h_mid',vert_h_mid) | |
| 271 | ✗ | call getin('vert_dzhig',vert_dzhig) | |
| 272 | ✗ | call getin('vert_z0hig',vert_z0hig) | |
| 273 | ✗ | call getin('vert_h_hig',vert_h_hig) | |
| 274 | |||
| 275 | ✗ | scaleheight=vert_scale ! for consistency with further computations | |
| 276 | ! Build geometrical distribution | ||
| 277 | ✗ | zz(1)=0. | |
| 278 | ✗ | DO l=1,llm | |
| 279 | ✗ | z=zz(l) | |
| 280 | zz(l+1)=zz(l)+vert_dzmin+vert_dzlow*TANH(z/vert_z0low)+ & | ||
| 281 | & (vert_dzmid-vert_dzlow)* & | ||
| 282 | & (TANH((z-vert_z0mid)/vert_h_mid)-TANH((-vert_z0mid)/vert_h_mid)) & | ||
| 283 | & +(vert_dzhig-vert_dzmid-vert_dzlow)* & | ||
| 284 | ✗ | & (TANH((z-vert_z0hig)/vert_h_hig)-TANH((-vert_z0hig)/vert_h_hig)) | |
| 285 | ENDDO | ||
| 286 | |||
| 287 | |||
| 288 | !=================================================================== | ||
| 289 | ! Comment added Fredho 2014/05/18, Saint-Louis, Senegal | ||
| 290 | ! From approximate z to ap, bp, so that p=ap+bp*p0 and p/p0=exp(-z/H) | ||
| 291 | ! sig0 is p/p0 | ||
| 292 | ! sig is an intermediate distribution introduce to estimate bp | ||
| 293 | ! 1. sig0=exp(-z/H) | ||
| 294 | ! 2. inversion of sig0=(1-pa/p0)*sig+(1-pa/p0)*exp(1-1/sig**2) | ||
| 295 | ! 3. bp=exp(1-1/sig**2) | ||
| 296 | ! 4. ap deduced from the combination of 2 and 3 so that sig0=ap/p0+bp | ||
| 297 | !=================================================================== | ||
| 298 | |||
| 299 | ✗ | sig0=EXP(-zz(:)/vert_scale) | |
| 300 | ✗ | sig0(llm+1)=0. | |
| 301 | ✗ | sig=racinesig(sig0) | |
| 302 | ✗ | bp(1)=1. | |
| 303 | ✗ | bp(2:llm)=EXP(1.-1./sig(2:llm)**2) | |
| 304 | ✗ | bp(llm+1)=0. | |
| 305 | ✗ | ap=pa*(sig-bp) | |
| 306 | |||
| 307 | case("read") | ||
| 308 | ! Read "ap" and "bp". First line is skipped (title line). "ap" | ||
| 309 | ! should be in Pa. First couple of values should correspond to | ||
| 310 | ! the surface, that is : "bp" should be in descending order. | ||
| 311 | ✗ | call new_unit(unit) | |
| 312 | open(unit, file="hybrid.txt", status="old", action="read", & | ||
| 313 | ✗ | position="rewind") | |
| 314 | ✗ | read(unit, fmt=*) ! skip title line | |
| 315 | ✗ | do l = 1, llm + 1 | |
| 316 | ✗ | read(unit, fmt=*) ap(l), bp(l) | |
| 317 | end do | ||
| 318 | ✗ | close(unit) | |
| 319 | call assert(ap(1) == 0., ap(llm + 1) == 0., bp(1) == 1., & | ||
| 320 | ✗ | bp(llm + 1) == 0., "disvert: bad ap or bp values") | |
| 321 | case default | ||
| 322 |
1/9✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
1 | call abort_gcm("disvert", 'Wrong value for "vert_sampling"', 1) |
| 323 | END select | ||
| 324 | |||
| 325 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 1 times.
|
40 | DO l=1, llm |
| 326 | 40 | nivsigs(l) = REAL(l) | |
| 327 | ENDDO | ||
| 328 | |||
| 329 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 1 times.
|
41 | DO l=1, llmp1 |
| 330 | 41 | nivsig(l)= REAL(l) | |
| 331 | ENDDO | ||
| 332 | |||
| 333 | 1 | write(lunout, *) trim(modname),': BP ' | |
| 334 | 1 | write(lunout, *) bp | |
| 335 | 1 | write(lunout, *) trim(modname),': AP ' | |
| 336 | 1 | write(lunout, *) ap | |
| 337 | |||
| 338 | 1 | write(lunout, *) 'Niveaux de pressions approximatifs aux centres des' | |
| 339 | 1 | write(lunout, *)'couches calcules pour une pression de surface =', preff | |
| 340 | 1 | write(lunout, *) 'et altitudes equivalentes pour une hauteur d echelle de ' | |
| 341 | 1 | write(lunout, *) scaleheight,' km' | |
| 342 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 1 times.
|
40 | DO l = 1, llm |
| 343 | 39 | dpres(l) = bp(l) - bp(l+1) | |
| 344 | 39 | aps(l) = 0.5 *( ap(l) +ap(l+1)) | |
| 345 | 39 | bps(l) = 0.5 *( bp(l) +bp(l+1)) | |
| 346 | 39 | presnivs(l) = 0.5 *( ap(l)+bp(l)*preff + ap(l+1)+bp(l+1)*preff ) | |
| 347 | 39 | pseudoalt(l) = log(preff/presnivs(l))*scaleheight | |
| 348 | 39 | write(lunout, *)'PRESNIVS(', l, ')=', presnivs(l), ' Z ~ ', & | |
| 349 | pseudoalt(l) & | ||
| 350 | 39 | , ' DZ ~ ', scaleheight*log((ap(l)+bp(l)*preff)/ & | |
| 351 | 79 | max(ap(l+1)+bp(l+1)*preff, 1.e-10)) | |
| 352 | ENDDO | ||
| 353 | |||
| 354 | 1 | write(lunout, *) trim(modname),': PRESNIVS ' | |
| 355 | 1 | write(lunout, *) presnivs | |
| 356 | |||
| 357 | CONTAINS | ||
| 358 | |||
| 359 | !------------------------------------------------------------------------------- | ||
| 360 | ! | ||
| 361 | FUNCTION ridders(sig) RESULT(sg) | ||
| 362 | ! | ||
| 363 | !------------------------------------------------------------------------------- | ||
| 364 | IMPLICIT NONE | ||
| 365 | !------------------------------------------------------------------------------- | ||
| 366 | ! Purpose: Search for s solving (Pa/Preff)*s+(1-Pa/Preff)*EXP(1-1./s**2)=sg | ||
| 367 | ! Notes: Uses Ridders' method, quite robust. Initial bracketing: 0<=sg<=1. | ||
| 368 | ! Reference: Ridders, C. F. J. "A New Algorithm for Computing a Single Root of a | ||
| 369 | ! Real Continuous Function" IEEE Trans. Circuits Systems 26, 979-980, 1979 | ||
| 370 | !------------------------------------------------------------------------------- | ||
| 371 | ! Arguments: | ||
| 372 | REAL, INTENT(IN) :: sig(:) | ||
| 373 | REAL :: sg(SIZE(sig)) | ||
| 374 | !------------------------------------------------------------------------------- | ||
| 375 | ! Local variables: | ||
| 376 | INTEGER :: it, ns, maxit | ||
| 377 | REAL :: c1, c2, x1, x2, x3, x4, f1, f2, f3, f4, s, xx, distrib | ||
| 378 | !------------------------------------------------------------------------------- | ||
| 379 | ns=SIZE(sig); maxit=9999 | ||
| 380 | c1=Pa/Preff; c2=1.-c1 | ||
| 381 | DO l=1,ns | ||
| 382 | xx=HUGE(1.) | ||
| 383 | x1=0.0; f1=distrib(x1,c1,c2,sig(l)) | ||
| 384 | x2=1.0; f2=distrib(x2,c1,c2,sig(l)) | ||
| 385 | DO it=1,maxit | ||
| 386 | x3=0.5*(x1+x2); f3=distrib(x3,c1,c2,sig(l)) | ||
| 387 | s=SQRT(f3**2-f1*f2); IF(s==0.) EXIT | ||
| 388 | x4=x3+(x3-x1)*(SIGN(1.,f1-f2)*f3/s); IF(ABS(10.*LOG(x4-xx))<=1E-5) EXIT | ||
| 389 | xx=x4; f4=distrib(x4,c1,c2,sig(l)); IF(f4==0.) EXIT | ||
| 390 | IF(SIGN(f3,f4)/=f3) THEN; x1=x3; f1=f3; x2=xx; f2=f4 | ||
| 391 | ELSE IF(SIGN(f1,f4)/=f1) THEN; x2=xx; f2=f4 | ||
| 392 | ELSE IF(SIGN(f2,f4)/=f2) THEN; x1=xx; f1=f4 | ||
| 393 | ELSE; CALL abort_gcm("ridders",'Algorithm failed (which is odd...') | ||
| 394 | END IF | ||
| 395 | IF(ABS(10.*LOG(ABS(x2-x1)))<=1E-5) EXIT !--- ERROR ON SIG <= 0.01m | ||
| 396 | END DO | ||
| 397 | IF(it==maxit+1) WRITE(lunout,'(a,i3)')'WARNING in ridder: failed to converg& | ||
| 398 | &e for level ',l | ||
| 399 | sg(l)=xx | ||
| 400 | END DO | ||
| 401 | sg(1)=1.; sg(ns)=0. | ||
| 402 | |||
| 403 | END FUNCTION ridders | ||
| 404 | |||
| 405 | ✗ | FUNCTION racinesig(sig) RESULT(sg) | |
| 406 | ! | ||
| 407 | !------------------------------------------------------------------------------- | ||
| 408 | IMPLICIT NONE | ||
| 409 | !------------------------------------------------------------------------------- | ||
| 410 | ! Fredho 2014/05/18 | ||
| 411 | ! Purpose: Search for s solving (Pa/Preff)*sg+(1-Pa/Preff)*EXP(1-1./sg**2)=s | ||
| 412 | ! Notes: Uses Newton Raphson search | ||
| 413 | !------------------------------------------------------------------------------- | ||
| 414 | ! Arguments: | ||
| 415 | REAL, INTENT(IN) :: sig(:) | ||
| 416 | REAL :: sg(SIZE(sig)) | ||
| 417 | !------------------------------------------------------------------------------- | ||
| 418 | ! Local variables: | ||
| 419 | INTEGER :: it, ns, maxit | ||
| 420 | REAL :: c1, c2, x1, x2, x3, x4, f1, f2, f3, f4, s, xx, distrib | ||
| 421 | !------------------------------------------------------------------------------- | ||
| 422 | ns=SIZE(sig); maxit=100 | ||
| 423 | ✗ | c1=Pa/Preff; c2=1.-c1 | |
| 424 | ✗ | DO l=2,ns-1 | |
| 425 | ✗ | sg(l)=sig(l) | |
| 426 | ✗ | DO it=1,maxit | |
| 427 | ✗ | f1=exp(1-1./sg(l)**2)*(1.-c1) | |
| 428 | ✗ | sg(l)=sg(l)-(c1*sg(l)+f1-sig(l))/(c1+2*f1*sg(l)**(-3)) | |
| 429 | ENDDO | ||
| 430 | ! print*,'SSSSIG ',sig(l),sg(l),c1*sg(l)+exp(1-1./sg(l)**2)*(1.-c1) | ||
| 431 | ENDDO | ||
| 432 | ✗ | sg(1)=1.; sg(ns)=0. | |
| 433 | |||
| 434 | ✗ | END FUNCTION racinesig | |
| 435 | |||
| 436 | |||
| 437 | |||
| 438 | |||
| 439 | END SUBROUTINE disvert | ||
| 440 | |||
| 441 | !------------------------------------------------------------------------------- | ||
| 442 | |||
| 443 | ✗ | FUNCTION distrib(x,c1,c2,x0) RESULT(res) | |
| 444 | ! | ||
| 445 | !------------------------------------------------------------------------------- | ||
| 446 | ! Arguments: | ||
| 447 | REAL, INTENT(IN) :: x, c1, c2, x0 | ||
| 448 | REAL :: res | ||
| 449 | !------------------------------------------------------------------------------- | ||
| 450 | ✗ | res=c1*x+c2*EXP(1-1/(x**2))-x0 | |
| 451 | |||
| 452 | ✗ | END FUNCTION distrib | |
| 453 | |||
| 454 | |||
| 455 |