re-formatting an unformatted fortran file - formatting

I have an "UNFORMATTED" fortran file for which I have written a small subroutine to try and get some information out of (given below). What I would like to do, or like to know if it is possible to do, is to "format" the file called fort.24 into either another formatted, readable, file or a readable print out to the screen.
I thought about just putting in a loop which reads each line of the file after it has been opened and then prints it to the screen but I am not sure how to do this.
Am I correct in thinking that unformatted files can be reformatted or is this "not how it works".
Thank you very much
James
SUBROUTINE mod2
implicit none
! Arguments
integer :: nset_pw_dipoles, mgvn, stot, gutot, iprnt, iwrite, &
& ifail,dip_comp_present(3)
character(len=11) :: form_pw_dipoles
character(len=80) :: title
integer, allocatable :: ichl(:), lvchl(:), mvchl(:)
real(kind=8), allocatable :: evchl(:), escat(:),re_pw_dipoles(:,:,:,:), im_pw_dipoles(:,:,:,:)
! Local
integer :: keydip, nchan, nbound, no_scat_energies, no_components, ierr
no_components=3
keydip=24
open (unit=24,file = "fort.24", form="UNFORMATTED", iostat=ierr, err=100)
! Read set header
! ----------------
read(24) keydip, nset_pw_dipoles
read(24) title
read(24) mgvn, stot, gutot, nchan, nbound, no_scat_energies, dip_comp_present
! Allocate space for channel info arrays
allocate( ichl(nchan), lvchl(nchan), mvchl(nchan), evchl(nchan), escat(no_scat_energies) )
read(24) ichl, lvchl, mvchl, evchl, escat
! Write Set Body
! --------------
! Allocate space for partial wave dipoles
allocate( re_pw_dipoles(nbound, nchan, no_components, no_scat_energies), &
& im_pw_dipoles(nbound, nchan, no_components, no_scat_energies) )
read(24) re_pw_dipoles
read(24) im_pw_dipoles
return
100 stop "ERROR: Reading partial wave dipoles"
END SUBROUTINE mod2

Related

Extending an object and overriding a procedure without being deferred in Fortran

I have a code with lots of different features and methods. Some methods are all for the same feature, i.e. only one among a selection can be selected.
Furthermore, depending on a feature I might need to do modify subroutines elsewhere. So in a loop in routine inject I might have a small if statement asking if I have used feature A, then do a few extra operations.
This is very frustating since different features seems to be connected with others routines very arbirarirly, and can be difficult to maintain.
I have decided to do following to avoid this:
I define an object t_inject with the purpose to execture routine inject. I rewrite my routine inject such that it contains only the code that is common for all different scenarios.
type t_inject
contains
procedure,nopass :: inject => inject_default
end type
Now I have another object to handle my feature A in case it is selected.
type,extends(t_inject) :: t_inject_a
contains
procedure, nopass :: inject => inject_a
end type
My subroutines inject_a and inject have same interface. E.g.
subroutine inject_a( part )
type(t_part) , intent(inout) :: part % an external data type
call inject(part)
! do the extra bit of stuff you need to do
end subroutine
subroutine inject( part)
type(t_part) , intent(inout) :: part % an external data type
! carry out the default stuff
end subroutine
Now in my main program
class(t_inject) :: inj
allocate(inj :: t_inject_a)
call inj% inject ( part)
Is that the way you would do it and is it valid?
I initially thought of doing an abstract declared type with a deferred inject procedure where I then could extent.
But for a very trivial problem I might not need that - I am also wondering whether my call call inj% inject(part) is sufficient for the compiler to know to where to go. Sometimes I see codes which need the class is condition before making the call.
I think three points should be modified:
The type-bound procedures need to refer to actual procedure names (via =>). So, I have changed the name of a module procedure inject() to inject_default(). (But please see test2.f90 also).
We need to attach allocatable to a class variable (e.g., inj2) to allocate it with a concrete type (e.g., t_inject_a).
In the allocate statement, the name of a concrete type should appear before ::, such that allocate( t_inject_a :: inj2 ).
The modified code may look like this:
!! test.f90
module test_mod
implicit none
type t_inject
contains
procedure, nopass :: inject => inject_default
endtype
type, extends(t_inject) :: t_inject_a
contains
procedure, nopass :: inject => inject_a
endtype
type t_part !! some other type
integer :: x = 100, y = 200
endtype
contains
subroutine inject_default( part )
type(t_part), intent(inout) :: part
print *, "x = ", part % x
endsubroutine
subroutine inject_a( part )
type(t_part), intent(inout) :: part
call inject_default( part )
print *, "y = ", part % y
endsubroutine
end
program main
use test_mod
implicit none
class( t_inject ), allocatable :: inj1, inj2
type( t_part ) :: part
!! Polymorphic allocation with concrete types.
allocate( t_inject :: inj1 )
allocate( t_inject_a :: inj2 )
print *, "inj1:"
call inj1 % inject( part )
print *, "inj2:"
call inj2 % inject( part )
end
"gfortran-8 test.90 && ./a.out" gives
inj1:
x = 100
inj2:
x = 100
y = 200
We can also use a module procedure inject() (rather than inject_default()) by using procedure, nopass :: inject, for example:
!! test2.f90
module test_mod
implicit none
type t_inject
contains
procedure, nopass :: inject
! procedure, nopass :: inject => inject !! this also works
endtype
type, extends(t_inject) :: t_inject_a
contains
procedure, nopass :: inject => inject_a
endtype
type t_part !! some other type
integer :: x = 100, y = 200
endtype
contains
subroutine inject( part )
type(t_part), intent(inout) :: part
print *, "x = ", part % x
endsubroutine
subroutine inject_a( part )
type(t_part), intent(inout) :: part
call inject( part )
print *, "y = ", part % y
endsubroutine
end
!! The remaining part (and the result) is the same...
In addition, one can also separate actual procedures like inject() in a different file and use them to define new types like t_inject (see mylib.f90 and test3.f90 below). This might be useful to reuse routines in some library file.
!! mylib.f90
module mylib
implicit none
type t_part !! some other type
integer :: x = 100, y = 200
endtype
contains
subroutine inject( part )
type(t_part), intent(inout) :: part
print *, "x = ", part % x
end
subroutine inject_a( part )
type(t_part), intent(inout) :: part
call inject( part )
print *, "y = ", part % y
end
end
!! test3.f90
module test_mod
use mylib
implicit none
type t_inject
contains
procedure, nopass :: inject
endtype
type, extends(t_inject) :: t_inject_a
contains
procedure, nopass :: inject => inject_a
endtype
end
!! The main program is the same as test.f90.
!! compile: gfortran-8 mylib.f90 test3.f90

