0

I tried the following code to get the code to work correctly. It seems I need to write an interface to avoid mistaken results. I wrote the following, but it does not pass the compiling stage. The errors are the following: (use gfortran compiler)

fit.f90:34.16:
  TYPE(spec), INTENT(IN) :: SMP
            1
Error: Derived type 'spec' at (1) is being used before it is defined
fit.f90:35.12:
  REAL(q), INTENT(OUT) :: RES
        1
Error: Symbol 'q' at 1 has no IMPLICIT type
...

Here is the compilable code to illustrate the issue.

MODULE prec
  INTEGER, PARAMETER :: q=8
END MODULE prec

MODULE MOD_FIT
  USE prec

  INTEGER, PARAMETER :: NO_NI=200
  TYPE spec
    ! source of fitting
    INTEGER NW
    COMPLEX(q), POINTER :: W(:),G(:)

    ! how spectrum is parametrized
    INTEGER NO_NM        ! continuous points labeled as 1,2,3,...,NO_NM
    REAL(q), ALLOCATABLE :: O_N(:),O_D(:)        ! frequency
    REAL(q), POINTER     :: A_N(:),B_N(:),A_D(:) ! A(Omega)

  END TYPE
  TYPE(spec) SMP

  INTERFACE
    SUBROUTINE NNLS_CMPLX(SMP,RES,RES_V)
      IMPLICIT NONE
      TYPE(spec), INTENT(IN) :: SMP
      REAL(q), INTENT(OUT) :: RES
      COMPLEX(q), OPTIONAL, INTENT(OUT) :: RES_V(SMP%HN)
    END SUBROUTINE NNLS_CMPLX      
  END INTERFACE

CONTAINS

  SUBROUTINE NNLS_CMPLX(SMP,RES,RES_V)
    IMPLICIT NONE
    TYPE(spec) :: SMP
    REAL(q) :: RES
    COMPLEX(q), OPTIONAL :: RES_V(*)

    RES=0
    IF(PRESENT(RES_V)) RES_V(1)=0

  END SUBROUTINE NNLS_CMPLX      

END MODULE MOD_FIT

PROGRAM MAIN
  USE prec; USE MOD_FIT
  REAL(q) PK_RES
  COMPLEX(q) RES_V(4)

  CALL NNLS_CMPLX(SMP,PK_RES,RES_V)

END
bsmile
  • 59
  • 8
  • 2
    Why did you delete the previous version of the question with many useful comments? – Vladimir F Героям слава Jun 03 '15 at 16:58
  • Sorry, I was told by the administrator to delete the previous version and give a more complete description of my question. So I did it. I do think there are many useful comments and I tried them out. – bsmile Jun 03 '15 at 17:20
  • 1
    No, you were told to delete your non-sense answer and to incorporate that information into your question by editing it, not deleting it and posting a new one. – Vladimir F Героям слава Jun 03 '15 at 17:23
  • There are essentially only two cases where we need to write an interface block manually: (1) When the subroutine to be called is defined (written) outside a Fortran module, and (2) when a subroutine name appears as a dummy argument (e.g., to pass a function to an optimization program). The following page may also be useful. http://stackoverflow.com/questions/19781217/which-is-the-diffeence-between-an-interface-block-and-a-module-procedure-in-fort?rq=1 – roygvib Jun 03 '15 at 18:18
  • 1
    From @bsmile 's deleted answer (should have been a comment): " The issue was finally identified (I would think so). It is not related to subroutine using optional dummy argument, but instead is related to uninitialized value for a variable printed on the screen (but not used in the code). intel's ifort helps me to identify the issue. GNU's gfortran generates code keeping running although it clearly messed up with memory usage at later irrelevant locations." For this reason I vote to close this question as solved by means unlikely to help future visitors. – Vladimir F Героям слава Jun 05 '15 at 09:30

1 Answers1

1

Having an explicit interface means that the compiler knows how the called subroutine or function (procedure) looks like.

Explicit interfaces should not be normally provided by an interface block, that is the thing:

interface
...
end interface

but by placing the procedures in modules instead.

You definitely cannot use an interface block for a module procedure (a procedure placed inside a module). Interface block tells that there is some external procedure somewhere with the properties you declare in the interface block. But your procedure is not external, it is in a module.

Just remove the interface block and it should work.

