1 | ! -*- Mode: f90 -*- |
---|
2 | MODULE math |
---|
3 | ! |
---|
4 | !> Some useful mathematical functions |
---|
5 | ! |
---|
6 | USE declare |
---|
7 | IMPLICIT NONE |
---|
8 | ! |
---|
9 | !> 2D vector type, quadruple precision |
---|
10 | TYPE v2d |
---|
11 | REAL (kind=rd) :: x !< X-coordinate |
---|
12 | REAL (kind=rd) :: y !< Y-coordinates |
---|
13 | END TYPE v2d |
---|
14 | ! |
---|
15 | !> Multiply 2D vectors |
---|
16 | INTERFACE OPERATOR ( * ) |
---|
17 | MODULE PROCEDURE vect_prod |
---|
18 | END INTERFACE |
---|
19 | ! |
---|
20 | CONTAINS |
---|
21 | ! |
---|
22 | ELEMENTAL FUNCTION vect_prod (a, b) |
---|
23 | !> Vector product |
---|
24 | USE declare |
---|
25 | IMPLICIT NONE |
---|
26 | ! |
---|
27 | REAL (kind=rl) :: vect_prod |
---|
28 | TYPE(v2d), INTENT (in) :: a !< First vector to multiply |
---|
29 | TYPE(v2d), INTENT (in) :: b !< 2nd vector to multiply |
---|
30 | ! |
---|
31 | vect_prod = a%x * b%y - a%y * b%x |
---|
32 | ! |
---|
33 | RETURN |
---|
34 | END FUNCTION vect_prod |
---|
35 | ! |
---|
36 | FUNCTION poly_surf (xa, ya ) |
---|
37 | !> Surface of a polygone |
---|
38 | USE declare |
---|
39 | IMPLICIT NONE |
---|
40 | ! |
---|
41 | REAL (kind=rl) :: poly_surf |
---|
42 | REAL (kind=rl), INTENT (in), DIMENSION ( :) :: xa, ya |
---|
43 | INTEGER (kind=il) :: jn |
---|
44 | REAL (kind=rd) :: zs |
---|
45 | ! |
---|
46 | zs = 0.0_rd |
---|
47 | DO jn = 1, SIZE (xa) - 2 |
---|
48 | zs = zs + v2d ( xa(jn+1)-xa(jn), ya(jn+1)-ya(jn)) * v2d ( xa(jn+2)-xa(jn), ya(jn+2)-ya(jn)) |
---|
49 | END DO |
---|
50 | poly_surf = 0.5_rl * zs |
---|
51 | ! |
---|
52 | RETURN |
---|
53 | END FUNCTION poly_surf |
---|
54 | ! |
---|
55 | ELEMENTAL FUNCTION dist (x1, y1, x2, y2) |
---|
56 | !> Distance between two points (cartesian) |
---|
57 | USE declare |
---|
58 | IMPLICIT NONE |
---|
59 | REAL (kind=rl) :: dist |
---|
60 | REAL (kind=rl), INTENT ( in) :: x1, y1, x2, y2 |
---|
61 | dist = SQRT ( (x2-x1)**2 + (y2-y1)**2 ) |
---|
62 | RETURN |
---|
63 | END FUNCTION dist |
---|
64 | ELEMENTAL FUNCTION ddist (x1, y1, x2, y2) |
---|
65 | !> Distance between two points (cartesian), quadruple precision |
---|
66 | USE declare |
---|
67 | IMPLICIT NONE |
---|
68 | REAL (kind=rd) :: ddist |
---|
69 | REAL (kind=rd), INTENT ( in) :: x1, y1, x2, y2 |
---|
70 | ddist = SQRT ( (x2-x1)**2 + (y2-y1)**2 ) |
---|
71 | RETURN |
---|
72 | END FUNCTION ddist |
---|
73 | ! |
---|
74 | ELEMENTAL FUNCTION dgeodist (x1, y1, x2, y2) |
---|
75 | !> Distance between two points (on sphere), quadruple precision |
---|
76 | USE declare |
---|
77 | IMPLICIT NONE |
---|
78 | REAL (kind=rd) :: dgeodist |
---|
79 | REAL (kind=rd), INTENT (in) :: x1, y1, x2, y2 |
---|
80 | REAL (kind=rd) :: zs, zrad |
---|
81 | zrad = ACOS ( -1.0_rd) / 180.0_rd |
---|
82 | zs = SIN (zrad*REAL(y1,rd)) * SIN (zrad*REAL(y2,rd)) & |
---|
83 | & + COS (zrad*REAL(y1,rd)) * COS (zrad*REAL(y2,rd)) * COS(zrad*REAL (x2-x1,rd)) |
---|
84 | zs = MAX (-1.0_rd, MIN (1.0_rd, zs)) |
---|
85 | dgeodist = REAL ( ACOS (zs), KIND=rl) |
---|
86 | RETURN |
---|
87 | END FUNCTION dgeodist |
---|
88 | ! |
---|
89 | !-$$ ELEMENTAL FUNCTION geodist (x1, y1, x2, y2) |
---|
90 | !-$$ !> Distance between two points (on sphere) |
---|
91 | !-$$ USE declare |
---|
92 | !-$$ IMPLICIT NONE |
---|
93 | !-$$ REAL (kind=rl) :: geodist |
---|
94 | !-$$ REAL (kind=rl), INTENT (in) :: x1, y1, x2, y2 |
---|
95 | !-$$ geodist = REAL (dgeodist (REAL (x1,rd), REAL (y1,rd), REAL (x2,rd), REAL(y2,rd)),rl) |
---|
96 | !-$$ END FUNCTION geodist |
---|
97 | |
---|
98 | ELEMENTAL FUNCTION geodist (zlon1, zlat1, zlon2, zlat2) |
---|
99 | !> Distance between two points (on sphere) |
---|
100 | USE declare |
---|
101 | IMPLICIT NONE |
---|
102 | REAL (kind=rl) :: geodist |
---|
103 | REAL (kind=rl), INTENT (in) :: zlon1, zlat1, zlon2, zlat2 |
---|
104 | REAL (kind=rl) :: zs, zrad |
---|
105 | zrad = ACOS ( -1.0_rl) / 180.0_rl |
---|
106 | zs = SIN (zrad*zlat1) * SIN (zrad*zlat2) + COS (zrad*zlat1) * COS (zrad*zlat2) * COS(zrad*(zlon2-zlon1)) |
---|
107 | zs = MAX (-1.0_rl, MIN (1.0_rl, zs)) |
---|
108 | geodist = ACOS (zs) |
---|
109 | RETURN |
---|
110 | END FUNCTION geodist |
---|
111 | |
---|
112 | !-$$ ELEMENTAL FUNCTION geodist_min (zlon1, zlat1, zlon2, zlat2, zdmax) |
---|
113 | !-$$ !> Distance between two points (on sphere). Simplified for too far points |
---|
114 | !-$$ USE declare |
---|
115 | !-$$ IMPLICIT NONE |
---|
116 | !-$$ REAL (kind=rl) :: geodist |
---|
117 | !-$$ REAL (kind=rl), INTENT (in) :: zlon1, zlat1, zlon2, zlat2, zdmax |
---|
118 | !-$$ REAL (kind=rl) :: zs, zrad |
---|
119 | !-$$ |
---|
120 | !-$$ IF ( ABS (zlat2-zlat1) .GT. zdmax * zrad ) THEN |
---|
121 | !-$$ geodist = zdmax |
---|
122 | !-$$ RETURN |
---|
123 | !-$$ END IF |
---|
124 | !-$$ |
---|
125 | !-$$ |
---|
126 | !-$$ zrad = ACOS ( -1.0_rl) / 180.0_rl |
---|
127 | !-$$ zs = SIN (zrad*zlat1) * SIN (zrad*zlat2) + COS (zrad*zlat1) * COS (zrad*zlat2) * COS(zrad*(zlon2-zlon1)) |
---|
128 | !-$$ zs = MAX (-1.0_rl, MIN (1.0_rl, zs)) |
---|
129 | !-$$ geodist = ACOS (zs) |
---|
130 | !-$$ RETURN |
---|
131 | !-$$ END FUNCTION geodist_min |
---|
132 | |
---|
133 | ! |
---|
134 | FUNCTION cartdist (zlon1, zlat1, zlon2, zlat2) |
---|
135 | !> Distance between two points (on sphere) |
---|
136 | ! Simplified computation |
---|
137 | USE declare |
---|
138 | IMPLICIT NONE |
---|
139 | REAL (kind=rl) :: cartdist |
---|
140 | REAL (kind=rl), INTENT (in) :: zlon1, zlat1, zlon2, zlat2 |
---|
141 | REAL (kind=rl) :: x1, y1, z1, x2, y2, z2, c1, c2, dx, dy, dz, dxyz |
---|
142 | REAL (kind=rl) :: zrad |
---|
143 | zrad = ACOS ( -1.0_rl) / 180.0_rl |
---|
144 | c1 = COS(zrad*zlat1) |
---|
145 | x1 = c1*COS(zrad*zlon1) |
---|
146 | y1 = c1*SIN(zrad*zlon1) |
---|
147 | z1 = SIN(zrad*zlat1) |
---|
148 | c2 = COS(zrad*zlat2) |
---|
149 | x2 = c2*COS(zrad*zlon2) |
---|
150 | y2 = c2*SIN(zrad*zlon2) |
---|
151 | z2 = SIN(zrad*zlat2) |
---|
152 | |
---|
153 | dx = x1-x1 ; dy = y1-y2 ; dz = z1-z2 |
---|
154 | dxyz = dx*dx + dy*dy + dz*dz |
---|
155 | cartdist = SQRT ( dxyz ) |
---|
156 | |
---|
157 | END FUNCTION cartdist |
---|
158 | ! |
---|
159 | ELEMENTAL FUNCTION an_som (x0, y0, x1, y1, x2, y2) |
---|
160 | !> Angle au sommet d'un triangle spherique |
---|
161 | USE declare |
---|
162 | IMPLICIT NONE |
---|
163 | REAL (kind=rd) :: an_som |
---|
164 | REAL (kind=rd), INTENT ( in) :: x0, y0, x1, y1, x2, y2 |
---|
165 | REAL (kind=rd) :: za, zb, zc, zs |
---|
166 | za = dgeodist (REAL(x1,rd), REAL(y1,rd), REAL(x2,rd), REAL(y2,rd)) |
---|
167 | zb = dgeodist (REAL(x0,rd), REAL(y0,rd), REAL(x1,rd), REAL(y1,rd)) |
---|
168 | zc = dgeodist (REAL(x0,rd), REAL(y0,rd), REAL(x2,rd), REAL(y2,rd)) |
---|
169 | IF ( za == 0.0_rd .OR. zb == 0.0_rd .OR. zc == 0.0_rd ) THEN |
---|
170 | an_som = 0.0_rd |
---|
171 | ELSE |
---|
172 | zs = ( COS(za)-COS(zb)*COS(zc) ) / ( SIN(zb)*SIN(zc) ) |
---|
173 | an_som = REAL (ACOS (zs)) |
---|
174 | ENDIF |
---|
175 | RETURN |
---|
176 | END FUNCTION an_som |
---|
177 | ! |
---|
178 | ELEMENTAL FUNCTION surf_sphe (x1, y1, x2, y2, x3, y3) |
---|
179 | !> Surface d'un triangle spherique |
---|
180 | USE declare |
---|
181 | IMPLICIT NONE |
---|
182 | REAL (kind=rd) :: surf_sphe |
---|
183 | REAL (kind=rd), INTENT ( in) :: x1, y1, x2, y2, x3, y3 |
---|
184 | REAL (kind=rd) :: za, zb, zc |
---|
185 | za = an_som (REAL(x1,rd), REAL(y1,rd), REAL(x3,rd), REAL(y3,rd), REAL(x2,rd), REAL(y2,rd)) |
---|
186 | zb = an_som (REAL(x2,rd), REAL(y2,rd), REAL(x1,rd), REAL(y1,rd), REAL(x3,rd), REAL(y3,rd)) |
---|
187 | zc = an_som (REAL(x3,rd), REAL(y3,rd), REAL(x2,rd), REAL(y2,rd), REAL(x1,rd), REAL(y1,rd)) |
---|
188 | IF ( za == 0.0_rd .OR. zb == 0.0_rd .OR. zc == 0.0_rd ) THEN |
---|
189 | surf_sphe = 0.0_rl |
---|
190 | ELSE |
---|
191 | surf_sphe = za + zb + zc - ACOS ( -1.0_rd) |
---|
192 | ENDIF |
---|
193 | RETURN |
---|
194 | END FUNCTION surf_sphe |
---|
195 | ! |
---|
196 | FUNCTION surf_box (xed, yed) |
---|
197 | !> Surface d'une boite de modele |
---|
198 | USE declare |
---|
199 | IMPLICIT NONE |
---|
200 | REAL (kind=rl) :: surf_box |
---|
201 | REAL (kind=rl), DIMENSION(9), INTENT(in) :: xed, yed |
---|
202 | INTEGER (kind=il) :: je, jne |
---|
203 | REAL (kind=rd) :: zsurf |
---|
204 | |
---|
205 | jne = SIZE(xed) |
---|
206 | zsurf = 0.0_rl |
---|
207 | |
---|
208 | DO je = 1, jne-1 |
---|
209 | zsurf = zsurf + surf_sphe (REAL(xed(jne ),rd), REAL(yed(jne ),rd), & |
---|
210 | & REAL(xed(je ),rd), REAL(yed(je ),rd), & |
---|
211 | & REAL(xed(je+1),rd), REAL(yed(je+1),rd) ) |
---|
212 | END DO |
---|
213 | |
---|
214 | surf_box = REAL (zsurf, kind = rl) |
---|
215 | |
---|
216 | RETURN |
---|
217 | END FUNCTION surf_box |
---|
218 | ! |
---|
219 | END MODULE math |
---|