Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.

MSFLIB and DFLIB

thomasglallen
Beginner
8,279 Views

I have some legacy code that uses MSFLIB and DFLIB, which apparently came from COMPAQ fortran.  When I get to the llinking, I get "error LNK2019: unresolved external symbol _f_setmessageqq referenced in the a routine".  I know that I'm using, in the routine, SETMESSAGEQQ(...), and that is the problem.  It either comes from MSLIB or DFLIB, don't know.  I get no error with the statements USE MSLIB and USE DFLIB in the fortran code, so does someone have a listing of intel  statements that are equivalent to the legacy statements in MSLIB and DFLIB.  I've searched and can't find any reference to the routines found in these libraries. Thanks.

Tom

0 Kudos
51 Replies
thomasglallen
Beginner
4,371 Views
In the same code, when I increase the array, I get the error that my variable CMB it too large for NTCOFF (Bigger than 2gb). CMB is a common statement like this: COMMON /CMB/ CM(IRESRV), IP((2*MAXSEG), IB11, IC11, ID11, NEQMAT, NEQ, NEQ2 Now, above this I have IMPLICIT REAL*8 (A-H,O-Z) and IMPLICIT INTEGER*8 (I-N). Now, the this common statement is located about 5 other subroutines. I added the ALLOCATABLE statement like this: COMMON ALLOCATABLE /CMB/ ... and still get the same error (CMB too large for NTCOFF). I tried different methods but got syntaxed errors. Where do I go from here in order to allocate enough memory for the arrays. Thanks.
0 Kudos
thomasglallen
Beginner
4,371 Views
Forgot to mention that the values for the arrays, such as IRESRV and MAXSEG are stored in an include file as a parameter (such as PARAMETER (MAXSEG=200000, MAXMAT=7500) and in the code IRESRV=MAXMAT**2 where this variable MAXMAT is defined in the parameter statement in the include file as well). Any help is appreciated. Thanks.
0 Kudos
Steven_L_Intel1
Employee
4,371 Views
You'll have to move away from COMMON. Also, you'll have to build for 64-bits if you aren't already. ALLOCATABLE is a variable attribute and not compatible with COMMON. I recommend creating a module that declares the allocatable arrays, something like this: [fortran] module CMB_MOD IMPLICIT NONE real(8), allocatable:: CM(:) integer(8), allocatable:: IP(:) integer(8) :: IB11, IC11, ID11, NEQMAT, NEQ, NEQ2 end module CMB_MOD [/fortran] Now in the places that you INCLUDEd the COMMON definitions, instead say: use CMB_MOD (This has to go before any IMPLICIT or other declarations.) At the start of your program, where you have also done the USE (the definitions of IRESRV and MAXSEG should also go in the module), say: allocate (CM(IRESRV), IP(2*MAXSEG) The rest of your program can remain unchanged except for needing the USE.
0 Kudos
dboggs
New Contributor I
4,371 Views
To address your original Q re the needed libraries: I too have this problem and would like to see such a list. But, the specific problem you describe should have a very fast solution: If you are programming with a valid Intel Visual Fortran installation then you also have contextual access to help, and all you should need to do is look up SETMESSAGEQQ. It will tell you that you need USE IFQWIN. Most of ifqwin overlaps with dflib, but there are differences. There is no problem having USE both in your code (although possibly inefficient, I don't know). If you really want to remember that IFQWIN is only there to solve this one unresolved external, then put USE IFQWIN, ONLY: SETMESSAGEQQ.
0 Kudos
Steven_L_Intel1
Employee
4,371 Views
SETMESSAGEQQ is a QuickWin routine. As I noted above, USE DFLIB should work fine for this in Intel Visual Fortran. We don't support USE MSFLIB. If you want to change to USE IFQWIN, that's fine too. Note that your application needs to be built as a QuickWin project type in order to use that routine.
0 Kudos
thomasglallen
Beginner
4,371 Views
Thanks. I tried it on one portion of the code, and it compiled and linked fine. Now, just want to make sure I understand - the "USE" statement (placed in all the required subroutines) will act as the COMMON statement in that all data will be shared amongst the subroutines. Also, it looked like the ALLOCATE(...) worked when I put it at the end all the COMMON statements in a routine, which I guess is where it should go (also after include, parameters, implicits, declarations). Is this correct? I'll have some other questions later. Thanks again.
0 Kudos
Steven_L_Intel1
Employee
4,371 Views
The USE makes the declarations in the MODULE visible. This includes the variable declarations that replace the COMMON. The ALLOCATE goes somewhere in executable code where you will do that statement before using the array.
0 Kudos
thomasglallen
Beginner
4,371 Views
I've been making the changes as suggest here, compiling and linking with no errors. Now when I run the code (excutable), it says that "allocatable array is already allocated". I suspect that in other subroutines, maybe a Dimenstion statement is being used that shouldn's since I'm allocating the space. I like to have some clues on this, so when it crashes, it dumps 4 columns (PC, Routine, Line, and Source). All columns say UNKNOWN accept for the PC column. Is there a way to turn on something that fills these columns in so I can get a clue as to where the "already allocated" variable is? This would help a lot in converting this code over more quickly. Thanks.
0 Kudos
Steven_L_Intel1
Employee
4,371 Views
/traceback is what you want if you're building from the command line - this should be on by default for VS builds. A DIMENSION attribute would not be relevant here - rather, you have an allocatable array that is previously allocated. Is this a local array to the routine? Is it named in a SAVE statement or is /Qsave enabled?
0 Kudos
thomasglallen
Beginner
4,371 Views
I replaced the COMMON block you suggested with the USE statement for the subroutines that contained the COMMON block. I would imagine it's a local array to the routine. I went ahead and added the /traceback and /Qsave, and ran it again, it gave me again the columns each with 10 rows, but only two of these were filled in with two routines and line numbers, the rest unknowns. The routines it indicated didn't seem to give me any clue about what was be allocated already. What is /QSave? Let me look at this for a bit - I think this is helping me somewhat to trace what is going on here. I'll get back with more specifics. Thanks.
0 Kudos
Steven_L_Intel1
Employee
4,371 Views
Actually, I wanted you to remove /Qsave if it had been added. This is Fortran > Data > Local variable storage > All variables SAVE in VS. This has an unfortunate side-effect on local allocatable variables.
0 Kudos
thomasglallen
Beginner
4,371 Views
I solved this allocate problem (I allocated a variable in main with the USE and did the same in a subroutine, and didn't need it in the subroutine, so I understand what is going on there) Now, I have another COMMON statement that I replaced with a USE. I placed it in one subroutine that had an equivalence statement : EQUIVALENCE (CAB,ALP),(SAB,BET). I obtained the error "attribtes of this name conflict with those made accessible by a USE statement". So I moved the EQUIVALENCE to the USE module, which solved that, but when I compile it, I get "An equivalence data object must not have the ALLOCATABLE or Pointer attribute" and "Variables containing ultimate allocatable array components cannot appear in COMMON or EQUIVALENCE statements. Variables ALP and BET are defined as REAL(8), ALLOCATABLE in module (have to be). Any way around equivalence, or something that is the same in fortran that works with ALLOCATABLE?
0 Kudos
thomasglallen
Beginner
4,371 Views
Also wanted to add that the CAB and SAB variables I mentioned above are defined in the subroutine as DIMENSION CAB(1), SAB(1).
0 Kudos
thomasglallen
Beginner
4,371 Views
Did some research. THe Fortran EQUIVALENCE was introduced as a means to inform the compiler that two or more different variables (usually arrays) could share the same storage locations because the programmer had arranged to complete the use of one of them before using any of the others. I guess years ago, memory and storage was limited, and newer machines don't have that issue. So I guess I could just comment out the equivalence and keep the Dimension statement - is that OK to do? It compiles or course with no errors.
0 Kudos
Steven_L_Intel1
Employee
4,370 Views
More often, EQUIVALENCE was used to provide access to a variable with a different type or length. You need to look at how the variables named in the EQUIVALENCE were used. If you simply take out the EQUIVALENCE, then instead of one set of data you have two - and probably introduce uninitialized references. There's no universal answer to your question. It all depends on what the application used EQUIVALENCE for.
0 Kudos
thomasglallen
Beginner
4,370 Views
Now that you mentioned this, the EQUIVALENCE statement is something like this: EQUIVALENCE(CAB, ALP) where CAB and ALP are defined as follows: ALP(MAXSEG), where MAXSEG = 2000 in an include file and DIMENSION CAB(1). These appear to have different lengths. I would imagine you are talking about this. In this particular case, what is going on with the variables in the equivalence in terms of what equals what or what is being shared. If I understand this concept, I'll be able to make some intelligent changes to this code. Thanks.
0 Kudos
bmchenry
New Contributor II
4,370 Views
Some thoughts/ideas on the subject. modules are not sequential like common storage used to be back in the day. equivalence to modules does not insure you are 1:1. to get around that be sure to set equivalence each variable to the array. for example, if you have in the old code real something (3) real one, two, three In the old days you could say equivalence (something(1), one) and it would equate all three items to the something() since they existed in sequence. not so much anymore. now you need to be specific about it equivalence (something(1), one), (something(2), two), (something(3), three) very tedious to set up but then once set up it works as expected.
0 Kudos
thomasglallen
Beginner
4,370 Views
As I'm going through the code making the substitution of USE cases for the COMMON statements, I make one change, run a test case, then make the next, etc. I made one change where I commented out a COMMON, replaced it with a USE, and I got a divide by zero error. I traced it down to a few COMMONs, don't know which one, but here's what I think is going on, and I need some advice just to save me some time: It looks like the USE statement doesn't appear to work exactly as a COMMON (I replaced a COMMON with a USE and got a divide by zero, restored it, and it was fine). In the code I'm trying to convert over to 64-bit with large arrays, some subroutines apparently when called have variables that are initialized and the COMMON captures these values in the subroutine, and these values are used/passed by other subroutines that contain these values. Now, worst yet, some of these subroutines contain an "if" statement, which can change the stored values in the COMMON statement when called by another subroutine that passes the value that satisfies the “if”. Now, in the module, I have the arrays as allocatable, non-arrays as either integer(8) or real(8) (as described above), and I allocate the arrays only once in the Main program, and then use the USE in replacement for the COMMON. So, I’m wondering does the USE capture changes to its variables in a subroutines that reassigns that values, or do I need to do something else to make this act exactly like these COMMON statements. As a side note, I compiled this under linux, don’t have the array allocation issues as in Windows. Thanks.
0 Kudos
thomasglallen
Beginner
4,370 Views
OK, maybe I talked out of line too soon, below is a test program, and it appears that the module captures changes in both subroutines, the print out should be 3333 and 4444.0, which it is. So, I guess the USE acts exactly as a COMMON, am I correct? Module myModule INTEGER i1 REAL f1 END MODULE PROGRAM myProg USE myModule IMPLICIT NONE C INTEGER i1 C REAL f1 i1=1111 f1=2222 CALL mysub1 WRITE(*,*) 'FROM mysbu1', i1, f1 CALL mysub2 WRITE(*,*) 'FROM mysub2', i1, f1 END C C SUBROUTINE mysub1 USE myModule IMPLICIT NONE C i1=3333 f1=4444 END C SUBROUTINE mysub2 USE myModule IMPLICIT NONE i1=5555 f1=6666 CALL mysub1 END
0 Kudos
Steven_L_Intel1
Employee
4,217 Views
I would not say that USE is "exactly like COMMON", though, as has been suggested in this thread, module variables made accessible by USE are usually a suitable replacement for COMMON as it is normally used. COMMON declares a layout of variables that overlay other declarations of the same named COMMON in other program units. If all of these COMMON layouts are the same and each variable is accessed individually, then it is pretty much the same as module variables. But COMMON allows different layouts in different program units (for named COMMON, all must be the same length) and it establishes a "storage sequence" of the variables as a group, which USE does not.
0 Kudos
Reply