Question

I keep receiving the "undefined symbol: ising3d_" error when I execute the ising3d.f inside of the ising3d_fort2oct.cc. Can anyone provide suggestions on what I could to change either ising3d.f or ising3d_fort2oct.cc to fix this problem?

Octave Terminal Commands :

octave:12> system("gfortran ising3d.f -o ising3d")
ans = 0
octave:13> mkoctfile ising3d_fort2oct.cc
octave:14> ising3d_fort2oct
error: /home/b/Desktop/Umaine_Classes/CHY_573/3disingmodelf/ising3d_fort2oct.oct: failed to load: /home/b/Desktop/Umaine_Classes/CHY_573/3disingmodelf/ising3d_fort2oct.oct: undefined symbol: ising3d_
octave:14> 

ising3d_fort2oct.cc : Dynamically Linked C++ Function calling fortran subroutine ising3d.f :

#include <octave/oct.h>
#include <octave/f77-fcn.h>
extern "C" void F77_FUNC (ising3d,ISING3D)();
DEFUN_DLD (ising3d_fort2oct, args , ,"work in progress")
    {
        octave_value_list retval;
        F77_FUNC(ising3d,ISING3D)();
        return retval;
    }

ising3d.f : really old fortran subroutine :

          SUBROUTINE ising3d()
C         3D ISING MODEL
C         Critical temperature TC = 4.5116=1/.22165
          DIMENSION IS(10,10,10), EX(13)
          REAL *8 R(1)
          DATA IS/1000*1/
          ITMAX=5000
          ISTART=4000
          L=10
          NR=1
          ISEED=768521034
          M=L*L*L
          DO 1000 K=1,24
          TR=0.05+(K-1)*.05
          T=TR/.221655
          MR=0.
          DO 3 I=1, 13, 2
3         EX(I)=EXP(-2*(I-7.)/T)
          DO 2 ITIME=1,ITMAX
          DO 1 K1=1,L
          K1P1=K1+1
          K1M1=K1-1
          IF(K1.EQ.1) K1M1=L
          IF(K1.EQ.L) K1P1=1
          DO 1 K2=1,L
          K2P1=K2+1
          K2M1=K2-1
          IF(K2.EQ.1) K2M1=L
          IF(K2.EQ.L) K2P1=1
          DO 1 K3=1,L
          K3P1=K3+1
          K3M1=K3-1
          IF(K3.EQ.1) K3M1=L
          IF(K3.EQ.L) K3P1=1
        IEN=7+IS(K3,K2,K1)*(IS(K3M1,K2,K1)+IS(K3P1,K2,K1)+IS(K3,K2M1,K1)
     &  +IS(K3,K2P1,K1)+IS(K3,K2,K1M1)+IS(K3,K2,K1P1))
          CALL GGUBS(ISEED,NR,R)
          IF(EX(IEN).LT.R(1)) GOTO 1
          IS(K3,K2,K1)=-IS(K3,K2,K1)
          M=M+2*IS(K3,K2,K1)
C          WRITE(*,*) M,ITIME
1         CONTINUE
          IF (ITIME.GT.ISTART) MR=MR+M
2         CONTINUE
          WRITE(*,*) FLOAT(MR)/1000./FLOAT((ITMAX-ISTART)),TR
          WRITE(1,*) FLOAT(MR)/1000./FLOAT((ITMAX-ISTART)),TR
1000      CONTINUE
          STOP
          END
          RETURN
          END

        SUBROUTINE GGUBS(ISEED,NR,R)
        IMPLICIT REAL *8(A-H,O-Z)
        DIMENSION R(NR)
        DATA D2P31M/2147483647.D0/
        DATA D2P31/2147483648.D0/
        DO 7 I=1,NR
        ISEED=MOD(16807.D0*ISEED, D2P31M)
        R(I)=ISEED/D2P31
    7   CONTINUE
        RETURN
        END
Was it helpful?

Solution

The problem is not in the code but in the way you are compiling and linking the oct-file to be called from Octave. When you built ising3d_fort2oct, you did not instruct it to link with or how to find the ising3d Fortran function.

You can link these two source files together in one of two ways. You can compile each individually and then link the resulting object files together, or you can call mkoctfile once with both source files and let it do everything for you.

To build the oct-file from both sources with one command, do

octave:1> mkoctfile ising3d_fort2oct.cc ising3d.f

in the Octave shell, where mkoctfile is told about the second source file to compile and link together with the first.

To build the Fortran subroutine separately, as you were attempting to do, and then link it later with the oct-file wrapper, you can instead do

octave:1> system ("gfortran -c ising3d.f -o ising3d.o");
octave:2> mkoctfile ising3d_fort2oct.cc ising3d.o

Note that you still need to link the oct-file with the object file explicitly. Otherwise the oct-file will be compiled assuming that the function is provided by Octave itself or by a system library, and that is why you get an undefined symbol error.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top