libSUFR
a LIBrary of Some Useful Fortran Routines
All Classes Namespaces Files Functions Variables Pages
sports.f90
Go to the documentation of this file.
1!> \file sports.f90 Procedures related to sports
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 related to sports
22
24 implicit none
25 save
26
27contains
28
29 !*********************************************************************************************************************************
30 !> \brief Compute the power used for cycling. Add the three components to get the total power.
31 !!
32 !! \param mass Mass of the rider + bike (kg)
33 !! \param slope Slope of the road, fraction
34 !! \param vair Air speed of the rider (m/s)
35 !! \param vgr Ground speed of the rider (m/s)
36 !!
37 !! \param pwr_mech Power to overcome mechanical resistance (of a typical bike, W) (output)
38 !! \param pwr_air Power to overcome air resistance (W) (output)
39 !! \param pwr_climb Power to climb a given slope (W) (output)
40 !!
41 !! \see
42 !! - https://en.wikipedia.org/wiki/Drag_%28physics%29#Power
43 !! - https://en.wikipedia.org/wiki/Bicycle_performance#Power_required
44 !! - http://www.sportsci.org/jour/9804/dps.html
45 !! - Charles Henry (2015-03-15). "Diagram of Crr as a function of V" - http://www.velomobil.ch/ch/sites/default/files/images/pages/reifenpruefstand/diagramm_cr_v.jpg
46 !! - ~/diverse/software/Fortran/fit/07_Bicycle_tyre_resistance (used Schwalbe Ultremo 2x for fit)
47
48 pure subroutine cycling_power(mass, slope, vair, vgr, pwr_mech, pwr_air, pwr_climb)
49 use sufr_kinds, only: double
50 use sufr_weather, only: air_density
51
52 implicit none
53 real(double), intent(in) :: mass, slope, vair, vgr
54 real(double), intent(out) :: pwr_mech, pwr_air, pwr_climb
55 real(double) :: k1,k2,g, g_mass_vgr
56 real(double) :: rho, surf,c_d, temp,press
57
58 !k1 = 0.0053d0 ! lumped constant for all frictional losses (tires, bearings, chain), dimensionless
59 k1 = 0.00267d0 + 0.001018d0 * vgr**0.46435d0 ! Schwalbe Ultremo 2x
60
61 ! Compute the air density for the given temperature and pressure:
62 temp = 15.d0 + 273.15d0 ! Temperature in deg C -> K
63 press = 1015.d0 * 100.d0 ! Pressure in mbar/hPa -> Pa
64 rho = air_density(press, temp) ! SI, kg/m^3
65
66 !k2 = 0.185d0 ! lumped constant for aerodynamic drag, kg/m, compute it below from T, P
67 surf = 0.4d0 ! Typical surface of a rider, m^2
68 c_d = 0.7d0 ! Drag coefficient
69 k2 = 0.5d0 * rho * surf * c_d ! 1/2 rho A C_d - A=0.4m^2, C_d=0.7 - k2 = 0.1718 with these numbers (T=15°C,P=1015hPa,surf=0.4,c_d=0.7)
70
71 g = 9.81d0 ! Gravitational acceleration, m/s^2
72
73 g_mass_vgr = g * mass * vgr
74 pwr_mech = k1 * g_mass_vgr ! Mechanical resistance
75 pwr_climb = slope * g_mass_vgr ! Slope
76 pwr_air = k2 * vair**2 * vgr ! Air resistance
77
78 end subroutine cycling_power
79 !*********************************************************************************************************************************
80
81
82 !*********************************************************************************************************************************
83 !> \brief Compute the power used for cycling, single-precision wrapper for cycling_power
84 !!
85 !! \param mass Mass of the rider + bike (kg)
86 !! \param slope Slope of the road, fraction
87 !! \param vair Air speed of the rider (m/s)
88 !! \param vgr Ground speed of the rider (m/s)
89 !!
90 !! \param pwr_mech Power to overcome mechanical resistance (of a typical bike, W) (output)
91 !! \param pwr_air Power to overcome air resistance (W) (output)
92 !! \param pwr_climb Power to climb a given slope (W) (output)
93 !!
94 !! \see
95 !! - https://en.wikipedia.org/wiki/Drag_%28physics%29#Power
96 !! - https://en.wikipedia.org/wiki/Bicycle_performance#Power_required
97
98 pure subroutine cycling_power_sp(mass, slope, vair, vgr, pwr_mech, pwr_air, pwr_climb)
99 use sufr_kinds, only: double
100 implicit none
101 real, intent(in) :: mass, slope, vair, vgr
102 real, intent(out) :: pwr_mech, pwr_air, pwr_climb
103 real(double) :: mass_dbl, slope_dbl, vair_dbl, vgr_dbl, pwr_mech_dbl, pwr_air_dbl, pwr_climb_dbl
104
105 mass_dbl = dble(mass)
106 slope_dbl = dble(slope)
107 vair_dbl = dble(vair)
108 vgr_dbl = dble(vgr)
109
110 call cycling_power(mass_dbl, slope_dbl, vair_dbl, vgr_dbl, pwr_mech_dbl, pwr_air_dbl, pwr_climb_dbl)
111
112 pwr_mech = real(pwr_mech_dbl)
113 pwr_air = real(pwr_air_dbl)
114 pwr_climb = real(pwr_climb_dbl)
115
116 end subroutine cycling_power_sp
117 !*********************************************************************************************************************************
118
119
120 !*********************************************************************************************************************************
121 !> \brief Convert heart rate to body power + uncertainty
122 !!
123 !! \param gender Athlete's gender: f(emale) or m(ale)
124 !! \param age Athlete's age (years)
125 !! \param mass Athlete's body mass (kg)
126 !! \param HR Heart rate (beats per minute)
127 !!
128 !! \param power Body power (W) (output)
129 !! \param dpower Uncertainty in body power (W) (output)
130 !!
131 !! \see Keytel et al., Prediction of energy expenditure from heart rate monitoring during submaximal exercise,
132 !! JSS 23:3, 289 (2005)
133
134 subroutine heartrate2power(gender, age, mass, HR, power, dpower)
135 use sufr_kinds, only: double
137
138 character, intent(in) :: gender
139 real(double), intent(in) :: age, mass, HR
140 real(double), intent(out) :: power, dpower
141
142 select case(gender)
143 case('f','F') ! Female
144 power = -20.4022d0 + 0.4472d0 * hr - 0.1263d0 * mass + 0.0740d0 * age
145 dpower = sqrt( 7.2318d0**2 + (0.0165d0 * hr)**2 + (0.1061d0 * mass)**2 + (0.1742d0 * age)**2 )
146 case('m','M') ! Male
147 power = -55.0969d0 + 0.6309d0 * hr + 0.1988d0 * mass + 0.2017d0 * age ! Power in kJ/min (!)
148 dpower = sqrt( 5.5780d0**2 + (0.0137d0 * hr)**2 + (0.0619d0 * mass)**2 + (0.1180d0 * age)**2 )
149 case default
150 call quit_program_error('libSUFR heartRate2Power(): unknown gender: '//gender, 0)
151 end select
152
153 ! Convert kJ/min to W:
154 power = power * 1000.d0/60.d0 ! i.e., *16.667
155 dpower = dpower * 1000.d0/60.d0 ! i.e., *16.667
156
157 end subroutine heartrate2power
158 !*********************************************************************************************************************************
159
160end module sufr_sports
161!***********************************************************************************************************************************
162
Provides kinds and related constants/routines.
Definition kinds.f90:26
integer, parameter double
Double-precision float. Precision = 15, range = 307.
Definition kinds.f90:35
Procedures related to sports.
Definition sports.f90:23
pure subroutine cycling_power_sp(mass, slope, vair, vgr, pwr_mech, pwr_air, pwr_climb)
Compute the power used for cycling, single-precision wrapper for cycling_power.
Definition sports.f90:99
pure subroutine cycling_power(mass, slope, vair, vgr, pwr_mech, pwr_air, pwr_climb)
Compute the power used for cycling. Add the three components to get the total power.
Definition sports.f90:49
subroutine heartrate2power(gender, age, mass, hr, power, dpower)
Convert heart rate to body power + uncertainty.
Definition sports.f90:135
System-related procedures.
Definition system.f90:23
subroutine quit_program_error(message, status)
Print an error message to StdErr and stop the execution of the current program.
Definition system.f90:78
Procedures to deal with weather.
Definition weather.f90:21
elemental real(double) function air_density(press, temp)
Compute the air density for the given temperature and pressure.
Definition weather.f90:64