Can't compile with module and main program in same file - fortran

I am trying to make use of a module that is in the same file as my main program. However, I cannot get it to work. Does Fortran allow a module to be contained in the same file as the main program or must it be in a separate file? Here is a simple version of my code:
main program
use my_module
call my_subroutine()
end program main
module my_module
contains
subroutine my_subroutine()
print *, "Hello World!"
end subroutine my_subroutine
end module my_module
When I try to compile this file I get:
Fatal Error: Can't open module file 'my_module.mod' for reading at (1): No such file or directory

Yes, Fortran does allow modules to be contained in the same file as the main program. However, modules must be written before the main program:
module my_module
contains
subroutine my_subroutine()
print *, "Hello World!"
end subroutine my_subroutine
end module my_module
program main
use my_module
call my_subroutine()
end program main

Related

Changing the status of a temporary file with the open statement in gfortran

I am using an old Fortran code and I have running it using g77-3.3 in an old OS. Since this version of the compiler no longer comes with most Linux distributions I tried using gfortran (4.9.2), and I am facing this small problem.
This codes uses temporary files. It writes to this file and then at a certain point it changes the status of the file to scratch, like in the following example:
PROGRAM testopenfile
IMPLICIT NONE
WRITE(8,*)'fdsasfd'
OPEN(8,STATUS='SCRATCH')
CLOSE(8)
END PROGRAM
This piece of code works with the g77 compiler, but when I run it with gfortran I get the message:
At line 4 of file testopenfile.f (unit = 8, file = 'fort.8')
Fortran runtime error: Cannot change STATUS paramter in OPEN statement.
Has this way of setting temporary files changed in gfortran? Am I doing something wrong? Could this be a bug in this version of gfortran?
If you write to unit 8 before opening the file, you are in fact writing to a file called fort.8, see here. Apparently, this file is still open at unit 8 when you try to attach the scratch file to it.
You can solve this by opening the scratch file before writing to the unit:
PROGRAM testopenfile
IMPLICIT NONE
OPEN(8,STATUS='SCRATCH')
WRITE(8,*)'fdsasfd'
CLOSE(8)
END PROGRAM
or by using a different unit.
Chapter C.6.3 ("OPEN statement (9.5.6)") in the Fortran 2008 Standard treats this case and has an example which looks just like your code. It states that this "example is invalid because it attempts to change the value of the STATUS= specifier."
If you want to delete the file on closing, you can also do
PROGRAM testopenfile
IMPLICIT NONE
WRITE(8,*)'fdsasfd'
CLOSE(8,status='DELETE')
END PROGRAM

GFortran and CodeBlocks issue with Modules and Multiple Files