Just a suggestion: use small caps and indentation in your code. It is very difficult to read as it stands.

To explain the actual error message: As francescalus comments, interface blocks have a separate scope. If they are placed in a module, they do not see the other contents of the module. That's why the compiler complains it does not know what spec and q are.

  • And even if the interface block were allowed, without the `import` statement it would be wrong (which explains the compiler error quoted). [The error message regarding the inappropriateness of the interface was missed from the question.] – francescalus Jun 03 '15 at 17:13
  • Actually, I removed the interface block and indeed it compiles and works to some point ---- the results can be wrong unless I give it a lot of debugging statements. I don't know how to describe the error, which is quite ellusive. My experience tells me that I most likely need to use an interface to help. I am a fortran 77 guy and am not familiar with the usage of interface. Thanks for further help! – bsmile Jun 03 '15 at 17:26
  • No, forget interface blocks for now and use modules. Interface blocks are useful for different, more advanced stuff. – Vladimir F Героям слава Jun 03 '15 at 17:27
  • @bsmile VladimirF suggests not moving the interface block to other places, but remove the interface block literally as a whole. The compiler can understand the interface of a subroutine if it exists in a module (in other words, the user do not need to supply it manually). – roygvib Jun 03 '15 at 17:32
  • @bsmile You do indeed need interfaces to help with things. It's just that, as comments and this answer attempt to explain: interfaces and interface blocks are not the same thing. An interface block provides an explicit interface, but is not the only way. A procedure visible through module use association has an explicit interface. – francescalus Jun 03 '15 at 17:32
  • I did have tried removing the interface as a whole as I explained above. The compilation is successful, but the execution result is unpredictable. I think it is something related to the optional dummy variable passed over in the NNLS_CMPLX subroutine. Have you ever met with this issue? How do you normally resolve it? I had resolved it with interface block before, but this time interface does not compile. Sorry for using cap letter in the code, I am used to the VASP coding style. – bsmile Jun 03 '15 at 18:19
  • Oh VASP :D (a nice plane-wave DFT code?) Btw, if a subroutine is written inside a module, there is no need to write an interface block manually even if the routine has optional arguments or arguments with any advanced features. On the other hand, if the routine is written outside a module, we definitely need to write an interface block to tell the compiler how to call them. (If only F77 features are used in the arguments, one could call them without interface blocks, but it is safer to write them.) – roygvib Jun 03 '15 at 18:28
  • @bsmile Also note that in the latter case above (to call a routine outside a module), your definition of an interface block must match precisely with the actual definition of a subroutine. Otherwise, the compiler believes your interface block, pass arguments in that way, and may result in unexpected behaviors. Unfortunately, there is no good mechanism to guarantee this consistency (in contrast to header files in C/C++), so just we need to check the consistency manually. – roygvib Jun 03 '15 at 18:33
  • It is indeed that VASP. Actually, as you see from the sample code I provided, the called subroutine with an optional variable is within a module which is "USE"d in the main. I don't understand why it sometimes does not work. – bsmile Jun 03 '15 at 19:14
  • In that case start a new question about internals of this subroutine and you must show the full relevant code and you must explain how it should work and what it does for you instead. – Vladimir F Героям слава Jun 03 '15 at 19:24
  • @bsmile Yeah, it looks like a strange behavior.... Btw, if you attach "intent(out)" such that `COMPLEX(q), OPTIONAL, INTENT(OUT) :: RES_V(SMP%HN)`, then the compiler might use RES_V(*) for its own, so it is safer to delete intent(out) if you do not define all the elements of an optional argument (array). In my case, I only use intent(in), which is similar to `const` in other languages, and never use intent(out) nor intent(inout). Please see this page also http://www.cs.rpi.edu/~szymansk/OOF90/bugs.html#2 – roygvib Jun 03 '15 at 19:33
  • I also agree with Vladimir; if you remove interface blocks and still get a strange behavior, it should be useful to make a further Question (or edit the above Question) with updated full codes + error messages :) – roygvib Jun 03 '15 at 19:45
  • @bsmile One more (potentially relevant) pitfall: http://www.cs.rpi.edu/~szymansk/OOF90/bugs.html#8 http://www.cs.rpi.edu/~szymansk/OOF90/bugs.html#9 – roygvib Jun 03 '15 at 19:56