using Fortran Module from external files - module

I would like to call subroutines contained in a module. the module is saved in a separate file with my_mod.f95 filename.
module calc_mean
! this module contains two subroutines
implicit none
public :: calc_sum
public :: mean
contains
subroutine calc_sum(x,n,s)
! this subroutine calculates sum of elements of a vector
! x the vector
! n size of the vector
! s sum of elements of x
integer, intent(in):: n
real, intent(in):: x(n)
integer :: i
real, intent(out):: s
s=0
do i=1,n
s=s+x(i)
end do
end subroutine calc_sum
!
!
!
subroutine mean(x,n,xav)
! this subroutine calculates the mean of a vector
! x the vector
! n size of the vector
! xav mean of x
integer, intent(in):: n
real, intent(in):: x(n)
real, intent(out):: xav
real :: s
!
!
call calc_sum(x,n,s)
xav=s/n
end subroutine mean
end module calc_mean
I have the main program saved in a different file with 'my_program.f95'
program find_mean
! this program calculates mean of a vector
use calc_mean
implicit none
! read the vector from a file
integer, parameter ::n=200
integer :: un, ierror
character (len=25):: filename
real :: x(n), xav
un=30
filename='randn.txt'
!
OPEN (UNIT=un, FILE=filename, STATUS='OLD', ACTION='READ', IOSTAT=ierror)
read(un,*) x !
!
call mean(x,n,xav)
write (*,100) xav
100 format ('mean of x is', f15.8)
end program find_mean
when I compile the main program with geany, I got the following error message. Please, help me!
**
/usr/bin/ld: /tmp/cctnlPMO.o: in function MAIN__': my_program.f08:(.text+0x1e1): undefined reference to __calc_mean_MOD_mean'
collect2: error: ld returned 1 exit status
**
When I save both the main program and the module to the same file and run it, everything is fine.

Related

Read(u=UNIT,*) reads just half the file in fortran

so I'm trying to make a Fortran subroutine that reads a matrix (or a tensor I guess) of size 125x125x125 from a file that I create in another subroutine, but for some reason it doesn't work. I have successfully done it using almost the same program but for a different size of matrix (70x200x70) and for some reason when I change the size of the arrays and a couple of other things to fit the new data, the program reads just half the data file and throws an error that says At line 133 of file Busqueda.f90 (unit = 2, file = 'test2.txt') Fortran runtime error: End of file. So my working code is:
Subroutine DataSorting(datasort,indexsort,datosden,datostemp)
use globals
implicit None
real*8, dimension(70,200,70) :: datosdentemp
real*8, dimension(70,200,70), intent(out) :: datostemp, datosden
real*8, dimension(980000), intent(out) :: datasort
integer,dimension(3,980000),intent(out) :: indexsort
integer, dimension(3) :: Result
integer :: i
rewind(2)
read(2,*) datosden
datosdentemp = datosden
rewind(3)
read(3,*) datostemp
do i = 1, 10
Result = MAXLOC(datosdentemp)
datasort(i) = datosden(Result(1),Result(2),Result(3))
indexsort(1,i) = Result(1)
indexsort(2,i) = Result(2)
indexsort(3,i) = Result(3)
datosdentemp(Result(1),Result(2),Result(3)) = 0
end do
End Subroutine DataSorting
And the code that dont work is:
Subroutine DataSorting(datasort,indexsort,datosden,datostemp)
use globals
implicit None
real*8, dimension(125,125,125) :: datosdentemp
real*8, dimension(125,125,125), intent(out) :: datostemp, datosden
real*8, dimension(1953125), intent(out) :: datasort
integer,dimension(3,1953125),intent(out) :: indexsort
integer, dimension(3) :: Result
integer :: i
rewind(2)
read(2,*) datosden
datosdentemp = datosden
rewind(3)
read(3,*) datostemp
do i = 1, 10
Result = MAXLOC(datosdentemp)
datasort(i) = datosden(Result(1),Result(2),Result(3))
indexsort(1,i) = Result(1)
indexsort(2,i) = Result(2)
indexsort(3,i) = Result(3)
datosdentemp(Result(1),Result(2),Result(3)) = 0
end do
End Subroutine DataSorting
The files from where I'm reading the data just have the data arranged in 125 columns and 15625 rows in the case of the non-working program, and in 70 columns and 14000 rows for the working one, and the files are just that, I mean they are really structured that way in both cases. I was using scratch files for the files 2 and 3, and change them to '.txt' files to see if there was a problem with the input file, but no. Then I build a new file and did the reading with a do-loop, to see if that was the problem, but no, but at least that helped me to realize that the code was reading exactly half of 15625, but i don't know why this is happening, I'm new to fortran, my thesis advisor told me to do this code in Fortran 'cause the amount of data that have to handle will make my Julia code way to slow, so honestly any help will be much appreciated.

