provide equivalent of fprintf(stderr, "%s\n", msg) in Fortran

Issue #1378 closed
Roland Haas created an issue

Currently to write out multi-line error messages in Fortran we use multiple calls to CCTK_WARN(1, warnline) followed possibly by a CCTK_ERROR(errline). Each of the level 1 warnings (given certain settings of the Cactus parameters) prints the source file location and other information to screen, thus cluttering the error output. A typical error message might look like this:

WARNING level 1 in thorn GRHydro processor 179 host nid03278
  (line 386 of GRHydro_Prim2Con.F90):
  -> EOS error in prim2con_hot:
WARNING level 1 in thorn GRHydro processor 179 host nid03278
  (line 388 of GRHydro_Prim2Con.F90):
  ->    64897   22   37   31  -1.440000E+00  -8.496000E+01  -1.296000E+01
8.595485E+01
WARNING level 1 in thorn GRHydro processor 179 host nid03278
  (line 390 of GRHydro_Prim2Con.F90):
  ->    1.228064E-09  -8.644951E-03  -5.842300E-01   4.789413E-01
WARNING level 1 in thorn GRHydro processor 179 host nid03278
  (line 392 of GRHydro_Prim2Con.F90):
  ->  code:      106
WARNING level 1 in thorn GRHydro processor 179 host nid03278
  (line 394 of GRHydro_Prim2Con.F90):
  -> reflevel:     0
WARNING level 1 in thorn GRHydro processor 179 host nid03278
  (line 386 of GRHydro_Prim2Con.F90):
  -> EOS error in prim2con_hot:
WARNING level 1 in thorn GRHydro processor 179 host nid03278
  (line 388 of GRHydro_Prim2Con.F90):
  ->    64897   23   37   31   1.440000E+00  -8.496000E+01  -1.296000E+01
8.595485E+01
WARNING level 1 in thorn GRHydro processor 179 host nid03278
  (line 390 of GRHydro_Prim2Con.F90):
  ->    1.227982E-09  -8.644755E-03  -5.798389E-01   4.789407E-01
WARNING level 1 in thorn GRHydro processor 179 host nid03278
  (line 392 of GRHydro_Prim2Con.F90):
  ->  code:      106
WARNING level 1 in thorn GRHydro processor 179 host nid03278
  (line 394 of GRHydro_Prim2Con.F90):
  -> reflevel:     0
WARNING level 1 in thorn GRHydro processor 179 host nid03278
  (line 166 of GRHydro_Eigenproblem.F90):
  -> EOS ERROR in eigenvalues_hot
WARNING level 1 in thorn GRHydro processor 179 host nid03278
  (line 168 of GRHydro_Eigenproblem.F90):
  ->   keyerr:   668 keytemp:     0
WARNING level 0 in thorn GRHydro processor 179 host nid03278
  (line 170 of GRHydro_Eigenproblem.F90):
  ->    1.228064E-09  -8.644951E-03  -5.842300E-01   4.789413E-01
