DEGREE-DAY CALCULATION FORMULAS
INTRODUCTION
At this time the USPEST.ORG IPM models - Weather Data website supports these types of degree-day calculations:
- [A] Simple Average (now w/horizontal upper threshold cutoff)
- [GD] Growing Degree Days (corn GDDs)
- [T1,T2] Single and Double Triangle (Sevacherian et al. 1977, J. Econ. Entomol. 70:399-402)
- [S1,S2] Single and Double Sine Curve (Baskerville & Emin 1969, Ecology 50:514-517)
- [I1,I2] Single and Double Sine Curve w/intermediate upper threshold cutoff (Roltsch et al 1999, Int J Biometeorol 42:169-176)
- [DH] Fire Blight Degree-Hours (fireblight model only; Smith 2010)
- [HD] Heating Degree-Days (power industry) (can be used as insect chilling units)
- [CD] Cooling Degree-Days (power industry)
- [WG] Bauer wheat model GDDs (Bauer et al. 1983 & 1984)
- [PD] Potato P-Days (used for potato early blight model)
- [XD] Max Temp only Heat Units (added for mountain pine beetle model)
- [XI] Max Temp only w/intermed. cutoff (Perry & Wehner 1996)
Below you will find the actual formulas used to calculate each of these.
The formulas are written in Perl, but should be legible to anyone with a working understanding of
any major programming language (e. g. C, Pascal, Fortran, BASIC, etc.)
Contact Len Coop at coopl@bcc.orst.edu or 541-737-5523 if
you have questions or have a need for some other calculation method.
#
# These are the formulas used to calculate heat units:
# Note: single and double Triangle and Sine methods assume you run twice;
# For "double" run once using $min from this morning and once using $min from tomorrow
# morning (then add them together)
# For "single" run twice using $min from this morning (then add them together)
sub docalcs1 { # SINGLE AND DOUBLE TRIANGLE METHODS
local($max, $min) = @_;
if (($min > $THI) && ($max > $THI)) {
$ddtmp = ($THI - $TLOW) / 2;
}
elsif (($max < $TLOW) && ($min < $TLOW)) {
$ddtmp = 0.0;
}
elsif (($min >= $TLOW) && ($max <= $THI)) {
$ddtmp = 6 * (($max + $min) - 2 * $TLOW) / 24;
}
elsif (($min < $TLOW) && ($max >= $TLOW)) {
$ddtmp = ((6 * ($max - $TLOW) ** 2) / ($max - $min)) / 24;
}
elsif (($min >= $TLOW) && ($max >= $THI)) {
$ddtmp = 6 * ($max + $min - 2 * $TLOW) / 24 - (6 * ($max - $THI) ** 2
/ ($max - $min)) / 24;
}
elsif (($min < $TLOW) && ($max >= $THI)) {
$ddtmp = (6 * ($max - $TLOW) ** 2 / ($max - $min) - 6 * ($max - $THI)
** 2 / ($max - $min)) / 24;
}
else {
$ddtmp = -999.99;
}
$ddtmp;
}
sub sinec { # SUBROUTINE USED BY THE SINE CURVE METHODS
local($sum, $diff, $fk1) = @_;
$twopi = 6.2834;
$pihlf = 1.5708;
$d2 = $fk1 - $sum;
$theta = atan2($d2, sqrt($diff * $diff - $d2 * $d2));
if (($d2 < 0) && ($theta > 0)) {
$theta = $theta - 3.1416;
}
$heat = ($diff * cos($theta) - $d2 * ($pihlf - $theta)) / $twopi;
$heat;
}
sub docalcs2 { # SINGLE AND DOUBLE SINE CURVE METHODS
local($max, $min) = @_;
if ($min > $THI) {
$heat = $THI - $TLOW;
}
else {
if ($max <= $TLOW) {
$heat = 0;
}
else {
$fk1 = 2 * $TLOW;
$diff = $max - $min;
$sum = $max + $min;
if ($min >= $TLOW) {
$heat = ($sum - $fk1) / 2;
}
else {
$heat = &sinec($sum, $diff, $fk1);
}
if ($max > $THI) {
$fk1 = 2 * $THI;
$zheat = $heat;
$heat = &sinec($sum, $diff, $fk1);
$heat = $zheat - $heat;
}
}
}
$ddtmp = $heat / 2;
$ddtmp;
}
sub docalcs3 { # SIMPLE AVERAGE METHOD - also called
# growing degree-days for cereals and several
# other crop growth models
# more cases to handle ADDED MAY 2015 LC
# 1. min > $THI (make this DD=0
# 2. max > $THI (handle this w/horiz cutoff like with growing DDs)
local($max, $min) = @_;
if (($max < $TLOW) && ($min < $TLOW)) {
$ddtmp = 0.0;
}
elsif ( ( $min > $THI ) && ( $max > $THI ) ) {
$ddtmp = 0.0;
}
else {
if ($max > $THI) {
$max = $THI;
}
$ddtmp = ($max + $min) / 2 - $TLOW;
}
if ($ddtmp < 0) {
$ddtmp = 0.0;
}
$ddtmp;
}
sub docalcs4 { # CORN GROWING DEGREE-DAYS
local($max, $min) = @_;
if (($max < $TLOW) && ($min < $TLOW)) {
$ddtmp = 0.0;
}
else {
if ($min < $TLOW) {
$min = $TLOW;
}
if ($max > $THI) {
$max = $THI;
}
$ddtmp = ($max + $min) / 2 - $TLOW;
if ($ddtmp < 0) {
$ddtmp = 0.0;
}
}
$ddtmp;
}
sub docalcs55 { # DEGREE-HOURS used by the OLD Fireblight model
local($max, $min) = @_;
$max = int($max + 0.5);
if ($max < $TLOW) {
$ddtmp = 0.0;
}
elsif ($min < 50) {
$ddtmp = $entry{$max, 1};
}
else {
$ddtmp = $entry{$max, 2};
}
$ddtmp;
}
sub docalcs5 { # DEGREE-HOURS used by the 2010EZ Fireblight model
# uses file fblookup.txt as a lookup table
local ( $max, $min ) = @_;
$max = int( $max + 0.5 );
if ( $max < 50 || $max > 102) {
$ddtmp = 0.0;
}
else {
$ddtmp = $entry{ $max, 1 };
}
$ddtmp;
}
sub docalcs6 { # HEATING DEGREE_DAYS used by heating and cooling
# industries - normally 65 is the TLOW with no
# THI
local($max, $min) = @_;
$ddtmp = $TLOW - (($max + $min)/2);
if ($ddtmp < 0) {
$ddtmp = 0.0;
}
$ddtmp;
}
sub docalcs7 { # COOLING DEGREE-DAYS used by heating and cooling
# industries - normally 65 is the TLOW with no
# THI
local($max, $min) = @_;
$ddtmp = (($max + $min)/2) - $TLOW;
if ($ddtmp < 0) {
$ddtmp = 0.0;
}
$ddtmp;
}
sub docalcs8
{ # P-DAYS used for potato growth and early blight treatment initiation
# added Dec 2010
# this is the daily approx version of equation 2 by Sands
local ( $max, $min ) = @_;
local ( $dp1, $dp2, $dp3, $dp4 ) = 0;
if ( $CELSIUS != 1 ) {
$cmax = ( $max - 32 ) * 5 / 9;
$cmin = ( $min - 32 ) * 5 / 9;
#$cmax = $max;
#$cmin = $min;
}
else {
$cmax = $max;
$cmin = $min;
}
$dp1 = &dp($cmin);
$dp2 = &dp( 0.66667 * $cmin + 0.333333 * $cmax );
$dp3 = &dp( 0.66667 * $cmax + 0.333333 * $cmin );
$dp4 = &dp($cmax);
#$ddtmp = 1.8/24 * (5*$dp1 + 8*$dp2 + 8*$dp3 + 3*$dp4);
$ddtmp = 1 / 24 * ( 5 * $dp1 + 8 * $dp2 + 8 * $dp3 + 3 * $dp4 );
$ddtmp;
}
sub dp { #estimate delta-p with $t temperature
local ($t) = @_;
local $dp = 0;
#local ($ta,$tb,$tc) = (7,21,30);
if ( $t < 7 || $t > 30 ) { $dp = 0.0 }
elsif ( ( $t >= 7 ) && ( $t < 21 ) ) {
$dp = 10 * ( 1 - ( $t - 21 )**2 / 196 );
}
elsif ( ( $t >= 21 ) && ( $t <= 30 ) ) {
$dp = 10 * ( 1 - ( $t - 21 )**2 / 81 );
}
if ( $dp < 0 ) { $dp = 0 }
$dp;
}
sub docalcs9 { # Exceed Tmax Heat Units w/upper horiz cutoff
# e.g. tmax=54 TLOW=50 THI=100 result=4
# e.g. tmax=104 TLOW=50 THI=100 result=50
# added for mountain pine beetle, should be useful
# as an insect adult activity threshold model
local ( $max, $min ) = @_;
if ( $max > $THI ) {
$max = $THI;
}
$ddtmp = $max - $TLOW;
if ( $ddtmp < 0 ) {
$ddtmp = 0.0;
}
$ddtmp;
}
sub docalcs_XI { # MAX TEMP W/INTERMED UPPER CUTOFF METHOD - added MAY 2015
# as per Perry & Wehner 1996 HortTechnology Jan/Mar 1996 27:30
# other crop growth models:
# ignore $min and
# if max > $THI subt. diff betw $max and $THI as a "heat penalty"
local ( $max, $min ) = @_;
if ( $max < $TLOW ) {
$ddtmp = 0.0;
}
elsif ($max > $THI) {
$ddtmp = ( $THI - ( $max - $THI )) - $TLOW;
}
else { # more cases to handle ADDED MAY 2015 Len
$ddtmp = $max - $TLOW;
}
if ( $ddtmp < 0 ) {
$ddtmp = 0.0;
}
$ddtmp;
}
sub docalcs10 { # WHEAT (Bauer model) GROWING DEGREE-DAYS
# TLOW =32
# # use TMAX=70 if prior to 2nd Leaf Stage ( < 215 DD )
# # use TMAX=95 if not prior to 2nd Leaf Stage ( >= 215 DD )
my $l_THI = 95;
if ($CELSIUS == 1) {
if ($dd_cum < 215*5/9 && $past_biofix == 1) {
$l_THI = 21;
}
elsif ($dd_cum >= 215*5/9 && $past_biofix == 1) {
$l_THI = 35;
}
}
else { # FAHRENHEIT
if ($dd_cum < 215 && $past_biofix == 1) {
$l_THI = 70;
}
elsif ($dd_cum >= 215 && $past_biofix == 1) {
$l_THI = 95;
}
}
local ( $max, $min ) = @_;
if ( ( $max < $TLOW ) && ( $min < $TLOW ) ) {
$ddtmp = 0.0;
}
else {
if ( $min < $TLOW ) {
$min = $TLOW;
}
if ( $max > $l_THI ) {
$max = $l_THI;
}
$ddtmp = ( $max + $min ) / 2 - $TLOW;
if ( $ddtmp < 0 ) {
$ddtmp = 0.0;
}
}
$ddtmp;
}
Last updated Feb 6, 2023
prep. by L. Coop