EMPIRE DA  v1.9.1
Data assimilation codes using EMPIRE communication
 All Classes Files Functions Variables Pages
lambertw.f90
Go to the documentation of this file.
1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2 !!! Time-stamp: <2015-05-21 13:35:03 pbrowne>
3 !!!
4 !!! Subroutine to implement the lambertw function
5 !!! Copyright (C) 2015 Mengbin Zhu
6 !!!
7 !!! This program is free software: you can redistribute it and/or modify
8 !!! it under the terms of the GNU General Public License as published by
9 !!! the Free Software Foundation, either version 3 of the License, or
10 !!! (at your option) any later version.
11 !!!
12 !!! This program is distributed in the hope that it will be useful,
13 !!! but WITHOUT ANY WARRANTY; without even the implied warranty of
14 !!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 !!! GNU General Public License for more details.
16 !!!
17 !!! You should have received a copy of the GNU General Public License
18 !!! along with this program. If not, see <http://www.gnu.org/licenses/>.
19 !!!
20 !!! Email: zhumengbin @ gmail.com
21 !!! Mail: School of Mathematical and Physical Sciences,
22 !!! University of Reading,
23 !!! Reading, UK
24 !!! RG6 6BB
25 !!!
26 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
27 
30 SUBROUTINE lambertw(K,X,W)
31 
32 !######################################################################
33 !Lambert W Function Numerical Solver
34 !In mathematics, the Lambert W function, also called the omega function
35 !or product logarithm, is a set of functions, namely the branches of
36 !the inverse relation of the function z = f(W) = We^W
37 !where e^W is the exponential function and W is any complex number.
38 !
39 !University of Reading,
40 !Dept. of Meteorology,
41 !Mengbin Zhu 14/04/2015
42 !######################################################################
43 
44 IMPLICIT NONE
45 
46 INTEGER, INTENT(IN) :: K
47 REAL(KIND=KIND(1.0d0)), INTENT(IN) :: X
48 REAL(KIND=KIND(1.0d0)), INTENT(OUT) :: W
49 
50 INTEGER :: I,J,Q,R,Q2,Q3
51 
52 REAL(KIND=KIND(1.0d0)),PARAMETER :: EPS=4.0E-16
53 REAL(KIND=KIND(1.0d0)),PARAMETER :: EM1=0.3678794411714423215955237701614608
54 
55 REAL(KIND=KIND(1.0d0)) :: PP,EE,TT2,L1,L2
56 
57 IF(k==0) THEN !Lambert W-Function 0 Branch
58  IF(x<-em1) THEN
59  print*,'Lambert W-Function: Bad Argument! STOP!'
60  RETURN
61  END IF
62  IF(x==0.0) THEN
63  w=0.0
64  RETURN
65  END IF
66  IF(x<(-em1+1e-4)) THEN
67  q=x+em1
68  r=sqrt(REAL(q))
69  q2=q*q
70  q3=q2*q
71  w=-1.0 &
72  & +2.331643981597124203363536062168*r &
73  & -1.812187885639363490240191647568*q &
74  & +1.936631114492359755363277457668*r*q &
75  & -2.353551201881614516821543561516*q2 &
76  & +3.066858901050631912893148922704*r*q2 &
77  & -4.175335600258177138854984177460*q3 &
78  & +5.858023729874774148815053846119*r*q3 &
79  & -8.401032217523977370984161688514*q3*q
80  RETURN
81  END IF
82  IF(x<1.0) THEN
83  pp=sqrt(2.0*(2.7182818284590452353602874713526625*x+1.0))
84  w=-1.0+pp*(1.0+pp*(-0.333333333333333333333+pp*0.152777777777777777777777))
85  ELSE
86  w=log(x)
87  END IF
88  !IF(X>3.0) THEN
89  ! W=W-LOG(W)
90  !END IF
91 
92  tt2=1.0
93  i=0
94  DO WHILE (abs(tt2)>(eps*(1.0+abs(w))))
95  !PRINT*,"Cannot go out of the cycle 0 Branch."
96  i=i+1
97  ee=exp(w)
98  tt2=w*ee-x
99  pp=w+1.0
100  tt2=tt2/(ee*pp-0.5*(pp+1.0)*tt2/pp)
101  w=w-tt2
102  !PRINT*,W
103  IF(i==20) THEN
104  w = w + 1.0e-6
105  END IF
106  IF(i==40) EXIT
107  END DO
108 
109 ELSE IF (k==-1) THEN !Lambert W-Function -1 Branch.
110  !IF(X<-EM1 .OR. X>0.0) THEN
111  ! PRINT*,'Lambert W-Function -1 Branch: Bad Argument! STOP!'
112  ! !STOP
113  ! RETURN
114  !END IF
115  !PRINT*,"THE -1 BRANCH"
116  IF(x==0.0) THEN
117  w=0.0
118  ELSE
119  !PRINT*,X
120  pp=1.0
121  IF(x<(-1e-6)) THEN
122  !PRINT*,"IS THIS REAL?"
123  pp=-sqrt(2.0*(2.7182818284590452353602874713526625*x+1.0))
124  w=-1.0+pp*(1.0+pp*(-0.333333333333333333333+pp*0.152777777777777777777777))
125  ELSE
126  l1=log(-x)
127  l2=log(-l1)
128  w=l1-l2+l2/l1
129  END IF
130  IF(abs(pp)<1e-4) THEN
131  RETURN
132  END IF
133  tt2=1.0
134  i=0
135  DO WHILE(abs(tt2)>eps*(1.0+abs(w)))
136  !PRINT*,"Cannot go out of the cycle"
137  i=i+1
138  ee=exp(w)
139  tt2=w*ee-x
140  pp=w+1.0
141  tt2=tt2/(ee*pp-0.5*(pp+1.0)*tt2/pp)
142  w=w-tt2
143  !PRINT*,W
144  IF(i==20) THEN
145  w = w + 1.0e-6
146  END IF
147  IF(i==40) EXIT
148  END DO
149  ENDIF
150 
151 ELSE
152  print*,"Lambert W-Function Branch Should Be -1 OR 0!"
153  !STOP
154  RETURN
155 END IF
156 
157 END SUBROUTINE lambertw
subroutine lambertw(K, X, W)
subroutine to implement the lambertw function see https://en.wikipedia.org/wiki/Lambert_W_function ...
Definition: lambertw.f90:30