Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28385 Discussions

lsode and mixing .f (F77) and .f90 (F90) programs/subroutines

lsudolemite
Beginner
807 Views
Hi, new to the forums and I'm running into an issue that Google hasn't been able to help me with. I'm far from proficient in Fortran, but I have learned a bit, and I'm running into a problem using an ODE solver called "dlsode" (double-precision version of the subroutine "lsode"). My main code is written in F90, and dlsode is an F77 subroutine that's being called. It appears as if after compiling using the following command:

ifort -c main.f90 sub1.f90 ... subn.f90 dlsode.f

that all of the necessary object files are created (where main.f90 is the main code and sub1.f90, etc, are other F90 subroutines). However when I try linking them using ifort or ifort -o, the following error message appears:

main.f90:(.text+0x171d): undefined reference to 'dlsode_'

Usually when I see this it means I forgot to include a subroutine in my shell script that I use for compiling. However, dlsode is there, it's in the compilation path, but it appears that the compiler just doesn't see it.

Is this the result of mixing F77 and F90 subroutines? This is the only reason I can think of for this particular error. I'd really appreciate any insight or feedback anyone has for me on this issue. Thanks!


0 Kudos
9 Replies
Ron_Green
Moderator
807 Views
Are you listing all of your object files on the link step, OR doing something like:

ifort -o foo.exe *.o

Please show us your command line. You must include all object files in the link step.

ron
0 Kudos
lsudolemite
Beginner
807 Views
Yes, they're all specifically included (no wild card). Below is the shell script I use:

ifort -c physconstants.f90
ifort -c bcleftq1.f90 bcrightq1.f90 caloriceosie2t.f90 caloriceosit2e.f90 caloriceosge2t.f90 caloriceosgt2e.f90 cartesiangrid1D.f90 conseospi.f90 conseospg.f90 convection1.f90 eigenvalue1.f90 fq1.f90 icp1.f90 icq1.f90 ktbin1.f90 minmod.f90 physconstants.f90 output.f90 primgpt2rho.f90 primgrhop2t.f90 sourcegrad1.f90 sourceparam1.f90 primirhot2p.f90 primirhop2t.f90 rk2.f90 rk4.f90 qinterp1.f90 pderivi.f90 pderivg.f90 dlsode.f scalarcalorici.f90 scalareosi.f90 scalarcaloricg.f90 scalareosg.f90
ifort -o bcleftq1.o bcrightq1.o caloriceosie2t.o caloriceosit2e.o caloriceosge2t.o caloriceosgt2e.o cartesiangrid1D.o conseospi.o conseospg.o convection1.o eigenvalue1.o fq1.o icp1.o icq1.o ktbin1.o minmod.o physconstants.o output.o primgpt2rho.o primgrhop2t.o primgrhot2p.o sourcegrad1.o sourceparam1.o primirhot2p.o primirhop2t.o rk2.o rk4.o qinterp1.o pderivi.o pderivg.o dlsode.o scalarcalorici.o scalareosi.o scalarcaloricg.o scalareosg.o

Here, "physconstants" is a module, "minmod" is a function, "ktbin1.f90" is the main code and all other files are subroutines.


0 Kudos
Ron_Green
Moderator
807 Views
the link step: the argument after -o should be the output executable file. If your cut and paste is correct, you are telling the compiler to put the executable in bcleftq1.o, and hence NOT including that object in the link.

I would also check that dlsode.f contains a subroutine named "dlsode" and that the main program is using a CALL statement - that is, make sure that the main program is CALLing a SUBROUTINE and not invoking dlsode as if it were a function (check the interface).

Finally, you can

nm dlsode.o

to check that the symbol for the subroutine is indeed exported correctly.

ron
0 Kudos
lsudolemite
Beginner
807 Views
Thanks so much for the quick reply. I included an executable file name, but the same error continues to appear, unfortunately. I also checked the data flow between the subroutine and main program, and that appears to be fine.

