- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have modules that reference each other. Is there any way to do this; e.g., pre-compiled modules? My desired code sequence would have the following pattern:
- module M1 source. This uses module M1, references subroutine S2, and contains array A1. All objects are public.
- module M2 source. This uses module M1, contains subroutine S2, and references array A1. All objects are public.
- main program P source. This uses modules M1 and M2 and references subroutine S2 and array A1.
I suspect this will not compile (if I do it in one step) because of the circular references; so, I did not try it. How about the following approach?
- Compile M1 source as a separate step.
- Compile M2 source as a separate step.
- Compile P source with a command that references the pre-compiled forms of M1 and M2.
[[I apologize for earlier not submitting this as a separate thread.]]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can't have circular references, and you can't get around this situation by gaming the compilation order. Suggestion: create a module G.f90 (ie, "globals") which contains data type definitions, defined parameters, array A1, and subroutine S2. Then: Main uses (G, M1, M2), and M1 and M2 both use G.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please replace M1 by M2 in the first bullet, which should read:
- module M1 source. This uses module M2, references subroutine S2, and contains array A1. All objects are public.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can't have circular references, and you can't get around this situation by gaming the compilation order. Suggestion: create a module G.f90 (ie, "globals") which contains data type definitions, defined parameters, array A1, and subroutine S2. Then: Main uses (G, M1, M2), and M1 and M2 both use G.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Paul - Thanks - I feared that might be the case - can't game compilation order. That seems unfortunate because it would require only a second pass to patch unresolved references. I would hope to see this capability in a future version.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I would very much hope not! Going the other way - it would be nice if the compiler yelled at me and gave me a good kick up the backside whenever I tried to create a circular module dependency.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IanH wrote:
I would very much hope not! Going the other way - it would be nice if the compiler yelled at me and gave me a good kick up the backside whenever I tried to create a circular module dependency.
Agreed, you know you have circular references by the symptoms of compile failure rather than just being told how you are being dumb. I guess VS should tell you this when it tried to determine the build order. Perhaps it does if you know the correct things to set????
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I used a general, easy, but unpleasant fix to my problem. I merged M1 and M2. This took care of many circular references but left me with a massive and borderline non-maintainable module. Another objection to this approach is that, for practical purposes, it is not extendable; the bigger the module the less mobile it becomes and the greater likelihood of having to add other modules to the mass. Relaxing the anti-circularity rule would avoid all this grief.
Pulling just the circular pieces into separate modules would overly complicate access to module-level objects.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That's why you and many others, including myself, are keenly awaiting the implementation of submodules from F2008 in Intel's Fortran Composer Studio Parallel Deluxe PQRST with Special Sauce 201X product.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IanH wrote:
That's why you and many others, including myself, are keenly awaiting the implementation of submodules from F2008 in Intel's Fortran Composer Studio Parallel Deluxe PQRST with Special Sauce 201X product.
Who blabbed? But note that you have to order the EC (Extra Cheese) option to get that...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I will have to read what F2008 has to say about submodules. But, the name itself does not immediately suggest a solution to the anti-circularity issue. I hope to be pleasantly surprised.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Obviously it may depend on details you've not stated. But what I imagine you would have is...
- module M source. This has, at least, array A1 and the interface for a separate module procedure for subroutine S2, plus perhaps other things common to former M1 and M2 and anything that needs to be collectively PUBLIC across former modules M1 and M2.
- submodule SM1, a descendent of module M. This contains the remaining bits of former module M1 not already in module M.
- submodule SM2, another descendent of module M. This contains the body of subroutine S2 and any other bits of former module M2 not already in module M.
- main program P source. This uses module M and references subroutine S2 and array A1
(What specifically stops you using Paul's approach in the meantime?)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Richard,
>>Another objection to this approach is that, for practical purposes, it is not extendable; the bigger the module the less mobile it becomes and the greater likelihood of having to add other modules to the mass. Relaxing the anti-circularity rule would avoid all this grief.
You make things extendable by constructing hierarchies, what you are trying to do is to avoid making hierarchies.
I use Paul's approach with a globals module, plus at times I go one step further and place the contains section into a separate module. This necessitates inserting interfaces into the data portion of the module.
Globals.f90
Adata.f90
Acode.f90
Bdata.f90
Bcode.f90
...
With this construct Acode can USE Bdata, and Bcode can USE Adata with no (compiler) circular dependencies.
When Acode USEs Bdata it has the interfaces to Bcode and can call anything interfaced in Bdata to Bcode.
Same thing the other way around.
The globals.f90 would contain the items that are relatively fixed. As changing anything in globals would tend to rebuild all.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve Lionel (Intel) wrote:
Quote:
IanH wrote:That's why you and many others, including myself, are keenly awaiting the implementation of submodules from F2008 in Intel's Fortran Composer Studio Parallel Deluxe PQRST with Special Sauce 201X product.
Who blabbed? But note that you have to order the EC (Extra Cheese) option to get that...
I'd order EC, any other chef's specials, and all the sides, hey the whole works, if I could get my hands on that "sub" !!! :-)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Patience, grasshopper. All things in time.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve Lionel (Intel) wrote:
Patience, grasshopper. All things in time.
That "patience is a virtue" is largely lost in the technology-driven world of ours - so many now keep "chomping at the bit" for the next new thing, say the next "i" device, but for a simple human like me, it's the next Fortran 2003/2008/201X feature in Intel Fortran!! :-)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[to jimd] I appreciate your comments because they seem like a big improvement to what I am doing. I particularly like the way you laid out the suggested pattern. However, I do not understand how Acode.f90 can access data (e.g., types and arrays) in Bdata.f90. Would Acode.f90 have to call getter's and setter's in Bcode.f90 to obtain the access?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Richard, I'm not sure reading your original post that Jim's post exactly fully fixes your problem. What he is saying is that by separating the module data (global) declarations into separate modules (ADATA and BDATA) the Modules ACODE and BCODE can then both have USE ADATA and USE BDATA with no circularity.
I think you also have the problem that you have subroutines that are that are circular in M1 and M2 which cannot be. It may be that you need to move a few subroutines from M2 to M2 or visa versa or if this cannot work fully extract some problem subroutines into M3 where M3 will USE M1 and M2 and sit higher up the build order.
there is no magic bullet it usually needs a little but of work to sort it out.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
L. Richard L. wrote:
[to jimd] I appreciate your comments because they seem like a big improvement to what I am doing. I particularly like the way you laid out the suggested pattern. However, I do not understand how Acode.f90 can access data (e.g., types and arrays) in Bdata.f90. Would Acode.f90 have to call getter's and setter's in Bcode.f90 to obtain the access?
[fortran]
! useAB.f90
program useAB
use Interfaces
use Adata
use Bdata
implicit none
A = 0.0
B = 0.0
print *,A,B
call Afoo(1.0)
print *,A,B
call Bfoo(2.0)
print *,A,B
end program useAB
-------------------------
! Interfaces.f90
module Interfaces
interface
subroutine Afoo(x)
use Adata
use Bdata
implicit none
real :: x
end subroutine Afoo
end interface
interface
subroutine Bfoo(x)
use Adata
use Bdata
implicit none
real :: x
end subroutine Bfoo
end interface
end module Interfaces
---------------------------------
! Adata.f90
module Adata
real :: A
end module Adata
-----------------------
! Acode.f90
subroutine Afoo(x)
use Interfaces
use Adata
use Bdata
implicit none
real :: x
A = A + x
B = B + x
end subroutine Afoo
-------------------------
! Bdata.f90
module Bdata
real :: B
end module Bdata
-----------------------------
! Bcode.f90
subroutine Bfoo(x)
use Interfaces
use Adata
use Bdata
implicit none
real :: x
call Afoo(x * 2.0)
end subroutine Bfoo
[/fortran]
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
(As I'm sure Jim knows - his code is not conforming because there are two interfaces for Afoo and Bfoo visible inside the Afoo and Bfoo subroutines respectively - one from being inside the actual subroutine proper and the other from the relevant interface block. You can prevent this problem from occurring by placing an ONLY clause on the USE Interfaces statements and preventing the relevant interface block from being visible.
Obviously woe betide anyone that manages to get a mismatch between the manually maintained interface block and the actual procedure interface.
Sometimes this approach is unavoidable due to real circular dependencies, but - my view - you need to have a pretty good reason to go down this path.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jim,
For the example you provide in Quote #18, it is unclear to me why you need to create interface blocks at all - see Ian's comments on all the potential issues with such an approach. Instead, for your specific example, why won't you utilize host association and make use of a procedure encapsulation module as shown below?
[fortran]
! useAB.f90
program useAB
use Adata, only : A
use Bdata, only : B
use foo, only : Afoo, Bfoo
implicit none
A = 0.0
B = 0.0
print *,A,B
call Afoo(1.0)
print *,A,B
call Bfoo(2.0)
print *,A,B
end program useAB
-------------------------
! Adata.f90
module Adata
implicit none
real :: A
end module Adata
-----------------------
! Bdata.f90
module Bdata
implicit none
real :: B
end module Bdata
-----------------------------
! module that encapsulates procedures
module foo
implicit none
use Adata, only : A
use Bdata, only : B
contains
subroutine Afoo(x)
implicit none
real :: x
A = A + x !.. HOST association would provide access to A
B = B + x !.. HOST association would provide access to B
end subroutine Afoo
-------------------------
! Bcode.f90
subroutine Bfoo(x)
implicit none
real :: x
call Afoo(x * 2.0) !.. HOST association should provide an explicit
! interface to Afoo
end subroutine Bfoo
end module foo
[/fortran]
Separately, it is unclear to me if Jim's example adequately captures the circular dependency issues faced by L. Richard L. Otherwise, Richard needs to present a real case with actual code that fails to compile and the readers can evaluate if there is a good scheme to overcome the issue.
I strongly feel one should:
- make good use of host association; it also comes in handy in inlining code, especially for frequently invoked procedures e.g., utilities, math functions, etc.,
- steer away from INTERFACE blocks as much as possible, and
- always apply the ONLY attribute on USE statements
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FortranFan,
The point of my post was to illustrate how to separate the functions, and not how one would code the specific sample code where Bfoo calls Afoo. I left it for an exercise of the reader to write into Afoo.f90 an additional subroutine Afee, and write into Bfoo.f90 an additional subroutine Bfee that makes the calls the other way (thus completing the other half of the circle).
If one were to rely on host association, then all the code, excepting the PROGRAM, would reside in a single module. And we wanted to avoid this.
Interface modules are the only way you get access to libraries (e.g. Win32, MKL, ...), and object-only code distribution. There is nothing inherently wrong with interfaces.
Note, the source code in the library should also use the same interface module. Thus assuring interface consistency.
Jim Dempsey

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page