title: How do I retain precision for a Fortran MPI program in a portable way?
body: <p>I have a Fortran program where I specify the <code>kind</code> of the numeric data types in an attempt to retain a minimum level of precision, regardless of what compiler is used to build the program.  For example:</p>
  
  <pre><code>integer, parameter :: rsp = selected_real_kind(4)
  ...
  real(kind=rsp) :: real_var
  </code></pre>
  
  <p>The problem is that I have used MPI to parallelize the code and I need to make sure the MPI communications are specifying the same type with the same precision.  I was using the following approach to stay consistent with the approach in my program:</p>
  
  <pre><code>call MPI_Type_create_f90_real(4,MPI_UNDEFINED,rsp_mpi,mpi_err)
  ...
  call MPI_Send(real_var,1,rsp_mpi,dest,tag,MPI_COMM_WORLD,err)
  </code></pre>
  
  <p>However, I have found that this MPI routine is not particularly well-supported for different MPI implementations, so it's actually making my program non-portable.  If I omit the <code>MPI_Type_create</code> routine, then I'm left to rely on the standard <code>MPI_REAL</code> and <code>MPI_DOUBLE_PRECISION</code> data types, but what if that type is not consistent with what <code>selected_real_kind</code> picks as the real type that will ultimately be passed around by MPI?  Am I stuck just using the standard <code>real</code> declaration for a datatype, with no <code>kind</code> attribute and, if I do that, am I guaranteed that <code>MPI_REAL</code> and <code>real</code> are always going to have the same precision, regardless of compiler and machine?</p>
  
  <p>UPDATE:</p>
  
  <p>I created a simple program that demonstrates the issue I see when my internal reals have higher precision than what is afforded by the <code>MPI_DOUBLE_PRECISION</code> type:</p>
  
  <pre><code>program main
  
     use mpi
  
     implicit none
  
     integer, parameter :: rsp = selected_real_kind(16)
     integer :: err
     integer :: rank
  
     real(rsp) :: real_var
  
     call MPI_Init(err)
     call MPI_Comm_rank(MPI_COMM_WORLD,rank,err)
  
     if (rank.eq.0) then
        real_var = 1.123456789012345
        call MPI_Send(real_var,1,MPI_DOUBLE_PRECISION,1,5,MPI_COMM_WORLD,err)
     else
        call MPI_Recv(real_var,1,MPI_DOUBLE_PRECISION,0,5,MPI_COMM_WORLD,&amp;
           MPI_STATUS_IGNORE,err)
     end if
  
     print *, rank, real_var
  
     call MPI_Finalize(err)
  
  end program main
  </code></pre>
  
  <p>If I build and run with 2 cores, I get:</p>
  
  <pre><code>       0   1.12345683574676513672      
         1   4.71241976735884452383E-3998
  </code></pre>
  
  <p>Now change the 16 to a 15 in <code>selected_real_kind</code> and I get:</p>
  
  <pre><code>       0   1.1234568357467651     
         1   1.1234568357467651  
  </code></pre>
  
  <p>Is it always going to be safe to use <code>selected_real_kind(15)</code> with <code>MPI_DOUBLE_PRECISION</code> no matter what machine/compiler is used to do the build?  </p>