- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am a novice in the use of Modules, and I've got a question.
I have a very old code that uses dozens of named common blocks. I am considering replacing each with a Module of the same name. Is that a wise thing to do? I think I will end up with a single .f90 file containing all the named Modules, and replacing all the named COMMON statements and associated variable declarations appearing throughout the code with USE statements with the same names.
Every routine throughout the code has IMPLICIT NONE in it, and I think that will help me along the way.
Link Copied
- « Previous
-
- 1
- 2
- Next »
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It is the former. As best I can tell, changes are to names only, not to data type or anything else (at least, I haven't spotted any). There are some places where EQUIVALENCE is used, but not with variables in common blocks. Most of the time, the common blocks are used without changing the names, but there are still many places where they are changed so they don't conflict with locally declared variables in individual subroutines.
I got most of the way through the conversion without having to change too many variable names, but then I hit whole bunch and decided to stop.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Brian Murphy wrote:
It is the former. ..
@Brian Murphy,
So if I undertand correctly, your situation seems akin to the following where you will notice the COMMON block variables have different names in the two scopes: YSLOPE and YINCPT in the function whereas M and C in the main program. Is this what you have?
FUNCTION Y(X) C Some user function: IMPLICIT NONE C Argument list DOUBLE PRECISION X C Function result DOUBLE PRECISION Y C Global data DOUBLE PRECISION YSLOPE DOUBLE PRECISION YINCPT COMMON / CQUAD / YSLOPE, YINCPT C Calculations Y = YSLOPE*X + YINCPT C END FUNCTION
PROGRAM QUADRT C IMPLICIT NONE C Declarations DOUBLE PRECISION INTGRT EXTERNAL INTGRT DOUBLE PRECISION M DOUBLE PRECISION C COMMON / CQUAD / M, C DOUBLE PRECISION Y EXTERNAL Y DOUBLE PRECISION R, XMIN, XMAX C Instructions XMIN = 0D0 XMAX = 1D0 M = 1D0 C = 1D0 R = INTGRT(Y, XMIN, XMAX) C Reporting PRINT *, 'Result from INTGRT: ' , R PRINT *, ' Expected Result: ' , (M*XMAX**2/2D0+C*XMAX)- & (M*XMIN**2/2D0+C*XMIN) C END PROGRAM QUADRT
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, but with a slight twist. For example, a common block most of the time uses variable names RHO and EMU, but in one particular subroutine there are local variables already using these names, so in this subroutine the common block statement was setup using different names, say RHOC and EMUC. Of course in retrospect this should not have been done, but it was.
In my meager understanding of Modules, I want the Module definition of this Common block to use RHO and EMU because those are the names used in the vast majority of cases, and in the above example that forces me to go through that subroutine and change the pair of local variable names to something that doesn't conflict with the names in the Module.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Brian Murphy wrote:
Yes, but with a slight twist. For example, a common block most of the time uses variable names RHO and EMU, but in one particular subroutine there are local variables already using these names, so in this subroutine the common block statement was setup using different names, say RHOC and EMUC. .. that forces me to go through that subroutine and change the pair of local variable names to something that doesn't conflict with the names in the Module.
@Brian Murphy,
This is exactly what I suspected when I first read your "name mangling" comment and I was hoping it won't trip you up because the Fortran standard provides a 'renaming' facility for module entities in a given scope.
If you keep the example in Message #15 in mind, then you can imagine an initial modernization of such code might be as shown below. Now in the main section of the code where all the key setup takes place i.e., under the "Instructions" section on the main program and the integration procedure in the 'math' library and the equation for the user function, you will notice the code can in essence be kept the same as the original; it's all the other 'furniture' around it that is being 'modernized'
Now notice line #5 in the main program below that has constructs such as "M => Slope" (which in your case will be "RHOC => RHO") that setups M as an alias for Slope in that scope. This can allow you to move forward with your work without requiring you to change a lot of instructions in other sections of your code.
module mykinds_m implicit none ! Select suitable working precision (WP), here's an example: integer, parameter :: WP = selected_real_kind( p=15, r=307 ) end module
module mylib_m use mykinds_m, only : WP implicit none private public :: integrate interface function Ifunc( X ) result( Y ) import :: WP ! Argument list real(WP), intent(in) :: X ! Function result real(WP) :: Y end function Ifunc end interface contains function integrate(F, Xmin, Xmax) result( r ) ! Integrate F using trapezoidal rule ! Argument list procedure(Ifunc) :: F real(WP), intent(in) :: Xmin real(WP), intent(in) :: Xmax ! Function result real(WP) :: r ! Local variables real(WP) :: Ymin real(WP) :: Ymax ! Calculations Ymin = F( Xmin ) Ymax = F( Xmax ) r = (Xmax - Xmin)*(Ymax + Ymin)/2_wp return end function end module mylib_m
module myfuncs_m use mykinds_m, only : WP implicit none private ! Global data real(WP) :: Slope real(WP) :: Intercept ! Public functions public :: myfunc ! Public data - only initially public :: Slope public :: Intercept contains function myfunc( X ) result( Y ) ! Some user function ! Argument list real(WP), intent(in) :: X ! Function result real(WP) :: Y ! Calculations Y = Slope*X + Intercept return end function myfunc end module myfuncs_m
program Quadrature use mykinds_m, only : WP use mylib_m, only : integrate use myfuncs_m, only : M => Slope, C => Intercept, Y => myfunc implicit none ! Declarationa real(WP) :: R real(WP) :: XMIN real(WP) :: XMAX ! Instructions XMIN = 0.0_wp XMAX = 1.0_wp M = 1.0_wp C = 1.0_wp R = integrate(Y, XMIN, XMAX) ! Reporting print *, 'Result from INTGRT: ' , R print *, ' Expected Result: ' , (M*XMAX**2/2.0_wp + C*XMAX) - & & (M*XMIN**2/2.0_wp + C*XMIN) stop end program Quadrature
What all this rearrangement provides you with are the advanatages mentioned earlier, defined floating-point representation, defined interfaces for all your procedures, ability to work with global data in a more controlled manner (private vs public scope), and so forth. And more benefits can be attained with further refinement as necessary.
Hope this helps,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well darn! I didn't know about the renaming feature of USE statements. The following is from page 151 of Metcalf's book Fortran 90/95 Explained.
reason for permitting accessed entities to be renamed by the use statement. Renaming is also available to resolve a name clash between a local entity and an entity accessed from a module, though our preference is to use a text editor or other tool to change the local name. With renaming, the use statement has the form
That would have saved me a lot of trouble. The best thing for me to do at this point might be to start over, and do the conversion without any renaming.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have started over, and so far I have successfully converted all common blocks which contain arrays (20 of over 85 named common blocks!). The code builds and runs, and the case that crashed no longer crashes. Yippee! I'm still using the older version of Intel Fortran.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Good luck in the remainder of your conversions.
Bear in mind that named commons are like unions. The same name can appear in different compilation units with potentially different mappings. This can often bite you when you convert to modules.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Brian Murphy wrote:
I have started over, and so far I have successfully converted all common blocks which contain arrays (20 of over 85 named common blocks!). The code builds and runs, and the case that crashed no longer crashes. Yippee! I'm still using the older version of Intel Fortran.
Mega Kudos to you on your effort and perseverance! Keep up the great work.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The renaming feature of the Use statement has made this much easier, and that's an understatement.
I am converting one named Common at a time, and I start each by carefully checking the list of variable names in every occurrence of the same named Common statement. The Visual Studio editor makes doing that pretty easy. After converting all of one Common, I build and run the code before going on to the next one.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have changed a few programs from Common Blocks to modules, the effort it worth it -- but people used to do terrible things in common blocks and it can be a pain to catch all the errors.
It is not that it is not a good idea as noted elsewehre it is more the time -- there is so much to do and such little time
John
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
After starting over, it was taking me about 15 to 20 minutes to do one Common block. So 20 took me about 5 to 6 hours, and my wife wanted to know why I was up so late. :)
Going forward, this particular code will be much easier to work with. Plus this has been a worthwhile learning experience for me since my fortran knowledge is largely stuck on F77 from the days of paper tapes.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page
- « Previous
-
- 1
- 2
- Next »