How to run Fortran file with too many subroutine and function?

The main program with too many subroutines and functions is existed. Some of the subroutines and functions also use subroutines, functions, and modules. I decided to write them in independent files due to clarity in the main program. Then I created an independent file as a module to collect them with the include command.

Now I have one main program and one independent file for the module. I compile the program but it shows an error. The error is about missing mentioned subroutine in the above independent file.

My question in general is: If you have a program with one main program and a number of sub-programs (subroutines, functions, and modules), which also they have sub-programs, what method do you use to assemble and run it?

I write my code in PLATO as a fortran95.

I will appreciate any comments that give me a little help and forgive me for writing shortcomings

What is the problem?

Consider the following structure. On the independent file as the main program:

MAIN PROGRAM

CALL A

CALL B

CALL C

END PROGRAM

On the independent file as the subroutine A:

SUBROUTINE A

...

END SUBROUTINE 

On the independent file as the subroutine B:

SUBROUTINE B
    
CALL B1

CALL B2
    
END SUBROUTINE 
---------------
SUBROUTINE B1
...
END SUBROUTINE
--------------
FUNCTION B2
...
END FUNCTION 

On the independent file as the subroutine C:

SUBROUTINE C
        
USE C1
    
CALL C2
        
END SUBROUTINE 
---------------
SUBROUTINE C1
...
END SUBROUTINE

On the independent file as the module C1:

MODULE C1

CONTAINS

SUBROUTINE C1-1
SUBROUTINE C1-2
SUBROUTINE C1-3
...
END MODULE

What I did:

I created an independent file as Module:

    MODUL D

    CONTAINS

    INCLUDE A.F95
    INCLUDE B.F95
    INCLUDE C.F95

END MODULE

Consequently, for the main program:

MAIN PROGRAM
    
USE D

CALL A
    
CALL B
    
CALL C
    
END PROGRAM

What is the Error:

Warning: Missing A (File address), Missing B (File address), Missing C (File address)

How do you compile it? Can show us the Makefile?

In your Module D, you forgot a CONTAINS line before the INCLUDEs. I would also add an IMPLICIT NONE before the CONNTAINS.

1 Like

Welcome @VOLCANIC_9 ,

Have you written INCLUDE A.F95 or INCLUDE "A.F95" ?

And although the INCLUDE statement can still be convenient in some situations, the recommended way in modern Fortran is to use modules. You can define modules module_A, module_B, module_C, one per file, and then wrote something like:

MAIN PROGRAM
USE module_A
USE module_B
USE module_C

CALL A
CALL B
CALL C
END PROGRAM

For a program using modules, you should compile the source file with a module before compiling any source file that USEs the module. What I do is create a text file listing the proper order of source files

a.f90
b.f90
main.f90

and then run a Python script that creates a make file, given the list of sources. As others have said, you should not need to use INCLUDE. Each of my source files contains either a module or the main program. Related functions and subroutines should be placed in a single module.

Question for the group – suppose a set of source files can be compiled to create an executable, but you forget the order the files should be compiled. Is there a tool to figure that out?

1 Like

Thank you for your comment.
I edited the code as following:
“Include” command is added at the first main program for the module “D”.
A “public” command is added in module “D” to introduce the sub-program.
Now I have two main problems:

  1. Nesting error. This refers to module “D” and it says the module is not terminated.
  2. For some of mentioned sub-program in the “public” command of module “D” (not every one of them) there is an error that says: “A” must appear in type declaration because implicit none.

It’s better in general to consider the dependencies between files rather than a serial compilation order since this allows parallel compilation where possible. I’ve never used it, but there is the fdepend tool for generating Makefile dependencies.

This very problem, of compiling dependencies in the correct order (and in parallel), is handled automatically by fpm (though there is no method currently of dumping the dependency information or serial build order).

1 Like

Thank you for your comment.

The “contains” command was mentioned but I forget to write it.

I edited the code as following:

“Include” command is added at the first main program for the module “D”.
A “public” command is added in module “D” to introduce the sub-program.

Now I have two main problems:

  1. Nesting error. This refers to module “D” and it says the module is not terminated.
  2. For some of mentioned sub-program in the “public” command of module “D” (not every one of them) there is an error that says: “A” must appear in type declaration because implicit none.

It’s not helping when you show us code that is not what you are actually using. To progress, you would need to at least show us the exact command you are using and the exact error message the compiler gives you.

My question in general is: If you have a program with one main program and a number of sub-programs (subroutines, functions, and modules), which also they have sub-programs, what method do you use to assemble and run it?