Fortran READ into derived type not working with gfortran (Fortran runtime error: End of file)

I have a derived type in Fortran and I need to read values from a text file into that type. My problem is that my code is working fine with the Intel Fortran compiler as well as the NAG Fortran compiler, but GFortran exits with an error. The minimal working example is below.
Module my_mod
Type T
Real :: a
End Type T
Interface Read (Formatted)
Module Procedure read_T
End Interface
Contains
Subroutine read_T(var, unit, iotype, v_list, iostat, iomsg)
Class (T), Intent (Inout) :: var
Integer, Intent (In) :: unit
Character (*), Intent (In) :: iotype
Integer, Intent (In) :: v_list(:)
Integer, Intent (Out) :: iostat
Character (*), Intent (Inout) :: iomsg
Read (unit, *, iostat=iostat, iomsg=iomsg) var%a
End Subroutine
End Module my_mod
Program main
Use my_mod
Implicit None
Type(T) :: x
Type(T) :: y
Open(unit=20, file='data.txt', action='read')
Read(20, *) x ! Here GFortran fails because it somehow reaches EOF
Write(*, *) x
Read(20, *) y
Write(*, *) y
End Program main
with the data.txt file:
1.0
2.0
With GFortran I get the error
At line 30 of file test.f90 (unit = 20, file = 'data.txt')
Fortran runtime error: End of file
Error termination. Backtrace:
#0 0x7f27a76fef2f in finalize_transfer
at ../.././libgfortran/io/transfer.c:4175
#1 0x400aca in ???
#2 0x400b86 in ???
#3 0x7f27a69a8504 in ???
#4 0x4007e8 in ???
#5 0xffffffffffffffff in ???
One thing that works is to replace the Read statements as follows
Read(20, fmt='(DT)', advance='no') x ! Works with all compilers :)
Write(*, *) x
Read(20, fmt='(DT)', advance='no') y ! Works with all compilers :)
Write(*, *) y
So my question .. is it possible to get the same behaviour in GFortran without fmt='(DT)', advance='no'?
And who has the correct behavior? GFortran or Intel Fortran and NAG Fortran?
Thanks for any help,
Simon

Use of selected_real_kind in a module [duplicate]

