- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
One of our codes currently uses of single precision (4-byte) real variables. It would be really great to use double precision math in some circumstances, but it would make solving large problems significantly more cumbersome due to the enhanced memory burden.
Is there a good way to make this an option at run time? I'm particularly concerned about MPI calls, which specify datatypes like "MPI_REAL" as arguments. I suppose I could set up IF statements around each MPI call, and choose "MPI_REAL" or "MPI_DOUBLE_PRECISION" based on some input parameter, but I'm hoping there's an easier way to do this. Likewise with the variable declarations.
Any ideas?
Thanks,
Greg
Link Copied
2 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You could do this with polymorphism, but I think the overhead might be quite a bit for your purposes and would also require significant code changes.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Greg,
Consider looking at using generic interfaces and your own derived types. The added overhead might not be too bad when the derived type contains arrays as opposed to scalars
TYPE MYTYPE
REAL(4), ALLOCATABLE :: R4(:) !could be replaced with UNION of POINTERs
REAL(8), ALLOCATABLE :: R8(:)
END TYPE MYTYPE
INTERFACE VEC_ADD(A,B)
SUBROUTINE VEC_ADD_REAL4(A,B)
REAL(4) :: A(:), B(:)
END SUBROUTINE VEC_ADD_REAL4
SUBROUTINE VEC_ADD_REAL8(A,B)
REAL(8) :: A(:), B(:)
END SUBROUTINE VEC_ADD_REAL8
SUBROUTINE VEC_ADD_MYTYPE(A,B)
TYPE(MYTYPE) :: A, B
END SUBROUTINE VEC_ADD_MYTYPE
END INTERFACE VEC_ADD
...
SUBROUTINE VEC_ADD_REAL4(A,B)
REAL(4) :: A(:), B(:)
A=A + B
END SUBROUTINE VEC_ADD_REAL4
SUBROUTINE VEC_ADD_REAL8(A,B)
REAL(8) :: A(:), B(:)
A = A + B
END SUBROUTINE VEC_ADD_REAL8
SUBROUTINE VEC_ADD_MYTYPE(A,B)
TYPE(MYTYPE) :: A, B
IF(ALLOCATED(A%R4)) THEN
IF(ALLOCATED(B%R4)) THEN
A%R4 = A%R4 + B%R4
ELSE
! OOPS OR CONVERT
ENDIF
ELSE
IF(ALLOCATED(A%R8)) THEN
IF(ALLOCATED(B%R8)) THEN
A%R8 = A%R8 + B%R8
ELSE
! OOPS OR CONVERT
ENDIF
ELSE
! OOPS OR IGNORE
ENDIF
ENDIF
END SUBROUTINE VEC_ADD_MYTYPE
Then in your code
...
CALL VEC_ADD(A,B)
...
And you are now free to change A, B either in compile timedeclarations in INCLUDE/USE files or at run time when A and B are MYTYPEs and properly allocated.
Jim Dempsey
Consider looking at using generic interfaces and your own derived types. The added overhead might not be too bad when the derived type contains arrays as opposed to scalars
TYPE MYTYPE
REAL(4), ALLOCATABLE :: R4(:) !could be replaced with UNION of POINTERs
REAL(8), ALLOCATABLE :: R8(:)
END TYPE MYTYPE
INTERFACE VEC_ADD(A,B)
SUBROUTINE VEC_ADD_REAL4(A,B)
REAL(4) :: A(:), B(:)
END SUBROUTINE VEC_ADD_REAL4
SUBROUTINE VEC_ADD_REAL8(A,B)
REAL(8) :: A(:), B(:)
END SUBROUTINE VEC_ADD_REAL8
SUBROUTINE VEC_ADD_MYTYPE(A,B)
TYPE(MYTYPE) :: A, B
END SUBROUTINE VEC_ADD_MYTYPE
END INTERFACE VEC_ADD
...
SUBROUTINE VEC_ADD_REAL4(A,B)
REAL(4) :: A(:), B(:)
A=A + B
END SUBROUTINE VEC_ADD_REAL4
SUBROUTINE VEC_ADD_REAL8(A,B)
REAL(8) :: A(:), B(:)
A = A + B
END SUBROUTINE VEC_ADD_REAL8
SUBROUTINE VEC_ADD_MYTYPE(A,B)
TYPE(MYTYPE) :: A, B
IF(ALLOCATED(A%R4)) THEN
IF(ALLOCATED(B%R4)) THEN
A%R4 = A%R4 + B%R4
ELSE
! OOPS OR CONVERT
ENDIF
ELSE
IF(ALLOCATED(A%R8)) THEN
IF(ALLOCATED(B%R8)) THEN
A%R8 = A%R8 + B%R8
ELSE
! OOPS OR CONVERT
ENDIF
ELSE
! OOPS OR IGNORE
ENDIF
ENDIF
END SUBROUTINE VEC_ADD_MYTYPE
Then in your code
...
CALL VEC_ADD(A,B)
...
And you are now free to change A, B either in compile timedeclarations in INCLUDE/USE files or at run time when A and B are MYTYPEs and properly allocated.
Jim Dempsey
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page