Allocating array of abstract type in Fortran

Basically, I have an abstract class a wrapper class and a base class which are defined in the Base Module. The abbstract class holds an allocatable array and a subroutine. In the constructor I want to allocate this array but that does not work.
The allocation does work for Base but I guess that is not what I want as the Child Class does not know anything from Base. How would I do this allocation?
Here's what I have:
Base Module
module BaseClass
implicit none
! ------------------------
! ABSTRACT CLASS
! ------------------------
type, abstract :: AbsBaseHelper
real, allocatable :: A(:) !! <-- this makes problems
contains
procedure :: construct
procedure(help_int), deferred :: help
end type
! ------------------------
! WRAPPER CLASS
! ------------------------
type :: BaseWrap
integer :: cI
class(AbsBaseHelper), pointer :: p
contains
procedure :: do_something
end type
! ------------------------
! INTERFACE
! ------------------------
interface
subroutine help_int(this)
import AbsBaseHelper
implicit none
class(AbsBaseHelper), intent(inout) :: this
end subroutine help_int
end interface
! ------------------------
! BASE CLASS
! ------------------------
type(BaseWrap) :: Base(2)
contains
! ------------------------
! CONSTRUCTOR
! ------------------------
subroutine construct(this, id)
implicit none
class(AbsBaseHelper), intent(in), target :: this
integer, intent(in) :: id
Base(id)%cI = id
! allocate( this%A(2) ) !! <-- does not work because this is only intent(in)
Base(id)%p => this
allocate( Base(id)%p%A(2) ) !! <-- does not work because it gives segmentation fault in 'help'
end subroutine construct
! ------------------------
! THE MAIN SUBROUTINE
! ------------------------
subroutine do_something(this)
implicit none
class(BaseWrap), intent(inout) :: this
print*, "Base Index : ", this%cI
call this%p%help()
print*, "Result 1 : ", this%p%A(1)
print*, "Result 2 : ", this%p%A(2)
end subroutine do_something
end module BaseClass
Child Module
module ChildClass1
use BaseClass
implicit none
type, extends(AbsBaseHelper) :: Child1
contains
procedure :: help
end type
contains
subroutine help(this)
implicit none
class(Child1), intent(inout) :: this
this%A(1) = 1 !! <-- produces segmentation fault
this%A(2) = 2
end subroutine
end module ChildClass1
The Program
program test
use BaseClass
implicit none
call init
call Base(1)%do_something()
contains
! ------------------------
! INITIALIZE
! ------------------------
subroutine init
use ChildClass1
implicit none
type(Child1), target :: c1
call c1%construct(1)
end subroutine init
end program test