So I am doing 2 modules which are linking to the main program. The first one has all the variables defined in it and the second one is with the functions.
Module1:
module zmienne
implicit none
integer, parameter :: ngauss = 8
integer, parameter :: out_unit=1000
integer, parameter :: out_unit1=1001
integer, parameter :: out_unit2=1002, out_unit3=1003
real(10), parameter :: error=0.000001
real(10):: total_calka, division,tot_old,blad
real(10),parameter:: intrange=7.0
real(10),dimension(ngauss),parameter::xx=(/-0.9602898565d0,&
-0.7966664774d0,-0.5255324099d0,-0.1834346425d0,&
0.1834346425d0,0.5255324099d0,0.7966664774d0,0.9602898565d0/)
real(10),Dimension(ngauss),parameter::ww=(/0.1012285363d0,&
0.2223810345d0,0.3137066459d0,0.3626837834d0,&
0.3626837834d0,0.3137066459d0,0.2223810345d0,0.1012285363d0/)
real(10) :: r, u, r6, tempred, f, r2, r1, calka,beta
real(10) :: inte
real :: start, finish
integer:: i,j,irange
real(10),dimension(ngauss)::x,w,integrand
end module zmienne
Module2
module in
implicit none
contains
real(10) function inte(y,beta,r2,r1)
real(kind=10)::r,beta,r6,r2,r1,u,y
r=(r2-r1)*y+r1
r6=(1.0/r)**6
u=beta*r6*(r6-1.0d0)
if (u>100.d0) then
inte=-1.0d0
else
inte=exp(-u)-1.d0
endif
inte=r*r*inte
end function
end module in
And while im calling them like that:
use zmienne; use in
I am getting following error:
Name 'inte' at (1) is an ambiguous reference to 'inte' from module 'zmienne'
I've deleted "inte" in the module1 but now I am getting following error:
irange=inte(intrange/division)
1
Error: Missing actual argument for argument 'beta' at (1)
The main program code is:
program wykres
use zmienne; use in
implicit none
open(unit=out_unit, file='wykresik.dat', action='write', status='replace')
open(unit=out_unit1, file='wykresik1.dat', action='write')
open(unit=out_unit2, file='wykresik2.dat', action='write')
open(out_unit3, file='wykresik3.dat', action='write')
! the gaussian points (xx) and weights (ww) are for the [-1,1] interval
! for [0,1] interval we have (vector instr.)
x=0.5d0*(xx+1.0d0)
w=0.5d0*ww
! plots
tempred = 1.0
call cpu_time(start)
do i=1,1000
r=float(i)*0.01
r6=(1.0/r)**6
u=beta*r6*(r6-1.0)
f=exp(-u/tempred)-1.0
write(out_unit,*) r, u
write(out_unit1,*)r, f
write(out_unit2,*)r, r*r*f
end do
call cpu_time(finish)
print '("Time = ",f6.3," seconds.")',finish-start
! end of plots
! integration 1
calka=0.0
r1=0.0
r2=0.5
do i=1,ngauss
r=(r2-r1)*x(i)+r1
r6=(1.0/r)**6
u=beta*r6*(r6-1.0d0)
! check for underflows
if (u>100.d0) then
f=-1.0d0
else
f=exp(-u)-1.d0
endif
! the array integrand is introduced in order to perform vector calculations below
integrand(i)=r*r*f
calka=calka+integrand(i)*w(i)
enddo
calka=calka*(r2-r1)
write(*,*)calka
! end of integration
! integration 2
calka=0.0
do i=1,ngauss
integrand(i)=inte(x(i),beta,r2,r1)
calka=calka+integrand(i)*w(i)
enddo
calka=calka*(r2-r1)
! end of integration 2
write(*,*)calka
! vector integration and analytical result
write(*,*)sum(integrand*w*(r2-r1)),-(0.5**3)/3.0
!**************************************************************
! tot_calka - the sum of integrals all integration ranges
! dividion the initial length of the integration intervals
! tot_old - we will compare the results fro two consecutive divisions.
! at the beginning we assume any big number
! blad - the difference between two consecutive integrations,
! at the beginning we assume any big number
! error - assumed precission, parameter, it is necassary for
! performing do-while loop
total_calka=0.0
division=0.5
tot_old=10000.0
blad=10000.0
do while (blad>error)
! intrange - the upper integration limit, it should be estimated
! analysing the plot of the Mayer function. Here - 7.
! irange = the number of subintegrals we have to calculate
irange=inte(intrange/division)
total_calka=-(0.5**3)/3.0
! the analytical result for the integration range [0,0.5]
! the loop over all the intervals, for each of them we calculate
! lower and upper limits, r1 and r2
do j=1,irange
r1=0.5+(j-1)*division
r2=r1+division
calka=0.0
! the integral for a given interval
do i=1,ngauss
integrand(i)=inte(x(i),beta,r2,r1)
calka=calka+integrand(i)*w(i)
enddo
total_calka=total_calka+calka*(r2-r1)
enddo
! aux. output: number of subintervals, old and new integrals
write(*,*) irange,division,tot_old,total_calka
division=division/2.0
blad=abs(tot_old-total_calka)
tot_old=total_calka
! and the final error
write(*,*) blad
enddo
open(1,file='calka.dat', access='append')
! the secod viarial coefficient=CONSTANT*total_calka,
! CONSTANT is omitted here
write(1,*)tempred,total_calka
close(1)
end program wykres
The inte is declared in both modules.
Upd. The inte(y,beta,r2,r1) function is defined in the module in, and is used in the main program. This function requires four arguments, but this call
irange=inte(intrange/division)
provides only one argument. I'm not sure if this function should be used in this case. Try to use long meaningful names for variables and functions to avoid similar issues.

increase array in module

