libSUFR
a LIBrary of Some Useful Fortran Routines
All Classes Namespaces Files Functions Variables Pages
earth.f90
Go to the documentation of this file.
1!> \file earth.f90 Procedures to deal with geography and the Earth
2
3
4! Copyright (c) 2002-2025 Marc van der Sluys - Nikhef/Utrecht University - marc.vandersluys.nl
5!
6! This file is part of the libSUFR package,
7! see: http://libsufr.sourceforge.net/
8!
9! This is free software: you can redistribute it and/or modify it under the terms of the European Union
10! Public Licence 1.2 (EUPL 1.2). This software is distributed in the hope that it will be useful, but
11! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12! PURPOSE. See the EU Public Licence for more details. You should have received a copy of the European
13! Union Public Licence along with this code. If not, see <https://www.eupl.eu/1.2/en/>.
14!
15!
16
17
18
19
20!***********************************************************************************************************************************
21!> \brief Procedures to deal with geography and the Earth
22
24 implicit none
25 save
26
27contains
28
29
30 !*********************************************************************************************************************************
31 !> \brief Compute the distance between two points over the Earth's surface
32 !!
33 !! \param lon1 Longitude of first location (rad)
34 !! \param lat1 Latitude of first location (rad)
35 !! \param lon2 Longitude of second location (rad)
36 !! \param lat2 Latitude of second location (rad)
37 !!
38 !! \param miles Return result in miles if present and True, otherwise return result in kilometres
39 !!
40 !! \retval distance The distance between the two points over the Earth's surface (in km or mi)
41
42 pure function distance(lon1,lat1, lon2,lat2, miles)
43 use sufr_kinds, only: double
44 use sufr_constants, only: earthr
45 implicit none
46 real(double), intent(in) :: lon1,lat1, lon2,lat2
47 logical, optional, intent(in) :: miles
48 real(double) :: r_e,fl,distance
49 real(double) :: mlat,dlat2,dlon2, sins2,coss2,rat, r,dist, h1,h2
50 logical :: milesl
51
52 milesl = .false. ! Return value in kilometres by default
53 if(present(miles)) milesl = miles
54
55 r_e = earthr*1.d-5 ! Earth's radius in km
56 fl = 0.003352810665d0 ! Earth's flattening
57
58 mlat = (lat1+lat2)*0.5d0
59 dlat2 = (lat1-lat2)*0.5d0
60 dlon2 = (lon1-lon2)*0.5d0
61
62 sins2 = sin(dlat2)**2 * cos(dlon2)**2 + cos(mlat)**2 * sin(dlon2)**2
63 coss2 = cos(dlat2)**2 * cos(dlon2)**2 + sin(mlat)**2 * sin(dlon2)**2
64 rat = atan2(sqrt(sins2),sqrt(coss2))
65
66 r = sqrt(sins2*coss2)/(rat + tiny(rat)) ! Prevent division by zero - good idea?
67 dist = 2 * r_e * rat
68
69 h1 = (3*r-1) / (2*coss2 + tiny(coss2))
70 h2 = (3*r+1) / (2*sins2 + tiny(sins2))
71
72 distance = dist*(1.d0 + fl*h1*sin(mlat)**2 * cos(dlat2)**2 - fl*h2*cos(mlat)**2 * sin(dlat2)**2)
73 if(milesl) distance = distance * 0.62137119d0 ! Miles rather than km - this is just one of the many definitions of a mile!
74
75 end function distance
76 !*********************************************************************************************************************************
77
78
79
80
81 !*********************************************************************************************************************************
82 !> \brief Compute the distance between two points over the Earth's surface -- single-precision version of distance()
83 !!
84 !! \param lon1 Longitude of first location (rad)
85 !! \param lat1 Latitude of first location (rad)
86 !! \param lon2 Longitude of second location (rad)
87 !! \param lat2 Latitude of second location (rad)
88 !!
89 !! \param miles Return result in miles if present and True, otherwise return result in kilometres
90 !!
91 !! \retval distance_r The distance between the two points over the Earth's surface (in km or mi)
92
93 pure function distance_r(lon1,lat1, lon2,lat2, miles)
94 implicit none
95 real, intent(in) :: lon1,lat1, lon2,lat2
96 logical, optional, intent(in) :: miles
97 real :: distance_r
98 logical :: milesl
99
100 milesl = .false. ! Return value in kilometres by default
101 if(present(miles)) milesl = miles
102
103 distance_r = real( distance(dble(lon1),dble(lat1), dble(lon2),dble(lat2), milesl) )
104
105 end function distance_r
106 !*********************************************************************************************************************************
107
108
109
110
111end module sufr_earth
112!***********************************************************************************************************************************
113
Provides all constants in the library, and routines to define them.
Definition constants.f90:23
real(double), parameter, public earthr
Equatorial radius of the Earth in cm, WGS84.
Procedures to deal with geography and the Earth.
Definition earth.f90:23
pure real(double) function distance(lon1, lat1, lon2, lat2, miles)
Compute the distance between two points over the Earth's surface.
Definition earth.f90:43
pure real function distance_r(lon1, lat1, lon2, lat2, miles)
Compute the distance between two points over the Earth's surface – single-precision version of distan...
Definition earth.f90:94
Provides kinds and related constants/routines.
Definition kinds.f90:26
integer, parameter double
Double-precision float. Precision = 15, range = 307.
Definition kinds.f90:35