Fortran: How to plug memory leak from un-deallocated pointer in linked list

I have a doubly-linked list implemented in Fortran 2008 (GNU Fortran v4.9.2). The list behaves as expected in terms of being able to insert/delete/push/pop, but under heavy use there is a memory leak I believe is coming pointers that are not being deallocated.
Here is a minimum working case:
module c_DLLMod
implicit none
private
type, public :: c_Node
private
type(c_Node), pointer :: Parent => null(), Child => null()
integer, allocatable :: Val
contains
procedure :: GetVal => m_GetVal
procedure :: SetVal => m_SetVal
end type c_Node
type, public :: c_DLL
private
type(c_Node), pointer :: Head => null(), Tail => null()
integer :: Size
logical :: IsReady = .false.
contains
procedure :: Front => m_Front
procedure :: PushFront => m_PushFront
procedure :: PopFront => m_PopFront
procedure :: Delete => m_Delete
procedure :: IsEmpty => m_IsEmpty
procedure :: Free => m_Free
end type c_DLL
interface c_DLL
module procedure m_NewDLL
end interface c_DLL
contains
! Begin c_Node methods
subroutine m_SetVal(N, Val)
class(c_Node), intent(inout) :: N
integer, intent(in) :: Val
if (.not. allocated(N%Val)) allocate(N%Val)
N%Val = Val
end subroutine m_SetVal
integer function m_GetVal(N) result(Val)
class(c_Node), intent(in) :: N
Val = N%Val
end function m_GetVal
! End c_Node methods
! Begin c_DLL methods
! Initialize linked list by setting initial size and ready status
function m_NewDLL() result(L)
type(c_DLL) :: L
L%Size = 0
L%IsReady = .true.
end function m_NewDLL
! Make sure that the head points to the first node and the tail to the last
subroutine m_Listify(L)
class(c_DLL), intent(inout) :: L
do while(associated(L%Head%Parent))
L%Head => L%Head%Parent
end do
do while(associated(L%Tail%Child))
L%Tail => L%Tail%Child
end do
end subroutine m_Listify
! Return the value stored in the front (head) node
integer function m_Front(L) result(Val)
class(c_DLL), intent(in) :: L
Val = 0
if (L%IsReady) Val = L%Head%GetVal()
end function m_Front
! Push new value to the front of the list
subroutine m_PushFront(L, Val)
class(c_DLL), intent(inout) :: L
integer, intent(in) :: Val
if (L%IsReady) then
if (L%Size == 0) then
! List is new or empty, so need to allocate the head node
! and assign its value to Val
if (.not. associated(L%Head)) then
allocate(L%Head)
L%Tail => L%Head ! List only has 1 value, so tail and head are same
end if
call L%Head%SetVal(Val)
else
! List is not empty, so make sure head and tail point to right
! nodes, then allocate new node in front of the head and assign
! Val to it.
call m_Listify(L)
allocate(L%Head%Parent)
call L%Head%Parent%SetVal(Val)
L%Head%Parent%Child => L%Head ! Give the new head its child node
nullify(L%Head%Parent%Parent) ! Tell new head that it is in fact the head (i.e. no parent node)
L%Head => L%Head%Parent ! Set head pointer to the new head
end if
L%Size = L%Size + 1
end if
end subroutine m_PushFront
! Remove the head node from the list
subroutine m_PopFront(L)
class(c_DLL), intent(inout) :: L
if (L%IsReady .and. L%Size > 0) then
if (associated(L%Head%Child)) then
! List has more than 1 value, so need to point head to the
! new head after popping
L%Head => L%Head%Child
call m_Delete(L, L%Head%Parent) ! Head%Parent is actually the head until it's deleted
else
! List has only 1 element, so can simply delete it
call m_Delete(L, L%Head)
end if
end if
end subroutine m_PopFront
! Remove a node N from the list, maintaining connectivity in the list
subroutine m_Delete(L, N)
class(c_DLL), intent(inout) :: L
type(c_Node), pointer, intent(inout) :: N
if (L%IsReady .and. L%Size >= 1) then
deallocate(N%Val) ! Deallocate the integer Val of the node to be deleted (N)
if (associated(N%Parent)) then
if (associated(N%Child)) then
! N has both parent and child nodes, so need to point parent to child
! and child to parent so that the list stays connected
N%Child%Parent => N%Parent
N%Parent%Child => N%Child
else
! N has only parent node, so the parent's child pointer will now become null,
! so that the parent know's it's the new tail of the list
nullify(N%Parent%Child)
end if
else
if (associated(N%Child)) then
! N has only child node, so the child's parent pointer will now become null,
! so that the child know's it's the new head of the list
nullify(N%Child%Parent)
end if
end if
! At this point I'm done with N, and N was allocated earlier by
! either the m_NewDLL function or inside a call to m_PushFront,
! but if I try to deallocate then it throws a runtime error that
! N isn't allocated and cannot be deallocated.
! deallocate(N)
nullify(N)
L%Size = L%Size - 1
end if
end subroutine m_Delete
! Check if list is empty
logical function m_IsEmpty(L)
class(c_DLL), intent(in) :: L
m_IsEmpty = (L%Size == 0)
end function m_IsEmpty
! Delete all elements of the list, starting with the head node
subroutine m_Free(L)
class(c_DLL), intent(inout) :: L
type(c_Node), pointer :: Cur
if (L%IsReady .and. L%Size > 0) then
Cur => L%Head
do while(associated(Cur%Child))
Cur => Cur%Child
call m_Delete(L, Cur%Parent)
end do
call m_Delete(L, Cur)
L%Size = 0
L%IsReady = .false.
end if
end subroutine m_Free
end module c_DLLMod
! Simple test program that pushs array values to a list
! and then pops them off the front of the list.
! This behavior is that of a stack, so the order
! of array elements is reversed in the process of
! pushing/popping.
program main
use c_DLLMod
implicit none
type(c_DLL) :: List
integer, dimension(10) :: A
integer :: i, j
! When IsDebug is true, the test will execute 10 million times, and
! the program's memory cost will go to ~2.5GB.
! When IsDebug is false, the test will execute once, and will output
! values along the way so that you can see the list is
! performing as expected.
logical :: IsDebug = .true.
A = (/ 2,1,4,3,6,5,8,7,10,9 /)
write(*,*) 'Starting test'
List = c_DLL()
do j = 1, 10000000
if (IsDebug) write(*,*) 'populate list'
do i = 1, 10
call List%PushFront(A(i))
if (IsDebug) write(*,*) List%Front()
end do
if (IsDebug) write(*,*) 'empty list'
do while(.not. List%IsEmpty())
if (IsDebug) write(*,*) List%Front()
call List%PopFront
end do
if (IsDebug) stop
end do
write(*,*) 'Finished'
call List%Free
end program main
Switch the value of IsDebug to toggle the short/long versions of the test.
Each c_Node has a integer pointer that is allocated before a value is stored, and deallocated in m_Delete() when the node is no longer required. On line 160 (deallocate(N) in m_Delete()) the node being deleted should be deallocated, but this line throws a runtime error stating that the node is not allocated and therefore is unable to be deallocated. When this line is commented out, the list works, but if the full test is run then the program will take ~2.5GB of memory, and I think the leak is due to these nodes not being deallocated when they’re deleted, resulting in millions of allocated pointers.
I’ve commented the code that, hopefully, you all can see what’s going on. I must be making a fundamental mistake somewhere with how I’ve implemented this linked list, but a similar implementation in C++ works just fine.
What am I doing wrong that keeps a deleted node from being able to be deallocated? Or is that actually the problem here?
Thanks,
Tim
P.S. On a side note, I'm not entirely sure when to use nullify(pointer) vs pointer => null(). Could you comment on my use of each please?
The key to find the bug (after a short check with valgrind) is this piece:
! At this point I'm done with N, and N was allocated earlier by
! either the m_NewDLL function or inside a call to m_PushFront,
! but if I try to deallocate then it throws a runtime error that
! N isn't allocated and cannot be deallocated.
! deallocate(N)
You really should deallocate N. The fact that it is null at this point means something is wrong!
The error is here:
if (associated(N%Child)) then
! N has only child node, so the child's parent pointer will now become null,
! so that the child know's it's the new head of the list
nullify(N%Child%Parent)
You are just now nullifying the N in fact, because what you passed to m_Delete was
call m_Delete(L, L%Head%Parent)
so that N is L%Head%Parent and N%Child is L%Head and its Parent is N. At least if I understand your code right.
Anyway, if I uncomment the deallocate and comment this nullify, it works nicely:
==3347==
==3347== HEAP SUMMARY:
==3347== in use at exit: 0 bytes in 0 blocks
==3347== total heap usage: 41 allocs, 41 frees, 12,271 bytes allocated
==3347==
==3347== All heap blocks were freed -- no leaks are possible
==3347==
==3347== For counts of detected and suppressed errors, rerun with: -v
==3347== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
As IanH points out in his comment, there is also another issue. You are passing the same entity as an actual argument to m_delete two times in two separate arguments in this call:
call m_Delete(L, L%Head)
L%Head is part of L and you change the association status of L%Head through the second argument, but also the value of other parts of L through the first argument. This is not allowed. The shortest way to resolve this is to add the target attribute to the first dummy argument of m_Delete along paragraph 12.5.2.13p1(3b) of the Fortran 2008 standard. All restrictions are in section 12.5.2.13 of F2008.

