- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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.]]
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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.
Ссылка скопирована
- « Предыдущий
-
- 1
- 2
- Следующий »
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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.
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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.
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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.
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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.
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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????
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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.
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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.
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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...
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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.
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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?)
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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" !!! :-)
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
Patience, grasshopper. All things in time.
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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!! :-)
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
[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?
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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.
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
(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.)
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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
- Отметить как новое
- Закладка
- Подписаться
- Отключить
- Подписка на RSS-канал
- Выделить
- Печать
- Сообщить о недопустимом содержимом
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
- Подписка на RSS-канал
- Отметить тему как новую
- Отметить тему как прочитанную
- Выполнить отслеживание данной Тема для текущего пользователя
- Закладка
- Подписаться
- Страница в формате печати
- « Предыдущий
-
- 1
- 2
- Следующий »