I am working with GFortran and CodeBlocks but I'm having an issue about Modules and Multiple files.
i keep getting this error:
Fatal Error: Can't open module file 'mesh.mod' for reading at (1): No such file or directory
For some reason, GFortran is not building the 'mesh.mod' file.
This problem does not occur when I put all the code in a single .f90 file.
Bellow is an example of code that this error happens.
main.f90
MODULE MESH
IMPLICIT NONE
INTEGER :: IMAX,JMAX,NMAX
REAL(8), ALLOCATABLE :: XD(:),YD(:),FX(:,:),FY(:,:)
REAL(8) :: PI,E,DX,DY,H,L,RHO,MU
PARAMETER (PI = ACOS(-1.D0))
PARAMETER (E = 2.718)
END MODULE MESH
!**************************************************************
program Cavity
Use Mesh
implicit none
Real(8), Allocatable :: func(:)
Real(8) :: Der,DfDx
integer :: i
IMAX=10
DX=1./10
Allocate(xd(IMAX),func(IMAX))
Do i=1,IMAX
xd(i)=i*DX
End Do
Do i=1,IMAX
func(i) = xd(i)**2
End Do
Der=Dfdx(func,2)
Write(*,*) Der
End program Cavity
Derivatives.f90
Real(8) Function DfDx(f,i)
Use Mesh
implicit none
Real(8) :: f(1:Imax)
integer :: i
DfDx=(f(i+1)-f(i-1))/(2d0*dx)
return
end function DfDx
When I use console command line compilation instead of CodeBlocks interface I already solved this problem (Compiling Multiple Files with modules) but I'm still getting this problem with CodeBlocks.
Does anyone know how to solve this issue?
Assuming what you have written is how your code is, then it appears that the problem is that the module mesh is inside the main program and not a separate file. You should have three files: Mesh.f90, Derivatives.f90 and Main.f90.
Mesh.f90 is exactly as you have it,
module Mesh
implicit none
integer :: IMAX,JMAX,NMAX
real(8), allocatable :: XD(:),YD(:),FX(:,:),FY(:,:)
real(8) :: PI,E,DX,DY,H,L,RHO,MU
parameter (PI = ACOS(-1.D0))
parameter (E = 2.718)
end module Mesh
Derivatives.f90 should be written as another module, using contains:
module Derivatives
use mesh
contains
real(8) function dfdx(f,i)
real(8) :: f(i:imax)
integer :: i
DfDx=(f(i+1)-f(i-1))/(2d0*dx)
end function dfdx
end module Derivatives
and the Main.f90 will then use both modules. Note that I had to eliminate the variable DfDx; this is because it conflicts with the function DfDx in module Derivatives
program Cavity
Use Mesh
use Derivatives
implicit none
Real(8), Allocatable :: func(:)
Real(8) :: Der
integer :: i
IMAX=10
DX=1./10
Allocate(xd(IMAX),func(IMAX))
Do i=1,IMAX
xd(i)=i*DX
End Do
Do i=1,IMAX
func(i) = xd(i)**2
End Do
Der=Dfdx(func,2)
Write(*,*) Der
End program Cavity
I do not know how CodeBlocks works, but I would presume it lets you choose the compilation order. If that is the case, you should compile Mesh.f90 first, then Derivatives.f90, then compile Main.f90 before linking them to an executable.
When I compiled & linked them, I got an answer of 0.200000002980232; hopefully that links up to what you have as well.
On codeblock, you may go to Project properties > Build targets
Then select the file you want to build first (say mod.f90).
In the "Selected file properties" go to "Build"
Here,change the priority weight. Lower weight implies the file will be built first.
The problem is that in CodeBlocks "projects are built in the order of appearence, from top to bottom" (CodeBlocks Wiki), in other words, the files are compiled alphabetically.
Which means that in my case, Derivatives.f90 was being compiled before than Main.f90 causing the error.
A way to circumvent the problem is to set only the Main.f90 file as build target in CodeBlocks:
Menu Project/Properties...
In Build Target Files at the tab Build targets check only Main.f90
And use the command Include 'File_Name.f90' inside the Main.f90 code to include the other f90 files for compilation in the right order.

OCaml - compiling a program as a library