Also, I forgot to include a line in the error message. The line above the error I posted earlier says:

ktbin1.o: In function 'MAIN_':
0 Kudos
Ron_Green
Moderator
807 Views
So your main Fortran PROGRAM is in source file ktbin1.f90, correct? And that calls dlsode?

Can you send the output of

nm dlsode.o

OR remove all your object files, tar up the files and attach them to this issue? Whichever is easier.

OR show the call to DLSODE from within ktbin1.f90, AND show the SUBROUTINE line from dlsode.f

we need more information.

ron
0 Kudos
lsudolemite
Beginner
807 Views
I will post all of the requested files/info later tonight or early tomorrow. Thanks again!
0 Kudos
lsudolemite
Beginner
807 Views
MAD wgreen:
So your main Fortran PROGRAM is in source file ktbin1.f90, correct? And that calls dlsode?

Can you send the output of

nm dlsode.o

OR remove all your object files, tar up the files and attach them to this issue? Whichever is easier.

OR show the call to DLSODE from within ktbin1.f90, AND show the SUBROUTINE line from dlsode.f

we need more information.

ron


Yes, the main program is ktbin1.f90. This file consists of the source code followed by an external subroutine called SOURCECV1 that is required by DLSODE. The portions of ktbin1.f90 that defines variables used by DLSODE are as follows:

INTEGER :: mf=22
INTEGER :: lrw=20000000
INTEGER :: liw=100000
INTEGER, ALLOCATABLE, DIMENSION(:) :: iwork
DOUBLE PRECISION, ALLOCATABLE, DIMENSION(:) :: rwork
INTEGER :: istate=1
INTEGER :: itask=1
INTEGER :: iopt=0
INTEGER :: itol=1
DOUBLE PRECISION :: rtol=1.0d-5
DOUBLE PRECISION :: atol=1.0d-6
DOUBLE PRECISION :: dummy=0.0d0
DOUBLE PRECISION :: t, dt
INTEGER :: N_x, N_eq
DOUBLE PRECISION, ALLOCATABLE, DIMENSION(:, :) :: qold, qnew
EXTERNAL SOURCECV1

ALLOCATE(iwork(liw), rwork(lrw))
ALLOCATE(qold(N_x, N_eq), qnew(N_x, N_eq))


Here, the variables "t", "dt", "N_x" and "N_eq" are given values elsewhere in the main program prior to the ALLOCATE statements. The call to DLSODE is made within a do loop:

DO i=1,N_x
istate=1
CALL DLSODE(sourcecv1, N_eq, qnew(i, :), t, t+dt, itol, rtol, atol &
itask, istate, iopt, rwork, lrw, iwork, liw, dummy, mf)
qold(i, :)=qnew(i, :)
END DO

I am attaching to this post the subroutine dlsode.f. This is a widely-available, well-verified solver with clear documentation provided at the top of the file explaining the purpose and use of all arguments. If any more information is needed, please let me know.
0 Kudos
Ron_Green
Moderator
807 Views
Ah I see what is going on. Did you notice the name of the subroutine in dlsode.f?

c **********************************************************************
c Program dlsode.f
c **********************************************************************
c


subroutine lsode (f, neq, y, t, tout, itol, rtol, atol, itask,
1 istate, iopt, rwork, lrw, iwork, liw, jac, mf)


"lsode" procedure, but you're calling "dlsode". Is it possible that the subroutine was corrupted, or perhaps you need a different 'dlsode' from ODEPACK. The 'nm dlsode.o' would show you the problem, since it will show "lsode_" in the symbol table. The linker is correct, you are missing "dlsode" subroutine OR you should be calling lsode.

ron
0 Kudos
lsudolemite
Beginner
807 Views
Wow, do I feel dumb. I never even saw this. Changed the subroutine name to "dlsode" and appears to work. Thanks so much for al the help.
0 Kudos
Reply