First, some terminology: what you informally call “sub-programs” (in the first occurrence above) are actually called “program units”. Formally, “subprogram” refers to functions and subroutines (and that seems to be the meaning of your second use of sub-program above). “Subprograms” are either external, or module (CONTAINed in a module or submodule), or internal (CONTAINed in a main program, an external subprogram or a module subprogram).

Program units can all be in the same source file, or they can be in separate source files. In the latter case, you would have to figure out the order of compilation (with help from tools provided by your compiler installation, perhaps). Program units are the main program, an external subprogram, a module or submodule and the (obsolescent and deprecated) block data.

I think your question then becomes, how do I move from external subprograms to module subprograms or internal subprograms. The answer depends on the use you make of the subprograms.

A subprogram that is only likely to be used in one place is a good candidate for an internal subprogram. Typically, a main program could be “call sub1(); call sub2(); call sub3()”. In that case, making sub1/sub2/sub3 internal to the main program makes sense. BUT: you must make sure that IMPLICIT NONE is already used in the externals sub1/sub2/sub3. This is because when you move them into a CONTAINS of the main, any variables not explicitly declared get “host-associated” with variables in the main program and you do NOT want that. If they compile happily with IMPLICIT NONE as external subprograms, then they could just be put in a CONTAINS of the main. You can do that with an INCLUDE “sub1_source.f90” or by copy-paste of the actual source lines. You will not be able to do this, however, if the external subprogram already CONTAINS subprograms (because you are not allowed two levels of CONTAINS in a main or three levels in a module). But you can “lift” internal subprograms to be “alongside” their former hosts provided you are careful with the host-associations that will now be completely different.That might mean a complete re-write.

An external subprogram that is used in many places in the source is a good candidate for becoming a module subprogram. Make up a name for the module, for example sub1_m. Then “Module sub1_m; contains; subroutine sub1() ; …body…; end subroutine; end module”. Wherever you “call sub1()”, you will need a “use sub1_m, only:sub1”. This will allow the compiler to check that you are calling sub1 in a sensible manner. You may find that the compiler now rejects calls that were previously waved through. This is a “GOOD THING”.

1 Like

From the way you describe your questions and also the replies above, I think some of the replies might be a bit more advanced to your question. (Well, ignore this reply if I was wrong!) If the Plato you mentioned is this Plato, you are using an IDE with an integrated Fortran compiler. I’ve never used Plato before, but at least with Visual Studio (which is also an IDE) and Intel Fortran compiler, the IDE will link all the source codes for you and you shouldn’t need to worry about how the source codes are linked (in most cases).

If you want to manually handle the process of compilation, what you need is a build tool. Start with make, cmake, or meson (The latter two are actually kinda different from the first). For very small project you can even write a bash script.

Again, IGNORE me if I misinterpret your question!

@VOLCANIC_9 ,

Welcome to this forum!

Can we assume you’ve a thread going at comp.lang.fortran as well?
https://groups.google.com/g/comp.lang.fortran/c/iwHXOVHOwF0/m/HLcx13wWDgAJ

You ask in one of your posts, “this is my first pro-code so I don’t know what is it and how I can write it.
Can you provide some keywords or links that help me what is the above line”

Which suggests you’re starting off with what’s currently a compiler-based language, Fortran - is that correct?

Note you’ve received a bunch of great replies on both the forums, but it can all come across as rather confusing or inadequate if you’re just staring off. What may help you is if you can spend some time by yourself to go through some step-by-step how-to tutorials.

If text-based information source is ok, you can consider the information packet by Ed Jorgenson at UNLV whose content combines nicely an introduction to Fortran in conjunction with its use with a compiler such as gfortran:
http://www.egr.unlv.edu/~ed/fortran.html

If you prefer a more visual engagement, you may like the tutorials at YouTube, particularly those on gfortran with Code::Blocks integrated development environment (IDE) which, via a user interface (UI( in the form of an IDE, can make it much more of an interactive experience that you may find easier to work with:

All the best,

Thanks for your comment.

I edited the post and it seems it works properly.

Thanks for your comment and feel free.
I want to know: is Geany with Mingw also linked the source code:?
(for some reason I forced to change my IDE and compiler)

I just tested a simple project on Geany with Mingw and answer is NO, you will have to customize the settings to link source codes correctly. My personal programming environment for Fortran on Windows 10 is WSL2 + VSCode, but still it needs tweaking and the performance is slower than a native Linux environment.

And in my opinion, it’s best learning to compile a project using command line. Once you have understood how the compiler works in command line, you will understand better how to set the same things in an IDE, if you prefer that way.

Graphical user interfaces hide what is underneath. In my opinion, it’s not a good thing for learning.

5 Likes

Thank you so much. I find something that works for me (At least I think).