I have an OCaml program(with a main method - it generates an executable) and I want to use it as a library.
I was compiling my program like this: ocamlc -I someDir -g -unsafe lotsOfCmoFiles -o outputFile and the program works fine.
Now I'm removing the line that makes it an executable(something like let _ = ...) and adding -a parameter to compile command: ocamlc -a -I someDir -g -unsafe lotsOfCmoFiles -o outputFile.cma
But somehow I can't load generated .cma file with ocamltop and ocamlbrowser shows an empty list. When I try to load from ocamltop:
# #load "outputFile.cma";;
Error: Reference to undefined global `Xyz'
And I'm 100% sure that xyz.cmo is included in lotsOfCmoFiles.
Am I giving some parameter wrong while compiling? Or else, what should I do to load my program in ocamltop ? (I'll use this library in another program, I'm giving ocamltop outputs as an example)
Any helps will be appreciated.
EDIT: So I can finally managed to compile and load it thanks to #cago, now I can load my library, and when I don't remove the main let _ = ... line it's automatically run when I load the .cma.
But I still can't open any modules. Strangely, this doesn't raise an exception
open Main
but then when I call a function from module Main:
# someFun;;
Error: Reference to undefined global `Main'
and ocamlbrowse still shows an empty list. now why is that?
EDIT2: I realized open Main doesn't fail because I have a Main module in the same folder(even though I didn't explicitly load it). If I move my .cma file somewhere else and load it, it works(ie. main function runs automatically), but now I can't open any modules even though ocamlobjinfo shows the modules.
EDIT3: -I doesn't help:
$ ocaml
OCaml version 4.00.1
# #load "lib.cma";;
ok
# open Lib;;
Error: Unbound module Lib
#
$ ocaml -I libFolder
OCaml version 4.00.1
# #load "toylib.cma";;
ok
# open Lib;;
# fun;;
Error: Reference to undefined global `Lib'
Some of the cmo in your lotsOfCmoFiles need to know the module Xyz. You need to take care of the dependency between your cmo files.
For example:
toto.ml:
let x = "toto"
titi.ml:
let y = Toto.x ^ " titi"
ocamlc -c toto.ml
ocamlc -c titi.ml
ocamlc -a titi.cmo toto.cmo -o lib.cma (* here is the probleme *)
# #load "lib.cma"
Error: Reference to undefined global `Toto'
Because titi depends on toto so you need to change the order of cmos:
ocamlc -a toto.cmo titi.cmo -o lib.cma
# #load "lib.cma"
# Titi.y;;
- : string = "toto titi"
EDIT:
If your cma is in a subdirectory for example, when you call ocaml you need to specify the path:
ocaml -I subdir/ (* subdir which contains lib.cma *)
# #load "lib.cma"
# Toto.x;;
- : string = "toto"
TL;DR: Make sure you don't have any top-level side-effects in the
I was running into this same kind of trouble. My project would build fine, most modules were available, but there was one module that kept triggering Reference to undefined global. But it was clear that the module was visible to the system: it was showing up in utop's autocomplete list, along with all of it's values, and I could reference it and import it into other modules.
The problem turned out to be an uncaught exception that was being thrown when that module was loaded. The exception was due to an attempt to load a non-existing file. It wouldn't cause problems during complication, but when the module was actually loaded it was breaking and the exception was being swallowed somewhere before I ever saw it.

No output after compiling and executing the code

I'm new to fortran and i'm trying to execute this as an output.
program write2file
implicit none
! open file
open (10, file='output_file.txt', status='unknown')
! write to file
write(10, *) 'Hello World!'
! close file
close(10)
end program write2file
I'm running it on Linux and I have tried to use this statement to compile and execute the output, but unfortunately, I wasn't able to get the 'output_file.txt'
Does anyone know what's wrong?
This is a comment rather than an answer but I feel in need of better formatting. After you execute the command
ifort -o output hi.f90
you should have an executable called output in your current working directory. To execute that executable execute the command
./output
which will, if you are successful, write the output you want to wherever the current version of the program directs it.
Reading your comments makes me suspect that you think the command
ifort -o output hi.f90
ought to execute your program and cause the creation of the output requested. But that command just compiles your sources (in the file hi.f90) into the executable called ouptut. Is this the first time you've used a compiler ?

How can I solve Fortran runtime error: End of file?

I am using Codeblock 13.12. My file is not readable. and getting the runtime error
program asd
implicit none
integer :: x
open(unit = 2, file = "text.txt")
read(2,*)x
write(*,*)x
end program
and my text.txt file is :
1
I've seen many answers, but none of them worked for my code
Your program is just fine. As a matter of fact, even if the first line is not properly terminated, gfortran will take the EOF as the EOL and still work.
Your problem is you are working in the IDE CodeBlock. The IDE does not run the program in your working directory so the file text.txt is not where the program is running, hence the end of file error.
Check out this post Codeblock working directory which will guide you to solving your problem.