Handling underflow errors in fortran 90

In summary: Be consistent in your use of spaces. Your assignment statements are typically good, but you have a lot of places with no spaces at all. For example, you have:expr1 = b(i,j,k)*psi(i,j+1,k)+b(i,j-1,k)&and:expr3 = expr1/expr2I would write them with spaces:expr1 = b(i, j, k) * psi(i, j + 1, k) + b(i, j - 1, k) &and:expr3 = expr1 / expr2
  • #1
meteo student
72
0
I am using fortran 90 to solve a elliptic partial differential equation numerically(Poisson's equation) and I have encountered a underflow error. All the arrays involved are stored as real data types. The original expression is highlighted in the comments and the my attempt at refactoring into simpler expressions is shown as expr0, expr1, expr2,expr3. I am not sure about my attempt to handle the underflow error because while the FPE problem goes away the solution does not converge and I get all zero values.

Any suggestions to improve my coding attempts ?
Fortran:
    use,intrinsic :: ieee_arithmetic
     use, intrinsic :: iso_fortran_env, only: compiler_version, compiler_options
     implicit none
     logical :: underflow_support, underflow
  
    do k=1,nz-1
         do i=1,nx-1
           do j=1,ny-1
           expr0 = omega*(-dxyz*rhoref(2*k)*pv(i,j,k)+a(i,j,k)*&
                (psi(i+1,j,k)+psi(i-1,j,k)))
           expr1 = b(i,j,k)*psi(i,j+1,k)+b(i,j-1,k)&
                *psi(i,j-1,k)+c(i,j,k)*&
                psi(i,j,k+1)+c(i,j,k-1)&
                *psi(i,j,k-1)
           expr1 = expr0 + expr1
           expr2 = (2.*a(i,j,k)+b(i,j,k)+b(i,j-1,k)+c(i,j,k-1)+c(i,j,k))

           call ieee_get_flag(ieee_underflow,underflow)
           if (underflow) then
           end if
           if (expr1 == 0.0) then
              expr3 = expr1/expr2
              expr3 = expr3 + (1.-omega)*psi(i,j,k)
              psi(i,j,k) = expr3
           end if
         
!
           !             psi(i,j,k)=omega*(-dxyz*rhoref(2*k)*pv(i,j,k)+a(i,j,k)*
           !   >              (psi(i+1,j,k)+psi(i-1,j,k))
           !   >              +b(i,j,k)*psi(i,j+1,k)+b(i,j-1,k)
           !   >              *psi(i,j-1,k)+c(i,j,k)*
           !   >              psi(i,j,k+1)+c(i,j,k-1)
           !   >              *psi(i,j,k-1))/
           !   >              (2.*a(i,j,k)+b(i,j,k)+b(i,j-1,k)
           !   >              +c(i,j,k-1)+
           !   >              c(i,j,k))
           !                 +(1.-omega)*psi(i,j,k)
         
        enddo
     enddo
  enddo
 
Last edited:
Technology news on Phys.org
  • #2
Please use code tags, as they preserve your indentation, which helps make your code more readable. I have added them to your code. For more info, see https://www.physicsforums.com/threads/read-this-before-posting-code-geshi-syntax-highlighter.773407/ at the top of this forum section.
meteo student said:
I am using fortran 90 to solve a elliptic partial differential equation numerically(Poisson's equation) and I have encountered a underflow error. All the arrays involved are stored as real data types. The original expression is highlighted in the comments and the my attempt at refactoring into simpler expressions is shown as expr0, expr1, expr2,expr3. I am not sure about my attempt to handle the underflow error because while the FPE problem goes away the solution does not converge and I get all zero values.

Any suggestions to improve my coding attempts ?
I don't see how this could possibly work.
1. There is no PROGRAM section. Possibly you just copied a short section of your code.
2. Your three DO loop run from 1 to, respectively, nz-1, nx-1, and ny-1. None of the nx, ny, nz variables has been initialized, at least in the section of code that you posted.
3. I don't see any declarations for any variables, including omega and dxyz, or for any of the arrays.
When I see obvious errors like these, I stop looking.

Since you asked how you might improve your coding attempts, here are some suggestions.
  • Add spaces in your code. The compiler doesn't care, but jamming everything together makes it harder for humans to read and understand what you're trying to do. Here is one of your assignment statements, written on one line:
    Fortran:
    expr0 = omega*(-dxyz*rhoref(2*k)*pv(i,j,k)+a(i,j,k)*(psi(i+1,j,k)+psi(i-1,j,k)))
    Granted, you wrote it on two lines, using &, but it's almost unreadable with everything jammed together.
  • Use more informative names -- rhoref means what? And what is dxyz?
    Single-letter names are OK for loop control variables (i, j, and k in your code), but you really should have better names than nx, ny, nz.
  • Where's the rest of the code? The only declarations I see are for underflow_support and underflow, neither of which has been initialized.
  • If your code isn't working correctly, use a debugger, and insert a breakpoint to inspect the values of the variables being manipulated. If you don't know how to use a debugger, invest some time in doing this. Any time you spend will be amply rewarded. In the meantime, use the tried and true method of inserting write statements to print the values of variables. When your code is working as expected, you can delete or comment out the extra write statements.

meteo student said:
Following is my code
Fortran:
    use,intrinsic :: ieee_arithmetic
     use, intrinsic :: iso_fortran_env, only: compiler_version, compiler_options
     implicit none
     logical :: underflow_support, underflow
  
    do k=1,nz-1
         do i=1,nx-1
           do j=1,ny-1
           expr0 = omega*(-dxyz*rhoref(2*k)*pv(i,j,k)+a(i,j,k)*&
                (psi(i+1,j,k)+psi(i-1,j,k)))
           expr1 = b(i,j,k)*psi(i,j+1,k)+b(i,j-1,k)&
                *psi(i,j-1,k)+c(i,j,k)*&
                psi(i,j,k+1)+c(i,j,k-1)&
                *psi(i,j,k-1)
           expr1 = expr0 + expr1
           expr2 = (2.*a(i,j,k)+b(i,j,k)+b(i,j-1,k)+c(i,j,k-1)+c(i,j,k))

           call ieee_get_flag(ieee_underflow,underflow)
           if (underflow) then
           end if
           if (expr1 == 0.0) then
              expr3 = expr1/expr2
              expr3 = expr3 + (1.-omega)*psi(i,j,k)
              psi(i,j,k) = expr3
           end if
         
!
           !             psi(i,j,k)=omega*(-dxyz*rhoref(2*k)*pv(i,j,k)+a(i,j,k)*
           !   >              (psi(i+1,j,k)+psi(i-1,j,k))
           !   >              +b(i,j,k)*psi(i,j+1,k)+b(i,j-1,k)
           !   >              *psi(i,j-1,k)+c(i,j,k)*
           !   >              psi(i,j,k+1)+c(i,j,k-1)
           !   >              *psi(i,j,k-1))/
           !   >              (2.*a(i,j,k)+b(i,j,k)+b(i,j-1,k)
           !   >              +c(i,j,k-1)+
           !   >              c(i,j,k))
           !                 +(1.-omega)*psi(i,j,k)
         
        enddo
     enddo
  enddo
 
  • #3
Thank you Mark for the response. I apologize for not adding the code tag. I added the tag now.
Thanks also for the suggestions on the readability.
Yes I already used a debugger (gdb) and could not make much progress with it.I am using gfortran and I added the breakpoint on the offending line. As the values for the arrays are very large gdb outputs these statements -
<error reading variable: value requires 250000 bytes, which is more than max-value-size>.
So I set max-value unlimited. After that I tried to run gdb it hangs without doing anything.
Then I removed following lines during compilation fpe=overflow,underflow,zero,denormal and then ran it and got an IEEE underflow error. I tried printing the values and there were some very small values - 1.E-45 etc.

I could post the full code but I wanted to avoid it as I had a specific question i.e. how to handle a underflow. Is there a way to flush the really low values to zero and then move on ?
 
Last edited:
  • #4
Fortran:
if (expr1 == 0.0) then
              expr3 = expr1/expr2
Here you are trying to divide Zero by something. Even with pencil and paper this does not work well.
 
  • #5
Tom.G said:
Fortran:
if (expr1 == 0.0) then
              expr3 = expr1/expr2
Here you are trying to divide Zero by something. Even with pencil and paper this does not work well.
Tom - I agree. If you can read my response to Mark I have summarized my efforts so far. My question was how to handle an underflow error and move on.

So if expr1 is a really low value such as -1.0E-45 is it reasonable to flush it to zero and move on ? That is the question I am asking here.
 
  • #6
As a minor nit, I'd reformat this piece of code to make it even more readable:

Fortran:
           expr0 = omega * ( (-dxyz) * rhoref(2*k) * pv(i, j, k) + a(i, j, k) * ( psi(i+1, j, k) + psi(i-1, j, k) ) )
       
           expr1 =    b(i, j, k)    * psi(i, j+1, k)    &
                    + b(i ,j-1, k)  * psi(i, j-1, k)    &
                    + c(i, j, k)    * psi(i, j, k+1)    &
                    + c(i, j, k-1)  * psi(i, j, k-1)

or

Fortran:
           expr0 = omega * ( (-dxyz) * rhoref(2*k) * pv(i, j, k)
                   + a(i, j, k) * ( psi(i+1, j, k) + psi(i-1, j, k) ) )
        
           expr1 = b(i, j, k)    * psi(i, j+1, k)    &
                   + b(i ,j-1, k)  * psi(i, j-1, k)    &
                     + c(i, j, k)    * psi(i, j, k+1)    &
                       + c(i, j, k-1)  * psi(i, j, k-1)

If you spend some time now reformatting it then you'll simplify your debugging effort later on especially if you have to revisit it 6 months later to fix something.
 
  • #7
Tom.G said:
Fortran:
if (expr1 == 0.0) then
              expr3 = expr1/expr2
Here you are trying to divide Zero by something. Even with pencil and paper this does not work well.
Sure it does. There's no problem dividing 0.0 by a nonzero value -- you get 0.0 as the answer. The problem comes when you divide by zero.
 
  • #8
meteo student said:
Yes I already used a debugger (gdb) and could not make much progress with it.I am using gfortran and I added the breakpoint on the offending line. As the values for the arrays are very large gdb outputs these statements -
<error reading variable: value requires 250000 bytes, which is more than max-value-size>.
So I set max-value unlimited. After that I tried to run gdb it hangs without doing anything.
250KB isn't all that big. Can you show the line of code that is causing this problem? Be sure to include declarations for all variables, and their values before that line is hit.

gdb shouldn't hang. Once you hit a breakpoint, the program will stop, and you can single-step through succeeding lines of code.
meteo student said:
Then I removed following lines during compilation fpe=overflow,underflow,zero,denormal and then ran it and got an IEEE underflow error. I tried printing the values and there were some very small values - 1.E-45 etc.

meteo student said:
So if expr1 is a really low value such as -1.0E-45 is it reasonable to flush it to zero and move on ? That is the question I am asking here.
Seems reasonable to me.
 

1. What is an underflow error in Fortran 90?

An underflow error occurs in Fortran 90 when a calculation results in a number that is smaller than the smallest representable number in the data type being used. This can happen when performing calculations with very small numbers or when dividing by a very large number.

2. How does Fortran 90 handle underflow errors?

Fortran 90 has built-in mechanisms to handle underflow errors. When an underflow occurs, the result is automatically set to the smallest representable number in the data type being used. This ensures that the program does not crash or produce incorrect results.

3. Can underflow errors be turned off in Fortran 90?

No, underflow errors cannot be turned off in Fortran 90. The language is designed to handle underflow errors automatically, so there is no need for a specific mechanism to disable them.

4. How can I avoid underflow errors in Fortran 90?

One way to avoid underflow errors in Fortran 90 is to use appropriate data types for your calculations. For example, if you know that your calculations will involve very small numbers, you can use a data type with a larger range, such as REAL*8 or DOUBLE PRECISION. Additionally, you can also check for underflow conditions in your code and handle them appropriately.

5. Are there any performance implications of handling underflow errors in Fortran 90?

Yes, handling underflow errors in Fortran 90 can have a slight impact on performance. However, the benefits of ensuring accurate results outweigh this small performance cost. If performance is a concern, it is recommended to use appropriate data types and optimize the code to minimize the occurrence of underflow errors.

Similar threads

  • Programming and Computer Science
Replies
4
Views
616
  • Programming and Computer Science
Replies
4
Views
7K
  • Programming and Computer Science
Replies
22
Views
4K
  • Programming and Computer Science
Replies
4
Views
1K
  • Programming and Computer Science
Replies
6
Views
3K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
5K
  • Programming and Computer Science
Replies
6
Views
4K
  • Programming and Computer Science
Replies
2
Views
1K
  • Programming and Computer Science
Replies
1
Views
2K
  • Programming and Computer Science
Replies
8
Views
5K
Back
Top