-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace stop
with return
and provide and bmi_failure
flags for EnergyModule error
#108
base: main
Are you sure you want to change the base?
Changes from 4 commits
f939e07
be6a639
0f4dc8c
989ba81
4c8a086
5fcfeed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,19 @@ | ||
module AsciiReadModule | ||
|
||
use UtilitiesModule | ||
use ErrorCheckModule | ||
|
||
implicit none | ||
|
||
contains | ||
|
||
subroutine open_forcing_file(filename) | ||
subroutine open_forcing_file(filename, error_flag) | ||
|
||
implicit none | ||
|
||
character*256, intent(in) :: filename | ||
integer, intent(out) :: error_flag | ||
character(len=256) :: error_string | ||
|
||
!--------------------------------------------------------------------- | ||
! local variables | ||
|
@@ -22,23 +25,25 @@ subroutine open_forcing_file(filename) | |
! Check if the specified file exists | ||
inquire(file = trim(filename), exist = lexist) | ||
if (.not. lexist) then | ||
write(*,'(/," ***** Problem *****")') | ||
write(*,'(" ***** File ''", A, "'' does not exist.")') trim(filename) | ||
write(*,'(" ***** Check the forcing file specified as a command-line argument",/)') | ||
stop ": ERROR EXIT" | ||
error_flag = NOM_FAILURE | ||
write(error_string,'(A,A,A)') "AsciiReadModule.f90:open_forcing_file(): File: ",trim(filename), " does not exist. Check the forcing file specified as a command-line argument" | ||
call log_message(error_flag, error_string) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See previous comment regarding writing to a possible public character variable in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, seems like kind of a bummer that we'd have to manually record where in the program the error occurs via the error message. My understanding is that this is because we're going to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this code is being run through the C pre-processor (as use of
Those I'm a touch concerned that these files might not get pre-processed as expected, since that usually seems to go with a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I considered the preprocessor approach that @PhilMiller discusses. Besides the issues with this approach that Phil brings up, I don't think that using preprocessor directives for delineating error sources would be appropriate. Currently, the program has sparse reliance on preprocessor directives and they are used for major functional conditions such as whether the code is run standalone or as a module. These few preprocessor directives could easily be removed so the reliance on them is easy to decouple. One possible intermediate improvement would be to define a string that contains the subroutine name and another string with module scope that contains the module name. Then, the error string would refer to those variables instead of them being hardwired. Given that LINE would unambiguously identify the line where the error is reported, unique error messages alternatively identify error sources although the onus is more on the programmer. |
||
return | ||
endif | ||
|
||
! Open the forcing file | ||
open(10, file = trim(filename), form = 'formatted', action = 'read', iostat = ierr) | ||
if (ierr /= 0) then | ||
write(*,'("Problem opening file ''", A, "''")') trim(filename) | ||
stop ": ERROR EXIT" | ||
error_flag = NOM_FAILURE | ||
write(error_string,'(A,A,A)') "ReadModule.f90:open_forcing_file(): Problem opening file: ",trim(filename) | ||
call log_message(error_flag, error_string) | ||
return | ||
endif | ||
|
||
end subroutine open_forcing_file | ||
|
||
subroutine read_forcing_text(iunit, nowdate, forcing_timestep, & | ||
u, v, sfctmp, spechumd, sfcprs, swrad, lwrad, pcprate, ierr) | ||
u, v, sfctmp, spechumd, sfcprs, swrad, lwrad, pcprate, ierr, error_flag) | ||
|
||
implicit none | ||
|
||
|
@@ -55,6 +60,7 @@ subroutine read_forcing_text(iunit, nowdate, forcing_timestep, & | |
real, intent(out) :: lwrad | ||
real, intent(out) :: pcprate | ||
integer, intent(out) :: ierr | ||
integer, intent(out) :: error_flag | ||
real, intent(out) :: u | ||
real, intent(out) :: v | ||
|
||
|
@@ -66,6 +72,7 @@ subroutine read_forcing_text(iunit, nowdate, forcing_timestep, & | |
integer :: hour | ||
integer :: minute | ||
character(len=12) :: readdate | ||
character(len=256):: error_string | ||
real :: read_windspeed | ||
real :: read_winddir | ||
real :: read_temperature | ||
|
@@ -166,10 +173,11 @@ subroutine read_forcing_text(iunit, nowdate, forcing_timestep, & | |
|
||
return | ||
endif | ||
if (ierr /= 0) then | ||
write(*,'("Error reading from data file.")') | ||
ierr = 2 | ||
return | ||
if (ierr /= 0) then | ||
error_flag = NOM_FAILURE | ||
write(error_string,'(A)') "AsciiReadModule.f90:read_forcing_text(): Error reading from data file." | ||
call log_message(error_flag, error_string) | ||
return | ||
endif | ||
write(readdate,'(I4.4,4I2.2)') year, month, day, hour, minute | ||
|
||
|
@@ -185,7 +193,10 @@ subroutine read_forcing_text(iunit, nowdate, forcing_timestep, & | |
before = fdata ( readdate, read_windspeed, read_winddir, read_temperature, read_humidity, read_pressure, read_swrad, read_lwrad, read_rain ) | ||
cycle READLOOP | ||
else | ||
stop "Logic problem" | ||
error_flag = NOM_FAILURE | ||
write(error_string,'(A)') "AsciiReadModule.f90:read_forcing_text(): Logic problem." | ||
call log_message(error_flag, error_string) | ||
return | ||
endif | ||
enddo READLOOP | ||
|
||
|
@@ -216,8 +227,11 @@ subroutine read_forcing_text(iunit, nowdate, forcing_timestep, & | |
|
||
else if (before%readdate < nowdate .and. nowdate < after%readdate) then | ||
|
||
call geth_idts(nowdate, before%readdate, idts) | ||
call geth_idts(after%readdate, before%readdate, idts2) | ||
call geth_idts(nowdate, before%readdate, idts, error_flag) | ||
call geth_idts(after%readdate, before%readdate, idts2, error_flag) | ||
if (error_flag == NOM_FAILURE) then | ||
return | ||
endif | ||
|
||
if (idts2*60 /= forcing_timestep) then | ||
print*, 'forcing_timestep = ', forcing_timestep | ||
|
@@ -226,7 +240,10 @@ subroutine read_forcing_text(iunit, nowdate, forcing_timestep, & | |
print*, 'idts = ', idts | ||
print*,' after%readdate = ', after%readdate | ||
print*, 'idts2 = ', idts2 | ||
stop "IDTS PROBLEM" | ||
error_flag = NOM_FAILURE | ||
write(error_string,'(A)') "AsciiReadModule.f90:read_forcing_text(): IDTS PROBLEM." | ||
call log_message(error_flag, error_string) | ||
return | ||
endif | ||
|
||
fraction = real(idts2-idts)/real(idts2) | ||
|
@@ -250,8 +267,10 @@ subroutine read_forcing_text(iunit, nowdate, forcing_timestep, & | |
rhf = rhf * 1.E-2 | ||
|
||
else | ||
print*, 'nowdate = "'//nowdate//'"' | ||
stop "Problem in the logic of read_forcing_text." | ||
error_flag = NOM_FAILURE | ||
write(error_string,'(A,A,A)') "AsciiReadModule.f90:read_forcing_text(): date: ", nowdate, ". Problem in the logic of read_forcing_text." | ||
call log_message(error_flag, error_string) | ||
return | ||
endif | ||
|
||
! Below commented out KSJ 2021-06-09 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ module DomainType | |
|
||
use NamelistRead, only: namelist_type | ||
use DateTimeUtilsModule | ||
use ErrorCheckModule | ||
|
||
implicit none | ||
save | ||
|
@@ -31,6 +32,8 @@ module DomainType | |
integer :: croptype ! crop type | ||
integer :: isltyp ! soil type | ||
integer :: IST ! surface type 1-soil; 2-lake | ||
integer :: error_flag ! flag for energy balance error (0 = no error, 1 = longwave < 0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is a possible solution although I'd need to also review how domain%error_flag is used apart from how we are using it for the current set of updates. Another possibility is to bind a new error object to the model% object and dissociate error_flag from domain%. |
||
|
||
real, allocatable, dimension(:) :: zsoil ! depth of layer-bottom from soil surface | ||
real, allocatable, dimension(:) :: dzsnso ! snow/soil layer thickness [m] | ||
real, allocatable, dimension(:) :: zsnso ! depth of snow/soil layer-bottom | ||
|
@@ -93,6 +96,7 @@ subroutine InitDefault(this) | |
this%croptype = huge(1) | ||
this%isltyp = huge(1) | ||
this%IST = huge(1) | ||
this%error_flag = huge(1) | ||
|
||
|
||
end subroutine InitDefault | ||
|
@@ -116,8 +120,12 @@ subroutine InitTransfer(this, namelist) | |
this%croptype = namelist%croptype | ||
this%isltyp = namelist%isltyp | ||
this%IST = namelist%sfctyp | ||
this%error_flag = 0 ! model initializes with no errors | ||
this%start_datetime = date_to_unix(namelist%startdate) ! returns seconds-since-1970-01-01 | ||
this%end_datetime = date_to_unix(namelist%enddate) | ||
if (this%start_datetime < 0 .OR. this%end_datetime < 0) then | ||
this%error_flag = NOM_FAILURE | ||
endif | ||
|
||
end subroutine InitTransfer | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than explicitly passing
error_flag
, could you just makeerror_flag
a public variable inErrorCheckModule
and set it in anywhere that usesErrorCheckModule
?Along those same lines, could you make a public character string in
ErrorCheckModule
and write any error message to that variable when the error is encountered? Then useErrorCheckModule
inbmi_noahowp.f90
to be able to print the error message there (when the error code has already been passed up the stack)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it would be possible to remove error_flag from some of the intermediate call signatures. That would clean up some of the call signatures at the expense of requiring programming care not to co-opt that variable for other uses.
Passing the error string up the stack would require adding an error string to the domain object (as currently constructed). I agree that would be more complete. That is Keith's call. If we do this, then it would make sense to follow through with your first suggestion about removing error_flag from some call signatures. When passing these to two variables up to BMI, we would need to either pass a single error object or pass both the error code and error string. I'd prefer to avoid binding ErrorCheckModule to BMI.