program evap c********************************************************************** c This program computes evapotranspiration from methods described in * c Thornthwaite and Mather 1957, using tables from their report and * c monthly mean temperatures that were thissen weighted for individual* c subbasins at the Great Lakes Environmental Research Laboratory. * c Designed and Programmed by: Cynthia E. Sellinger, Physical * c Scientist, Great Lakes Environmental Research Laboratory, National * c Oceanic and Atmospheric Administration, Department of Commerce. * c * c 20 Aug 2013 - Slight modifications by Tim Hunter, IT Specialist, * c NOAA/GLERL. In response to user-reported issues, I noted and * c made minimal fixes including the following: * c 1) Replaced imbedded TAB characters with spaces. This was * c required for consistent compiler performance. * c 2) Fixed some formatting issues in the main program. Significant * c issues remain with the indentation. This code is not very * c easy to read due to the indentation issues, but I do not * c have time to finish repairing that. * c 3) Very minor changes in file handling to make it a tiny bit * c more user-friendly. * c 4) Recompiled with gfortran 4.8.0 and placed revised executable * c on our ftp site. Hoping that this resolves the user issues. * c********************************************************************** implicit none real avg,temp,ae,stt, + heat1,year_heat,total,pet,evapo,lat,correction, + heat,precip,temp_1,precip_1,latitude,p_pe, + x,y integer i,j,year,col,mon,count,count2, + year2,ns,year_1,mon_1,moist,row character*50 file1,file3 c c PRINT *, ' ' PRINT *, ' ' PRINT *, ' ' PRINT *, ' ' PRINT *, ' ' print *, ' Enter the filename of the monthly ' print *, ' averaged temperature and precipitation. ' print *, ' NOTE: temperatures should be in degrees of' print *, ' Celsius and precipitation values should ' print *, ' be monthly totals in units of millimeters.' PRINT *, ' ' PRINT *, ' ' PRINT *, ' ' PRINT *, ' ' PRINT *, ' ' read(5,2)file1 print *, 'Enter outfile name ' read(5,2)file3 c print *, 'enter "1" for northern hemisphere and "2" for ' print *, 'southern hemisphere ' read(5,*)ns print *, 'enter the latitude of your area ' read(5,*)latitude print *, ' ' print *, ' ' print *, ' ' print *, ' Choose a number 1-11 for the moisture holding' print *, ' capacity of the soil ' print *, ' ' print *, ' ' print *, ' 1. 25 millimeters' print *, ' 2. 50 millimeters' print *, ' 3. 75 millimeters' print *, ' 4. 100 millimeters' print *, ' 5. 125 millimeters' print *, ' 6. 150 millimeters' print *, ' 7. 200 millimeters' print *, ' 8. 250 millimeters' print *, ' 9. 300 millimeters' print *, ' 10. 350 millimeters' print *, ' 11. 400 millimeters' print *, ' ' print *, ' ' print *, ' ' read(5,*)moist c c c c Three steps must be taken to find evapotranspiration, first must obtain c the heat index given monthly temperatures and using table 2 of section 1. c c read in heat index,unadjusted potential evap files, and correction factor c files c c c open files c open(1,file=file1,status='old') open(2,status='scratch',access='direct',recl=16, + form='unformatted') open(3,file=trim(file3),status='replace') open(4,status='scratch',access='direct',recl=8, + form='unformatted') open(7,status='scratch',access='direct',recl=4, + form='unformatted') c c c 2 format(a) c count = 0 do i = 1,50000 read(1,*,end=784)year,mon,avg,precip count = count + 1 if(avg.lt.0) then avg = 0.0 endif write(2,rec=count)year,mon,avg,precip enddo 784 continue close(1) print *, 'number of records = ', count c c look up the heat index c total = 0.0 count2 = 0 do i = 1,count read(2,rec=i)year,mon,temp,precip c print *, 'computing the heat index for record #',i,' of ', + count c call index(temp,heat1,row,col,x,y) call index(temp,heat1,row,col) c c 100 format(1x,4i6,5f10.2) c if(i.gt.1) then read(2,rec=i-1)year_1,mon_1,temp_1,precip_1 if(mon.gt.mon_1.and.year.eq.year_1) then total = total + heat1 if(i.eq.count) then count2 = count2 + 1 year_heat = total year2 = year_1 write(4,rec=count2)year2,year_heat total = 0.0 + heat1 endif else count2 = count2 + 1 year_heat = total year2 = year_1 write(4,rec=count2)year2,year_heat total = 0.0 + heat1 endif elseif(i.eq.1) then total = 0.0 + heat1 endif enddo c c c find unadjusted evapotranspiration by using the yearly summed heat index c and the monthly air temperature to apply to table 4 c c c do i = 1,count c read(2,rec=i)year,mon,temp,precip c c print *, 'count2 = ',count2 do j = 1,count2 read(4,rec=j)year2,year_heat if(year2.eq.year) then heat = year_heat c if(temp.ge.0.and.temp.lt.26.5) then call table4(temp,heat,pet) c elseif(temp.ge.26.5) then call table5(temp,pet) endif c c adjust evapotranspiration for latitude and month of the year by multiplying c by the adjustment factor given in table 6 c c adjust evapotranspiration for latitude and month of the year by multiplying c by the adjustment factor given in table 6 c print *, 'performing evap lat correction for rec # ',i, + ' of',count lat = latitude col = mon if(ns.eq.1) then call table6(lat,col,correction) else call table7(lat,col,correction) endif c evapo = pet * correction c endif enddo write(7,rec=i)evapo enddo c c compute actual evapotranspiration c call moisture(count,moist) c write(3,16) do i = 1,count read(2,rec=i)year,mon,temp,precip read(7,rec=i)evapo read(14,rec=i)ae,stt read(13,rec=i)p_pe write(3,15)year,mon,precip,temp,evapo,ae enddo 15 format(2x,i4,3x,i4,2x,4f8.2) 16 format(2x,'Year',3x,'Month',4x,'Precip',3x,'Temp', + 3x,' PET',2x,'Actual ET',/) c close(2) close(3) close(4) close(7) close(13) close(14) stop end c c c c c c this subroutine reads table2 and returns a heat index c c subroutine index(temp,heat1,row,col,x,y) subroutine index(temp,heat1,row,col) implicit none real heat(40,10),x,heat1,temp integer row,col,i,j,dummy,y c open(1,file='table2.dat',status='old',recl=135) do i = 1,40 read(1,*)dummy,(heat(i,j),j=1,10) enddo c c c y = int(temp) x = (temp - float(y)) * 10. row = y + 1 col = int(x) + 1 heat1 = heat(row,col) c c close(1) return end c c subroutine table4(temp,heat,pet) implicit none real evp(107,47),temp,heat,pet,index(1,47),temperature(107), +temp1,temp2,heat1,heat2 integer i,j c c c c select table c open(1,file='table4.dat',status='old') c read(1,10)(index(1,j),j=1,47) c do i = 1,107 read(1,11)temperature(i),(evp(i,j),j=1,47) enddo c c select the right pet for give heat index and temperature c do i = 1,107 do j = 1,47 c if(i.eq.1.and.j.eq.1) then if(temp.ge.temperature(i).and.temp.lt.temperature(i+1). + and.heat.ge.index(1,j).and.heat.lt.index(1,j+1)) then c compute the nearest value temp1 = temp - temperature(i) temp2 = temperature(i+1) - temp heat1 = heat - index(1,j) heat2 = index(1,j+1) - heat if(temp1.le.temp2.and.heat1.le.heat2) then pet = evp(i,j) elseif(temp1.le.temp2.and.heat1.gt.heat2) then pet = evp(i,j+1) elseif(temp1.gt.temp2.and.heat1.gt.heat2) then pet = evp(i+1,j+1) elseif(temp1.gt.temp2.and.heat1.le.heat2) then pet = evp(i+1,j) endif endif c elseif(j.eq.1.and.i.gt.1) then if(temp.lt.temperature(i).and.temp.ge.temperature(i-1). + and.heat.ge.index(1,j).and.heat.lt.index(1,j+1)) then c compute the nearest value temp1 = temp - temperature(i-1) temp2 = temperature(i) - temp heat1 = heat -index(1,j) heat2 = index(1,j+1) - heat if(temp1.le.temp2.and.heat1.le.heat2) then pet = evp(i-1,j) elseif(temp1.le.temp2.and.heat1.gt.heat2) then pet = evp(i-1,j+1) elseif(temp1.gt.temp2.and.heat1.gt.heat2) then pet = evp(i,j+1) elseif(temp1.gt.temp2.and.heat1.le.heat2) then pet = evp(i,j) endif else endif c elseif(j.gt.1.and.i.eq.1) then if(temp.ge.temperature(i).and.temp.lt.temperature(i+1). + and.heat.lt.index(1,j).and.heat.ge.index(1,j-1)) then c compute the nearest value temp1 = temp - temperature(i) temp2 = temperature(i+1) - temp heat1 = heat - index(1,j-1) heat2 = index(1,j) - heat if(temp1.le.temp2.and.heat1.le.heat2) then pet = evp(i,j-1) elseif(temp1.le.temp2.and.heat1.gt.heat2) then pet = evp(i,j) elseif(temp1.gt.temp2.and.heat1.gt.heat2) then pet = evp(i+1,j) elseif(temp1.gt.temp2.and.heat1.le.heat2) then pet = evp(i+1,j-1) endif endif c elseif(i.gt.1.and.j.gt.1) then if(temp.lt.temperature(i).and.temp.ge.temperature(i-1). + and.heat.lt.index(1,j).and.heat.ge.index(1,j-1)) then c c compute the nearest value temp1 = temperature(i) - temp temp2 = temp - temperature(i-1) heat1 = index(1,j) - heat heat2 = heat - index(1,j-1) c if(temp1.le.temp2.and.heat1.le.heat2) then pet = evp(i,j) elseif(temp1.le.temp2.and.heat1.gt.heat2) then pet = evp(i,j-1) elseif(temp1.gt.temp2.and.heat1.gt.heat2) then pet = evp(i-1,j-1) elseif(temp1.gt.temp2.and.heat1.le.heat2) then pet = evp(i-1,j) endif else endif c endif enddo enddo 10 format(9x,47f8.2) 11 format(1x,f6.2,2x,47f8.2) close(1) return end c c c subroutine table5(temp,pet) implicit none real temp,evp(13,10),x,pet integer row,col,i,j,dummy,y,temp2(13) c data temp2/26,27,28,29,30,31,32,33,34,35,46,37,38/ c open(1,file='table5.dat',status='old',recl=128) read(1,2) do i = 1,12 read(1,*)dummy,(evp(i,j),j=1,10) enddo c c 2 format(a) c y = int(temp) do i = 1,12 if(y.eq.temp2(i)) then row = i else endif enddo c x = (temp - float(y)) * 10. col = nint(x + 1) pet = evp(row,col) c c close(1) return end c c subroutine table6(lat,col,correction) implicit none real corr(51,12),correction,lat integer row,col,dummy,i,j c c open(1,file='table6.dat',status='old',recl=125) c do i = 1,51 read(1,*)dummy,(corr(i,j),j=1,12) enddo c row = nint(lat) + 1 correction = corr(row,col) close(1) return end c subroutine table7(lat,col,correction) implicit none real corr(51,12),correction,lat integer row,col,dummy,i,j c c open(1,file='table7.dat',status='old',recl=125) c do i = 1,51 read(1,*)dummy,(corr(i,j),j=1,12) enddo c row = nint(lat) + 1 correction = corr(row,col) close(1) return end c c c subroutine moisture(c2,moist) c c this program reads moisture of thornwaite's soil moisture retention c and provides values for actual evapotranspiration c implicit none real pet,precip,p_pe,act_pot_wl(3000), + delta_st(3000),ae,sum,sum2,sum_pos, + pe1(1500),w_ret(200,10),w_ret2,remainder,sum_neg,pe1_2, + w_ret3(200),water_loss,st2,sum7, + ae1,st(3000),stt,dummy integer i,j,k,col,row,start,finish,begin,check,c2,begin2, + c3,c4,b_c(200),year,mon,e_c(200),c5,year_1,mon_1, + c6,years,c8,c7,moist,c10,count,c9,c99 c open(13,status='scratch',access='direct',recl=4, + form='unformatted') open(14,status='scratch',access='direct',recl=8, + form='unformatted') c c compute p_pe c do i = 1,c2 read(2,rec=i)year,mon,dummy,precip read(7,rec=i)pet p_pe = precip - pet write(13,rec=i)p_pe enddo c c if(moist.eq.1) then open(1,file='table23.dat',status='old') c10 = 10 elseif(moist.eq.2) then open(1,file='table24.dat',status='old') c10 = 23 elseif(moist.eq.3) then open(1,file='table25.dat',status='old') c10 = 37 elseif(moist.eq.4) then open(1,file='table26.dat',status='old') c10 = 51 elseif(moist.eq.5) then open(1,file='table27.dat',status='old') c10 = 35 elseif(moist.eq.6) then open(1,file='table28.dat',status='old') c10 = 75 elseif(moist.eq.7) then open(1,file='table29.dat',status='old',recl=140) c10 = 106 elseif(moist.eq.8) then open(1,file='table30.dat',status='old') c10 = 126 elseif(moist.eq.9) then open(1,file='table31.dat',status='old') c10 = 120 elseif(moist.eq.10) then open(1,file='table32.dat',status='old') c10 = 115 elseif(moist.eq.11) then open(1,file='table33.dat',status='old') c10 = 156 endif c c do i = 1,c10 read(1,*,end=22)pe1(i),(w_ret(i,j),j=1,10) enddo 22 continue c c break data into yearly sets c c3 = 0 c4 = 0 c5 = 0 c6 = 0 c7 = 0 c8 = 0 c c print *, 'c2 = ',c2 do i = 1,c2 read(2,rec=i)year,mon,dummy,dummy if(i.eq.1) then read(2,rec=i+1)year_1,mon_1,dummy,dummy if(year.lt.year_1) then c3 = c3 + 1 c4 = c4 + 1 c5 = c5 + 1 b_c(c3) = 1 e_c(c3) = 1 elseif(year.eq.year_1) then c4 = c4 + 1 c5 = c5 + 1 endif elseif(i.gt.1) then read(2,rec=i-1)year_1,mon_1,dummy,dummy c print *, 'year,year1,mon,mon1 ',year,year_1,mon,mon_1 if(i.eq.c2) then c3 = c3 + 1 b_c(c3) = c5 - c4 + 1 e_c(c3) = c2 elseif(year.eq.year_1.and.mon.gt.mon_1) then c4 = c4 + 1 c5 = c5 + 1 else c3 = c3 + 1 b_c(c3) = c5 - c4 + 1 e_c(c3) = c5 c4 = 1 c5 = c5 + 1 endif endif enddo c c c do years = 1,c3 c c6 = e_c(years) c7 = b_c(years) print *, 'computing evapotranspiration for year#',years,' of', + c3 c c c print *, 'c7 , c6 ',c7,c6 sum = 0.0 do i = c7,c6 read(13,rec=i)p_pe sum = sum + p_pe enddo c c c compute the accumulative water loss potential if the total p-pe is positive c if(sum.ge.0.00) then c9 = 0 c99 = 0 sum2 = 0.0 do i = c7,c6 read(13,rec=i)p_pe if(p_pe.gt.0.0) then c9 = c9 + 1 else goto 9999 endif enddo 9999 continue c do i = c7,c6 read(13,rec=i)p_pe c99 = c99 + 1 if(p_pe.ge.0.0.and.c99.le.c9) then act_pot_wl(i) = 0.0 elseif(p_pe.lt.0.0) then sum2 = sum2 + p_pe act_pot_wl(i) = sum2 elseif(p_pe.ge.0.0.and.c99.gt.c9) then act_pot_wl(i) = p_pe endif enddo c C FIND THE STORAGE VALUES FOR THE POS SUMS c do i = c7,c6 sum7 = abs(act_pot_wl(i)) row = int(sum7/10.) remainder = sum7 - (float(row) * 10.) col = int(remainder) col = col + 1 row = row + 1 C st(i) = w_ret(row,col) enddo c c c find change in storage c do i = c7,c6 if(i.eq.1) then delta_st(i) = 0.0 else delta_st(i) = st(i) - st(i-1) endif enddo endif c c c find the water loss if p-pe is negatice c c if(sum.lt.0.00) then c sum_neg = 0.0 sum_pos = 0.0 do i = c7,c6 read(13,rec=i)p_pe if(p_pe.lt.0.00) then sum_neg = sum_neg + p_pe else sum_pos = sum_pos + p_pe endif enddo c c find the value of soil moisture retention equal to the total negative c value of p - pe from table c sum_neg = abs(sum_neg) c c find the proper column and row in the mositure table c row = int(sum_neg/10.) remainder = sum_neg - (float(row) * 10.) col = int(remainder) col = col + 1 row = row + 1 c w_ret2 = w_ret(row,col) w_ret3(1) = w_ret2 c c add the positive sum to this value to obtain a value at the end of c the moist period c do k = 2,100 w_ret2 = w_ret2 + sum_pos c print *, 'sum pos = ',sum_pos c c find the value potential evaporation value on the table's border c pe1_2 = 0.0 do i = 1,c10 do j = 1,10 if(j.eq.1) then if(w_ret2.eq.w_ret(i,j)) then pe1_2 = pe1(i) goto 16 else endif else if(w_ret2.eq.w_ret(i,j)) then pe1_2 = pe1(i) + float(j-1) goto 16 else endif endif enddo enddo 16 continue c c now add the total negative p-pe to this value c c print *, 'pet1_2 ',pe1_2 pe1_2 = pe1_2 + sum_neg c print *, 'pet1_2 ',pe1_2 c c now find the value of the soil moisture retention at the end of the c dry period in the body of the table c row = int(pe1_2/10.) remainder = pe1_2 - (float(row) * 10.) col = int(remainder) col = col + 1 row = row + 1 c print *, 'row col = ',row,col c w_ret2 = w_ret(row,col) w_ret3(k) = w_ret2 c c check to see if the moisture retention is the same if(w_ret3(k).eq.w_ret3(k-1)) then row =int( (w_ret2 + sum_pos)/10.) remainder = (w_ret2 + sum_pos) - (float(row)*10.) col = int(remainder) row = row + 1 col = col + 1 c print *, 'row,col, w_ret2 ',row,col,w_ret2 water_loss = -w_ret(row,col) go to 188 else endif enddo 188 continue c c c find the actual potential water loss sum2 = water_loss count = 0 do i = c7,c6 read(13,rec=i)p_pe if(p_pe.ge.0.0) then act_pot_wl(i) = 0.0 else count = count + 1 if(count.eq.1) then act_pot_wl(i-1) = sum2 sum2 = sum2 + p_pe act_pot_wl(i) = sum2 else sum2 = sum2 + p_pe act_pot_wl(i) = sum2 endif endif enddo c c Find storage by finding the act_pot_wl in the body of the table and c obtaining it from the border then obtaining the positive ones by c subtracting or adding to the water loss potential c start = 0 begin = 0 check = 0 finish = 0 do i = c7,c6 read(13,rec=i)p_pe if(p_pe.gt.0.0) then else check = check + 1 if(check.eq.1) then start = i else endif endif enddo finish = start + check begin = start - 1 c c c look up storage values c sum7 = 0.0 do i = c7,c6 if(act_pot_wl(i).lt.0.0) then c sum7 = abs(act_pot_wl(i)) row = int(sum7/10.) remainder = sum7 - (float(row) * 10.) col = int(remainder) col = col + 1 row = row + 1 st(i) = w_ret(row,col) c else st(I) = 0.0 endif enddo c st2 = st(begin) begin2 = begin - 1 do i = begin2,c7,-1 read(13,rec=i+1)p_pe st2 = st2 - p_pe st(i) = st2 enddo c st2 = st(finish-1) do i = finish,c6 read(13,rec=i)p_pe st2 = st2 + p_pe st(i) = st2 enddo C C c c compute change in storage which is zero if the storage is above 0 c and is the difference from one month to the next. c do i = c7,c6 read(13,rec=i)p_pe if(p_pe.lt.0.0.and.i.gt.begin) then delta_st(i)= st(i) - st(i-1) else delta_st(i) = p_pe endif enddo c ENDIF c c c c compute the actual evapotranspiration when precipitation is greater c than the potential evapotranspiration, the soil remains full of water c and the actual evapotranspiration will equal the potential. When the c precipitation drops below the potential evapotranspiration the soil begins c to dry out and actual evapotranspiration becomes less that the potentially c possible. In those months the actual evapotranspiration equals the c precipitation plus the amount of water drawn from the soil moisture c storage (delta_st) c do i = c7,c6 read(2,rec=i)year,mon,dummy,precip read(13,rec=i)p_pe read(7,rec=i)pet if(p_pe.ge.0.0) then ae1 = pet else ae1 = precip - delta_st(i) endif c8 = c8 + 1 ae = ae1 stt = delta_st(i) write(14,rec=c8)ae,stt c print *, 'c8 ',c8 enddo c ENDDO c c return end