Overloading the equals operator in Fortran

Is there a way to overload the = operator so that you can write an assignment like in this example:
module constants_mod
integer,parameter :: dpn = selected_real_kind(14)
end module
module vectorField_mod
use constants_mod
implicit none
private
public :: vectorField
public :: allocateX,allocateY,allocateZ
public :: delete
! public :: operator(=)
type vectorField
integer,dimension(3) :: sx,sy,sz
real(dpn),dimension(:,:,:),allocatable :: x,y,z
end type
interface delete
module procedure deallocateVectorField
end interface
! interface operator (=)
! module procedure vectorAssign
! end interface
contains
! function vectorAssign(f) result(q)
! implicit none
! real(dpn),intent(in) :: f
! type(vectorField) :: q
! q%x = f; q%y = f; q%z = f
! end function
! subroutine vectorAssign(f,g)
! implicit none
! type(vectorField),intent(inout) :: f
! real(dpn),intent(in) :: g
! f%x = g; f%y = g; f%z = g
! end subroutine
subroutine allocateX(field,Nx,Ny,Nz)
implicit none
type(vectorField),intent(inout) :: field
integer,intent(in) :: Nx,Ny,Nz
if (allocated(field%x)) deallocate(field%x)
allocate(field%x(Nx,Ny,Nz))
field%sx = shape(field%x)
end subroutine
subroutine allocateY(field,Nx,Ny,Nz)
implicit none
type(vectorField),intent(inout) :: field
integer,intent(in) :: Nx,Ny,Nz
if (allocated(field%y)) deallocate(field%y)
allocate(field%y(Nx,Ny,Nz))
field%sy = shape(field%y)
end subroutine
subroutine allocateZ(field,Nx,Ny,Nz)
implicit none
type(vectorField),intent(inout) :: field
integer,intent(in) :: Nx,Ny,Nz
if (allocated(field%z)) deallocate(field%z)
allocate(field%z(Nx,Ny,Nz))
field%sz = shape(field%z)
end subroutine
subroutine deallocateVectorField(field)
implicit none
type(vectorField),intent(inout) :: field
deallocate(field%x,field%y,field%z)
field%sx = 0; field%sy = 0; field%sz = 0
end subroutine
end module
program test
use constants_mod
use vectorField_mod
implicit none
type(vectorField) :: a
integer :: N = 1
real(dpn) :: dt = 0.1
call allocateX(a,N,N,N)
call allocateY(a,N,N,N)
call allocateZ(a,N,N,N)
a%x = dble(1.0) ! want to avoid this
a%y = dble(1.0) ! want to avoid this
a%z = dble(1.0) ! want to avoid this
a = real(1.0,dpn) ! want this instead (does not compile)
call delete(a)
end program
I've tried two different ways (shown in comments) but I get errors saying that there is a syntax error in generic specification (for publicizing the = operator).
= is not an operator, it is an assignment in Fortran and they are very different beasts.
To the classical possibility found in Fortran 90 and explained well in other answers, Fortran 2003 added a better possibility to bind the overloaded operators and assignments with the derived type.
This way you are sure you will not import the type without the assignment (beware of public and private statement in this case!). It can have very unpleasant consequences and can be hard to debug:
type vectorField
integer,dimension(3) :: sx,sy,sz
real(dpn),dimension(:,:,:),allocatable :: x,y,z
contains
procedure :: assignVector
generic :: assignment(=) => assignVector
end type
This way you do not have to be that careful to not forget the public :: assignment (=)
For defined assignment operator(=) is not correct, but assignment(=) is: see Fortran 2008 12.4.3.4.3. So you instead want the two lumps
public :: assignment (=)
and
interface assignment (=)
module procedure vectorAssign
end interface
Note that the correct way to define the assignment is by the subroutine as you have it (although the assignee could have intent(out) instead of intent(inout)).
Yes, you can overload the assignment operator. The syntax and requirements are different for the assignment operator than for other operators because the semantics are fundamentally different: all other operators compute a new value based on one or two arguments, without changing the arguments, whereas assignment changes the value of the left-hand argument.
In your case, I think it should look like this:
module vectorField_mod
! ...
interface assignment (=)
module procedure vectorAssign
end interface
contains
! ...
subroutine vectorAssign(f,g)
implicit none
type(vectorField),intent(out) :: f
real(kind = dpn), intent(in) :: g
f%x = g
f%y = g
f%z = g
end subroutine vectorAssign
end module vectorField_mod

