|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
Wswain
Joined: 17 Jul 2009 Posts: 12
|
Posted: Fri Jul 17, 2009 6:06 pm Post subject: Compile issues with Silverfrost, F77 Code |
|
|
We have F77 code that compiles fine on a linux GNU77 box. When I bring it into the silverfrost (we use it with Microsift Development Environment, Visual Studio 2003 as the Salford FT95 add-in.
I've cleared most problems of the compiler thinking a variable was Real(kind=1) vs integrer by explictly adding INT infront of the variable.
However, I have three errors now stopping the run.
1.) Passing a subroutine into a another subroutine as a variable by declaring explicit in the calling routine. It keeps thinking the sub variable needs to be a real(kind=1) variable by the receiving subroutine. This is not correct and the language is all there to set the declarations, plus works with GUN77.
2.) I'm using the personal version and am getting Error 112: undefined variable, array element or function result (/undef). I note a copiler switch may fix this but would turn off debugging as Checkmate and debug seem to set /undef implicitly.
3.) Floating point overflow on a couple calcs. Is the divide by a very small number (exp10**33)= 0, causing the overflow? Is the personal edition limited to the precision causing this. Again, GNU77 run does not crash. I need to run the program to have the watches active (or write out some inetrmediate values before I can tell which way the overflow is going. But, can't get past items 1 and 2 to run the program until the overflow.) Could this be a windows processor 32bit OS problem that doesn't crash the linux?
We need this ported into windows for modern work. The LINUX legacy is OK but very limited for us.
Any help gratefully received.
Regards,
Bill |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2393 Location: Yateley, Hants, UK
|
Posted: Fri Jul 17, 2009 11:26 pm Post subject: |
|
|
Bill,
I can't help but think your code probably ran more by luck than anything else under GNU77.
If the compiler thinks that your variable is Real not Integer, then it is because you have a major bug in the code. If you use IMPLICIT NONE, then you have to give a type to everything. If you use implicit typing, then the variable names have to match. This error alone needs fixing for anything to run.
Turning now to the numbered points:
1. Don't you mean EXTERNAL? Can you post a simple example for us to look at?
2. Undefined variable messages are probably because you have some variables used before they are defined. Does your previous compiler initialise everything? No wonder it doesn't work.
3. Probably No to the questions. It is the preceding errors that cause the problem.
If you are anywhere near SW London I could take a look at it for you next week.
Eddie |
|
Back to top |
|
|
Wswain
Joined: 17 Jul 2009 Posts: 12
|
Posted: Sat Jul 18, 2009 3:58 pm Post subject: linker |
|
|
Eddie,
Thanks and I think you've pointed me in a direction. I reviewed the make file and it has the flags -g and -static set for the linker and -g for the compiler. I think this means global variables are initialized if I understand a reading from the internet. I couldn't find a flag description manual or cheat sheet for the compiler and ifort linker recommended by the code writers in the make file.
The code is pretty robust and written by one of the premier US labs, but definantly old school of F77. I.e. a lot of DIMENSION a(*) references. I would have to totally rewrite the code to get rid of these and make them defined length. We can't do that if thats a problem.
I note your statement about the compiler thinking a value is REAL(Kind=1) must be because its so. I looked back through and we're passing an array value a(x) where x represents the array position. I'm used to arrays being one type in C and C+, hence my confusion where a(y) is an integer, used also as a passing variable, but a(x) is not.
I'm more of a code user than a compiler & linker expert and the two errors come up during linking.
I'm possibly looking to recreate the subroutine in the receiving subroutine so I don't have to pass it as an argument. This may fix one of the problems.
If you have any more thoughts I look forward to them.
Sorry, I won't be in SW London for a couple months as I travel to the UK a couple times a year, but am US and live in America.
Great to hear support from the Uk though as I work for a UK based company and have tons of UK colleagues and friends.
Bill |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2585 Location: Sydney
|
Posted: Sun Jul 19, 2009 9:08 am Post subject: |
|
|
Bill,
Assuming the problem is F77 memory management:-
You might find that the array A is being used to allocate memory for arrays in the called routines. If A(x) is real and A(y) is integer in the calling routine then this is an indication of this to me.
"x" and "y" must be declared as integer, or actually start with I-N for default integer, as array subscripts must be integer.
The array A and it's size would be declared in the main program or a common block. Then in all subsequent subroutines where it is supplied it would be in a "dimension A(*)" statement.
In the 1970's and 1980's this was a very common method of alloacting space for arrays in F77. F95 has automatic arrays and ALLOCATE, which makes this much easier, but the old F77 technique does work in F95, but you can not use /check, especially where the array is used for real and integer arrays.
You can overcome this /check problem by declaring two arrays.
Real*4 A(100000)
real*8 B(50000)
Integer*4 IA(100000)
equivalence (a(1), ia(1))
equivalence (a(1), b(1))
! Use A for R*4, B for R*8 and IA for I*4
! check index for all B calls
then changing the integer calls for A to be IA, if the receiving array is integer.
You mention the use of KIND, which is not F77, but F90+. Also if it is sharing memory check the byte length of the integers and reals. I prefer REAL*8 and INTEGER*4 to clearly document the byte length of the variables and arrays. Also real*8 takes twice as much memory for each variable as integer*4. You may need REAL*4 for the array A(*), for the integer and real memory to be calculated the same, although the supplied memory length calculation is easy to fix.
When using this type of code which you think is robust, I recommend that you do not use /implicit or /check as compiler options.
However, trying to impose /implicit and declaring the type of all variables in each subroutine or function is a good way of documenting the variables and also checking what variables have been used by someone else.
My understanding of EXTERNAL in F77 is that it is limited to functions and not allowable for subroutines, so check it's use you initially implied.
Then again it may not be a F77 memory management problem !
John |
|
Back to top |
|
|
Wswain
Joined: 17 Jul 2009 Posts: 12
|
Posted: Sun Jul 19, 2009 9:31 pm Post subject: |
|
|
John and Eddie,
Your knowledge of the details is slightly overwhelming to a casual user. I'm mostly a C/C+ programmer, but exactly I'm an engineer that uses programming to create code to solve my problems. This code was bought from Sandi National labs and is quite powerful for our problem at hand. It was just developed with F77 (unix targe) and it appears with all those warts for F95 and windows compatibility porting problems.
That said, I do appreciate your comments as they are helping fix things. I got the code to compile and run with the Salford f95 windows visual studio module yesterday.
I had to actually spent a lot of time commenting out the floating point error problems in basic physics calulations where a denominator seems to be zero and we are getting devide by zero (although not stated problems). Replaced by a unity (1.0) divisor to get through the problem.
Apparently, the source writers didn't have this problem I'm running into. Again, I'm not sure if this is an initialialization of global variables problem that F77 didn't consider, or the -g flag in the compiler and linker took care of. As a note, I rewrote almost all DIMENSION xt, xc, etc as REAL (or INT) xt, xc, etc. to clear the undefined variable errors. Although define the length as we use some very high exponent numbers (+ and -)and unsure if I'll restrict/crash the program by say;. Real*8 declarations.
First New question: Are variables (arrays) created in PROGRAM Main file seen throughout all the files that are part of the visual project solution? Again, I'm used to C/C+ with local scope and it appears the files loaded in the solution (5 files) seem to talk with each other. I can call from program main a subroutine in another file as part of the project solution set as if it was an #include file. Although, the original program still passes subroutines into other subroutines as a variable using EXTERNAL.
The main probelm I have as of 4am this morning is a mathematical subroutine to determine residuals on a very heavy matrix runs well the first time, but then seems to zeros out the Y(i) matrix causing division by zero errors. That's where I'm at now trying to understand this nueances. This has been identified by writing the calling function to the screen prior to making the CALL and it seen that the second iteration of the CALL is where I loose the Y(i) values and are all zeros.
But, this appears to me to be about scope that I don't understand. The original authors send the subroutine an array, y, as a variable. But then in the subroutine at the "header area" they re-declare the array with DIMENSION y(*). To me this is appears bad coding from the C world as redfining the variable in a local scope mode. What happened to the original array's values passed to the subroutine? But, as I'm only familiar with Fortran from my college days I'm having to dig back through reference books without this deep level of context in the books.
As usual my problems always seem to go beyond the typical reference material and since I don't code daily with it the problems are probably trivial to an expert Fortran coder.
Its Sunday afternoon and took a long break as I worked till 4am EST digging into the problems and narrowing down on this one very large, but also heavy math matrix manipulation subroutine.
I need to email the source code author to see what the array y(i) is trying to do, and is it global, or do two, y(i) exists. The reason I ask this is that the math matrix subrotine is about differential equations that take the form of yprime = f(something). Does the author re-implement a new y matrix for this sub-routine to keep consistent swith math syntax and the external y array got zeroed out. Or, is this something more fundamental to the overall problem.
Your thoughts again are very much appreciated, if not just to know I've got somebody to chat through this with.
Thanks,
Bill |
|
Back to top |
|
|
Wswain
Joined: 17 Jul 2009 Posts: 12
|
Posted: Sun Jul 19, 2009 9:46 pm Post subject: refernce information on code subroutine |
|
|
Modified format from fixed for forum:
this code solves a system of differential/c algebraic equations of the form g(t,y,yprime) = 0.
c
subroutine dasslrt uses the backward differentiation formulas of orders one through five to solve a system of the above form for y and yprime. values for y and yprime at the initial time must be given as input. these values must be consistent, (that is. if t,y,yprime are the given initial values, they must satisfy g(t,y,yprime) = 0.) the subroutine solves the system from t to tout. it is easy to continue the solution to get results at additional tout. this is the interval mode of operation. intermediate results can also be obtained easily by using the intermediate-output capability.
c
c dasslrt uses subroutines dastep,inider,vnorm,solve, njac,intrp,rchek,roots,r1mach,wtset and the linpack routines sgefa,sgesl,sgbfa, sgbsl,and the blas routines saxpy,sscal, isamax,sdot,scopy, and routines from the error-handling package xerror. the routine xerrwv from xerror is machine-dependent.
c
a labelled common nwm001 is used internally to communicate pointers to locations in rwork and iwork. another labelled common nwm00r is used internally to communicate variables used in the root-finding process.
c
c
c ------------description of arguments to dasslrt----------------------
c ------------(an overview)--------------------------------------------
c
c the parameters are
c
c res -- this is a subroutine which you provide
c to define the differential/algebraic
c system
c
c neq -- this is the number of equations
c to be solved
c
c t -- this is the current value of the
c independent variable.
c
c tout -- this is a point at which a solution
c is desired.
c
c info(*) -- the basic task of the code is
c to solve the system from t to
c tout and return an answer at tout.
c info(*) is an integer array which is
c used to communicate exactly how you
c want this task to be carried out.
c
c y(*) -- this array contains the solution
c components at t
c
c yprime(*) -- this array contains the derivatives
c of the solution components at t
c
c rtol,atol -- these quantities represent
c absolute and relative error
c tolerances which you provide to indicate
c how accurately you wish the solution
c to be computed. you may choose them
c to be both scalars or else both
c vectors.
c
c idid -- this scalar quantity is an indicator reporting
c what the code did. you must monitor this
c integer variable to decide what action to
c take next.
c
c rwork(*),lrw -- rwork(*) is a real work array of
c length lrw which provides the code
c with needed storage space.
c
c iwork(*),liw -- iwork(*) is an integer work array
c of length liw which provides the code
c with needed storage space.
c
c data,prop -- these are real and integer parameter
c ,global arrays which you can use for
c communication between your calling
c program and the res subroutine
c (and the jac subroutine)
c
c jac -- this is the name of a subroutine which you
c may choose to provide for defining
c a matrix of partial derivatives
c
c g -- this is the name of the subroutine for defining
c constraint functions, whose roots are desired
c during the integration. this name must be declared
c external in the calling program
c
c ng -- this is the number of constraint functions g(i).
c if there are none, set ng=0, and pass a dummy name
c for g.
c
c jroot -- this is an integer array of length ng for output
c of root information
c
c quantities which are used as input items are
c neq,t,y(*),yprime(*),tout,info(*),
c rtol,atol,rwork(1),rwork(2),rwork(3),lrw,iwork(1),
|
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2393 Location: Yateley, Hants, UK
|
Posted: Sun Jul 19, 2009 11:04 pm Post subject: |
|
|
Bill,
Roughly how many lines of code are we talking about here?
I never knew that EXTERNAL was limited to FUNCTIONs (if it is).
The scope of a variable name in Fortran 77 is limited to the subprogram (PROGRAM, FUNCTION, SUBROUTINE) it appears in. Fortran 90 and 95 introduce things called MODULEs that can give variables wider scope, but that won't be present in a Fortran-77 code.
Variables can be passed as subprogram arguments OR through a COMMON block. If the same name is given in two subprograms for the same variable, it looks like the scope is wider than it actually is. The type of a variable usually needs to be the same in every routine that it is passed between. The exception is when the original programmer passes a block of memory and is not interested in its contents any more, as then he can declare it as a different type. This sort of code is almost impossible to read.
"Assumed size" (*) always gives readability problems.
Eddie |
|
Back to top |
|
|
Wswain
Joined: 17 Jul 2009 Posts: 12
|
Posted: Sun Jul 19, 2009 11:39 pm Post subject: |
|
|
Eddie,
Thanks for the quick reply.
Between all 5 files probably looking at 12,000 lines. The three big files are 2,400, 3,000 and 3,800 each.
As to the Subroutine causing the trouble I am posting the first couple lines of the routine which is about 500 lines. Please note the redeclaration of the input varible y, as DIMENSION y(*). The write function a ouple lines below is strictly a debug line that allowed me to catch the calling routine that is causing the problems. Within this there is a CALL to a subroutine DASSLRT ( an implicit differential solver routine of about 3,800 lines with many calls to y(i) = throughout.
Posting:
subroutine resids(ires,time,y,ypr,f,data,prop,global,nelmax)
save
c
c.... subroutine evaluates residuals f(1), f(2),...,f(ny),...,f(nymax).
c
dimension y(*),ypr(*),f(*),data(nelmax,*),prop(nelmax,*),global(*)
c.... compute current properties.
write (*,*) 'Calling Props from Subroutine residuals'
call props(time,y,ypr,data,prop,global,nelmax)
c.... call appropriate subroutines for each residual calculation.
do 1000 nel=1,nelmax
neltype=data(nel,1)
go to (1,2,3,4) neltype
A main problem I'm having with Windows visual studio and Salford is that when I hit DEBUG, F5 to step through it the program pauses/halts at an empty MSDOS command screen and never proceeds to run to actually step through to my break lines. Therefore I can't watch the variables while stepping through the code. Is this a visual studio problem with Salford? I can always do this with C/C+. Does the personal edition splash "image" that never comes up durring debug, but does during a .exe run contribute? (p.s. this was an eval of the silverfrost for purchase that seems to be turning into requiring a full license version with respect to porting old F77 code?) I've already sent silverfrost sales an email.
Thanks,
Bill |
|
Back to top |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2585 Location: Sydney
|
Posted: Mon Jul 20, 2009 1:00 am Post subject: |
|
|
Bill,
A lot of your questions relate to the code, but are difficult to answer from the available info.
Try including the compiler options /save /zero /do1. Also use /debug and /-implicit.
These may retain some of the non-standard coding techniques that might explain some of the problems.
As with C, variables are local or global if inclued in common.
When returning from a subroutine, the standard is all local variables are lost, although most f77 compilers did not enforce this. /save fixes this problem.
If one subroutine is 3,800 lines, I would estimate that the programmer was an engineer or a research student. It may not be robust code.
A general guide to fixing these problems is :
1) never loose the original source and
2) try to find a solution that imposes minimal change to the original code
3) document your attempts
Can you run the program as stand alone first?
There are many other possible approaches you could try. 12,000 lines is a lot to get fixed, especially if the original developer did not use standard conforming f77 code.
Good luck
John |
|
Back to top |
|
|
Wswain
Joined: 17 Jul 2009 Posts: 12
|
Posted: Mon Jul 20, 2009 1:45 am Post subject: |
|
|
John,
Thanks. As mentioned in the original, the code complies using the make file dor GNU-77 on Redhat linux,....and seems to run.
The make file included the -g and -static flags for the linker, and just -g for the compiler.
Thats the frustrating thing. The subroutine you mention being 3,800 lines is actually a file with the main subroutine at the top and about 10 other subs at the bottom called from the main subroutine of the file. Actas like an include file, somewhat. Similar to C function calls at the bottom but without prototyping in the header.
I'll try your flags.
I'm fairly certain these were robust F77 coders as again they work for the Sandia national lab. The author I spoke with is quite senior, but he doesn't work on anything but unix/linux. I think this is the main problem for the portability. Also, there seniority explains the "old style" of 80's F77 programming that seems to have F90+ compilers/linkers messed around.
I still have the base uncorrupted code.
Regards,
Bill |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2393 Location: Yateley, Hants, UK
|
Posted: Mon Jul 20, 2009 8:19 pm Post subject: |
|
|
Bill,
While you are still at the evaluation stage, let me tell you that the PE unlicensed version is identical to the licensed version EXCEPT for the initial "nag" screen and in consequence, a slower startup.
I don't think that you are looking at absolutely standard Fortran77, as the code almost certainly makes use of something in the GNU77 compiler that isn't standard. Compiler and linker switches are a giveaway that this is so.
Consider your code fragment:
Code: | subroutine resids(ires,time,y,ypr,f,data,prop,global,nelmax)
save
c
c.... subroutine evaluates residuals f(1), f(2),...,f(ny),...,f(nymax).
c
dimension y(*),ypr(*),f(*),data(nelmax,*),prop(nelmax,*),global(*)
c.... compute current properties.
write (*,*) 'Calling Props from Subroutine residuals'
call props(time,y,ypr,data,prop,global,nelmax)
c.... call appropriate subroutines for each residual calculation.
do 1000 nel=1,nelmax
neltype=data(nel,1)
go to (1,2,3,4) neltype |
In the loop do 1000 etc, the program extracts "neltype" as the first of several properties for element number "nel". In the following computed goto, neltype can only validly be 1,2,3 or 4. However, the array "data" is REAL, and therefore there is no guarantee that the correct value is extracted from it. Of course, I suppose that as some small integers are stored exactly in REAL variables, you might get the right answer putting NELTYPE into the "data" array and getting it out again, but it is bad coding, and shouldn't be relied upon. (1, 2 and 4 are almost certainly stored exactly - but is 3? Anything that is an integer power of 2 is potentially stored exactly). I wouldn't rely on it.
Hence, at the risk of being slightly negative about the original coders, I would have to say that you shouldn't rely on the quality of the original code.
Plenty of people are going to say that the computed GOTO is rubbish. I've used it a few times (in 40 years) but not often. I certainly wouldn't use it without testing that NELTYPE was in the range 1 to 4 inclusive! Again, don't be too confident of the quality of the original code.
I don't think that 12,000 lines of code is too much to transfer, especially as it appears to have lots of comments (including a blank comment line before and after each meaningful comment (sometimes). On the other hand, even in the fragment you psted, a comment appears that makes me wonder:
Code: | c.... subroutine evaluates residuals f(1), f(2),...,f(ny),...,f(nymax). |
Where do we find out what "nymax" is? There isn't any COMMON, and there isn't a parameter in the list.
This code uses "assumed size" arrays. Again, although I never use them, they are a way of having a variable-sized array passed without also having to pass a variable giving the size.
All might be clearer if we could read the main program!
In my view, you need a real Fortran guru.
Regards
Eddie |
|
Back to top |
|
|
Wswain
Joined: 17 Jul 2009 Posts: 12
|
Posted: Mon Jul 20, 2009 8:50 pm Post subject: |
|
|
Eddie,
Wow, great comments and I definantely hadn't considered the Integer part of the DATA. Nel = Number of Elements as the main program creates node meshes for the diffferential numerical integration of fluid flow calculations. The nodes are physical elements of the problem creation using a data file to describe the physical arrangement and fluid properties.
The GOTO you point out is one of four types of fluid flow that got placed into the DATA array by a read function to a structured data file of the problem, ie, isothermal, with heat transfer, etc. The Read gets an INT for this position (_, 1) in the DATA array strored. NelType relates to the numbered elements physical type as either a continuity node, an energy or physical property node. The DATA array created has mixed integers that are basically flags and REAL numbers that are actual data such as pressure and temperature.
As to the need of a Real Fotran guru. How, do I locate one? Would you consider yourself one for consultation?
I'm not sure I can send the main file for review, but will check the export and distribution statements. I fear the posting to this forum creates distribution to potentially thousands of viewers. As to getting it to a code Guru for assistance in another manner, such as email, should be allowed as that would be maintenance for specific compiler compatibility and the license also says we can make changes to support our specific data run needs. This feature of manipulating the source code for customization is called out in the users manual of the code.
Regards,
Bill |
|
Back to top |
|
|
Wswain
Joined: 17 Jul 2009 Posts: 12
|
Posted: Tue Jul 21, 2009 12:25 am Post subject: |
|
|
All,
Played around with the compiler flags this afternoon. Believe it or not, all the floating point errors were due to not using:
/defreal_kind 3
I can't find the documentation for the precision and bit size on the type 3, but found a note in the help file that says "kind =3" for win32 only. But, not what it means.
the code executed flawlesly with the correct outputs.
Unbelieveable!!!!!!
Bill |
|
Back to top |
|
|
Wswain
Joined: 17 Jul 2009 Posts: 12
|
Posted: Tue Jul 21, 2009 12:49 am Post subject: |
|
|
All,
Thanks for the assistance during my trials and tribulations over the weekend.
The good news story is that the work casued me really get into the code and understand its capabilities and actions a whole lot more than I did. We're looking forward to actually running our real world problems on the exe file using the supported input files we'll create in text now.
I think even setting up the problems is a whole lot easier now understanding how the code reads in the infile.
Kind Regards,
Bill |
|
Back to top |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2393 Location: Yateley, Hants, UK
|
Posted: Tue Jul 21, 2009 12:31 pm Post subject: |
|
|
Bill,
Kind=1 is REAL*4, Kind=2 is REAL*8, Kind=3 is REAL*10 (in old notation). The default is Kind=1.
Glad it now works. You still need someone skilled to go through the code and "future proof" it. That's not me, I'm afraid.
I advise you to try compiling the code in Win32 mode (not with .NET). I imagine that it will execute faster, but I may be wrong. Then give some deep thought as to whether or not you want a proper windows interface. FTN95 gives you 2 completely separate routes to that.
Best of luck
Eddie |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|