5.668696E-04
cactus_sim:
Cactus/arrangements/Carpet/Carpet/src/helpers.cc:314:
int Carpet::Abort(const cGH*, int): Assertion `0' failed.
Rank 179 with PID 13388 received signal 6

with errors from multiple MPI processes possibly intersecting each other.

It would be useful to provide a subroutine equivalent to

subroutine CCTK_WARN_SHORT(msg)
  character*(*) :: msg
  write (stderr,'(a)') msg
end subroutine

(name is up for discussion) that outputs only "msg" to stderr (and the warning listener registered in the flesh) without prepending the file information output.

A similar routine might be offered for C (in WARN and VWarn flavors) both for symmetry reasons and to have the message pass the warning listeners, though in C one can usually get away with a single CCTK_VWarn and a very long format string.

Keyword:

Comments (9)

  1. Frank Löffler
    • removed comment

    If what you want to achieve is multiple lines, isn't is easier to encode that in the warnline in the first place (using '\n') and only call CCTK_WARN once?

  2. Roland Haas reporter
    • removed comment

    I do not know how to use "\n" in Fotran. Is this possible? Also in Fotran I would have to allocate a buffer to hold all text at once. So possibly several hundred characters which is not ideal. In C: yes, the most convenient method is to have long format string and \n in it. Currently the Fortan code typically looks like this:

    character*256 :: warnline
    if (dens(i,j,k).ne.dens(i,j,k)) then
       !$OMP CRITICAL
       call CCTK_WARN(1,"dens NAN at entry of Con2Prim")
       write(warnline,"(A10,i5)") "reflevel: ",GRHydro_reflevel
       call CCTK_WARN(1,warnline)
       write(warnline,"(3i5,1P10E15.6)") i,j,k,x(i,j,k),y(i,j,k),z(i,j,k)
       call CCTK_WARN(1,warnline)
       write(warnline,"(1P10E15.6)") rho(i,j,k),dens(i,j,k),eps(i,j,k)
       call CCTK_WARN(1,warnline)
       write(warnline,'(a32,2i3)') 'hydro_excision_mask, atmosphere_mask: ', hydro_excision_mask(i,j,k), atmosphere_mask(i,j,k)
       call CCTK_WARN(1,warnline)
       call CCTK_WARN(0,"Aborting!!!")
       !$OMP END CRITICAL
    endif
    

    constructs like this are very common in GRHydro.

  3. Frank Löffler
    • removed comment

    I think it should work (read: I didn't test now) to do something like:

    character*256 :: warnline
    write(warnline,"(i5,A1,i5)") GRHydro_reflevel, "\n", GRHydro_reflevel
    call CCTK_WARN(1,warnline)
    

    Yes, that would require warnline to be long enough, but that is already the case without "\n", and a general problem in Fortan.

  4. Roland Haas reporter
    • removed comment

    This almost worked. Adding "\n" produces

    WARNING[L1,P0] (GRHydro):     0\    0
    

    If I then replace the "\n" by the number 10 (ASCII code for the line-feed), I get:

    WARNING[L1,P0] (GRHydro):     0
        0
    

    Not sure what I would get under OSX and Windows where the end-of-line marker is "\r" and "\r\n" respectively. Ideally I would have liked:

    WARNING[L1,P0] (GRHydro):     0
    WARNING[L1,P0] (GRHydro):     0
    

    ie some short leader for each line.

  5. Frank Löffler
    • removed comment

    I think OSX uses \n as well. Only the older MacOS used \r.

    Concerning the prefix: For a multi-line warning I would actually rather avoid the duplicate prefix, and just use a "\n" (in whatever form this works) as first character to get an output of the form

    WARNING[L1,P0] (GRHydro):
    0
    0
    

    GRHydro might be fine with the other option, but especially for thorns with longer names it would reduce the available space per line quite a bit.

  6. Erik Schnetter
    • removed comment

    I usually use write to produce several lines of output, often using do loops etc. to produce the output. A single call to an error message routine would not work. I then conclude by a call to CCTK_ERROR.

    It is customary to use unit 6 for stdout (equivalent to using *) and unit 0 for stderr. Thus:

    write(0,) "Something went wrong!" write(0,) "These are my variables:",a,b,c write(0,) "begin gxx" write(0,) "... and here is a whole grid function just for kicks":, gxx write(0,*) "end gxx" call CCTK_ERROR("aborting")

  7. Erik Schnetter
    • removed comment

    I believe that writing to unit 0 in Fortran is equivalent to the suggested function. Can we close this ticket as "wontfix"?

  8. Roland Haas reporter
    • changed status to resolved
    • removed comment

    Ah, I did not now about unit 0 for stderr. Cactus redirects file descriptor 0 (Unix parlance, stdout) to /dev/null on the non-root processes, so writing to unit 6 (or *) did not work.

  9. Log in to comment