Type bound procedure encapsulation

How to pass an encapsulated type bound function? I played with the example from the Modern Fortran Explained book (Metcalf, Reid and Cohen) and this is what I did:
module mod_polynoms_abstract
use mod_geometrics
implicit none
type, abstract :: bound_user_polynom
! No data
contains
procedure(user_polynom_interface), deferred :: eval
end type bound_user_polynom
abstract interface
real function user_polynom_interface(poly, pt)
import :: bound_user_polynom, point
class(bound_user_polynom) :: poly
type(point), intent(in) :: pt
end function user_polynom_interface
end interface
contains
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!Integral driver/chooser function
real function integral(userfun, options,status)
class(bound_user_polynom) :: userfun
integer, intent(in) :: options
real, intent(out) :: status
select case( options )
case (1)
integral = first_integral(userfun)
case (2)
integral = second_integral(userfun)
case default
integral = def_integral(userfun)
end select
end function
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!1. integration
real function first_integral(userfun)
class(bound_user_polynom),intent(in) :: userfun
first_integral= 1.0 * userfun%eval(point(x=2.,y=2.,z=0.))
end function
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!2. integration
real function second_integral(userfun)
class(bound_user_polynom),intent(in) :: userfun
second_integral= 2.0 * userfun%eval(point(x=2.,y=2.,z=0.))
end function
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!default integration
real function def_integral(userfun)
class(bound_user_polynom) :: userfun
def_integral= 0.0 * userfun%eval(point(x=2.,y=2.,z=0.))
end function
end module
This compiles, but when I run the program I get different results.
When I call the function, maybe like this:
integral_result = integral(poly, 2 , status)
I get sometimes the right result, which is computed with the second_integral(userfun)
function. But sometimes the result is wrong.
The function can't calculate userfun%eval(point(x=2.,y=2.,z=0.)) correctly, but I don't know why.
Is this the correct way to do this?
Edit:
I use :
COLLECT_GCC=gfortran4.8
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/4.8.0/lto-wrapper
Ziel: x86_64-unknown-linux-gnu
Konfiguriert mit: ./configure --disable-multilib
Thread-Modell: posix
gcc-Version 4.8.0 (GCC)
The correct result of userfun%eval(point(x=2.,y=2.,z=0.)) is 0.962435484
So integral(poly, 2 , status) must give me 1.92487097.
But when I execute the program several times I got:
first run : 1.92487097
second run: 54877984.0
... : 1.92487097
... : 2.55142141E+27
... : 4.19146938E+33
... : 1.95548379
and so on ..
Edit 2:
The type polynom is defined as:
type, extends(bound_user_polynom) :: polynom
real(kind=kind(1.0D0)), allocatable, dimension(:) :: coeff
type(monomial),allocatable, dimension(:) :: monom
contains
procedure :: eval => poly_eval
procedure, private :: p_add
generic :: operator(+) => p_add
procedure, private :: p_subs
generic :: operator(-) => p_subs
end type
!constructor
interface polynom
module procedure construct_poly
end interface
and in my main program i call:
integral_result = integral(p(2), 2 , status)
Found the error with some help from comp.fortan:
in:
userfun%eval(point(x=2.,y=2.,z=0.))
i had one uninitialized variable which gave me this strange results.
Is seems there is nothing wrong with the rest of the code.
Thank You,
Jan