I am trying to write a small module/class in Fortran. The idea is very basic:
Create and initialize the object with a dedicated constructor
Add a new element inside of it
I already write Fortran but only subroutine and I will try to use oriented object principle. Currently I have two errors:
the constructor I built does not work (seems to not accept my input arguments)...
the add_bb procedure is not accepted.
MNWE:
module test_mod
implicit none
type :: bb
real :: item
real,allocatable :: vect(:)
end type bb
interface bb
procedure :: new_bb!,add_bb
end interface bb
contains
type(bb) function new_bb(val,nbv)
real, intent(in) :: val
integer, intent(in) :: nbv
integer :: ii
new_bb%item=val
allocate(new_bb%vect(nbv))
print *,nbv
do ii=1,nbv
new_bb%vect(ii)=val
print *,ii
enddo
print *,new_bb%vect
end function new_bb
type(bb) function add_bb(it)
real,intent(in) :: it
integer :: sp
real,allocatable :: tmp(:)
sp=size(add_bb%vect)+1
allocate(tmp(sp))
tmp(1:sp-1) = add_bb%vect(1:sp-1)
call move_alloc(tmp, add_bb%vect)
add_bb%vect(sp)=it
end function add_bb
end module test_mod
program test
use test_mod
implicit none
type(bb) :: cc
cc=bb(10,20)
call cc%add_bb(10)
print *,cc%item
print *,cc%vect
!
end program test
I tried to fix the bugs in your code, but as I worked on it more, I discovered more and more fundamental flaws in your code. Obviously, that implies that you are likely not well familiar with OOP, in particular, in Fortran. Therefore, I recommend you to grab a book, for example, "Modern Fortran Explained" by Metcalf et al. and learn this topic. Meanwhile, here is a revised version of your code that at least works without syntax error:
module test_mod
implicit none
type :: bb_type
real :: item
real, allocatable :: vect(:)
contains
procedure, pass :: add_bb
end type bb_type
interface bb_type
procedure :: construct_bb
end interface bb_type
contains
function construct_bb(val,nbv) result (bb)
real, intent(in) :: val
integer, intent(in) :: nbv
type(bb_type) :: bb
integer :: ii
bb%item=val
allocate(bb%vect(nbv))
print *,nbv
do ii=1,nbv
bb%vect(ii)=val
print *,ii
enddo
print *,bb%vect
end function construct_bb
subroutine add_bb(self,it)
class(bb_type), intent(inout) :: self
real,intent(in) :: it
integer :: sp
real, allocatable :: tmp(:)
sp=size(self%vect)+1
allocate(tmp(sp))
!tmp(1:sp-1) = self%vect(1:sp-1)
!call move_alloc(tmp, self%vect)
!self%vect(sp)=it
end subroutine add_bb
end module test_mod
program test
use test_mod
implicit none
type(bb_type) :: cc, dd
cc=bb_type(10,[20])
call dd%add_bb(10.0)
print *,cc%item
print *,cc%vect
!
end program test

Binary Read/Write of Data Types with Allocatable Components in Fortran90+

What is the best way to save a binary snapshot of the variable save which is made out of sample data type below?
program save_it
type core
integer, dimension(8) :: indx
end type core
type sample
integer :: a
real*8, dimension(:), allocatable :: b
type(core), dimension(:), allocatable :: c
end type sample
! here it comes
type(sample) :: save
! here we allocate all componenets of variable "save"
!.
!.
! Now, how to write/read variable "save" to/from external file?
end program save_it
There is pretty straight binary input/output streaming in C++ but I don't know how to do it in Fortran 90+.
If by Fortran90+ you mean you are happy with Fortran 2003, then there is the option of user-defined derived type IO. This allows you to wrap the extra bookkeeping required for the allocation in the write statement. I'll put example code at the bottom.
If you don't want to use this feature, which is possibly because you don't have a compiler which supports it (I've tested with ifort 14), then you can mimic the bookkeeping easily enough.
The crucial part is just sending out and reading back in the sizes and allocating the variables before the read.
The code:
module types
type core
integer, dimension(8) :: indx
end type core
type sample
integer :: a
real*8, dimension(:), allocatable :: b
type(core), dimension(:), allocatable :: c
contains
procedure write_sample
procedure read_sample
generic :: write(unformatted) => write_sample
generic :: read(unformatted) => read_sample
end type sample
contains
! Unformatted writing for the sample derived type
subroutine write_sample(dtv, unit, iostat, iomsg)
class(sample), intent(in) :: dtv
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
integer i
! Write a record giving sizes for the allocation
write(unit, iostat=iostat, iomsg=iomsg) SIZE(dtv%b), SIZE(dtv%c)
write(unit, iostat=iostat, iomsg=iomsg) dtv%a, dtv%b, &
(dtv%c(i)%indx, i=1,SIZE(dtv%c))
end subroutine write_sample
! Unformatted reading for the sample derived type
subroutine read_sample(dtv, unit, iostat, iomsg)
class(sample), intent(inout) :: dtv
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
integer i
integer sizeb, sizec
! We first have a record telling us the sizes of components
read(unit, iostat=iostat, iomsg=iomsg) sizeb, sizec
! So we do the allocation
allocate(dtv%b(sizeb), dtv%c(sizec))
! And then finally the reading.
read(unit, iostat=iostat, iomsg=iomsg) dtv%a, dtv%b, &
(dtv%c(i)%indx, i=1,SIZE(dtv%c))
end subroutine read_sample
end module types
program save_it
use types
implicit none
integer i, unit_in, unit_out
! here it comes
type(sample) :: save
type(sample) :: save_test
! Define some values - using ifort don't forget to set the compile flag
save%a = 14
save%b = [(i*1., i=1, 10)]
save%c = [core([(i, i=1,8)]), core([(i, i=11, 18)])]
! Write out the derived type
open(newunit=unit_out, file='serial', form='unformatted', &
status='replace', action='write')
write(unit_out) save
close(unit_out)
! Read in the derived type to a new one
open(newunit=unit_in, file='serial', form='unformatted', &
status='old', action='read')
read(unit_in) save_test
close(unit_in)
! Test, if we want to be certain
end program save_it
There's certainly a lot of work to be done on making it robust.