I'm developing an integral using libcuba with Fortran, but when I go to run the program, this error appears
Backtrace for this error:
0x7ff80c55d31a
0x7ff80c55c503
0x7ff80bbd9f1f
0x55eb8a7eb281
0x55eb8a7ec8e1
0x55eb8a7c0b24
0x55eb8a7c1785
0x55eb8a7daf03
0x55eb8a7d7e8f
0x55eb8a7c34b1
0x55eb8a7c20a9
0x55eb8a7c1087
0x55eb8a7c1732
0x7ff80bbbcb96
0x55eb8a7bbc99
0xffffffffffffffff
Targeting failure (recorded core image)
The code of program is:
PROGRAM Integral_E_ultra
IMPLICIT None
DOUBLE PRECISION NORM,VAL
CALL E_ultra(VAL)
STOP
END
SUBROUTINE E_ultra(VAL)
IMPLICIT NONE
DOUBLE PRECISION NORM,VAL,PI,VALG1
DOUBLE PRECISION INTEGRALG1(1),ERRORG1(1),PROBG1(1)
PARAMETER (PI=3.14159265358979D0)
C Parameters related to the CUBA numerical integration:
integer ndim,ncomp,mineval,maxeval,verbose,last
integer fail,nregions,neval
double precision epsrel,epsabs,userdata
parameter (ndim=1)
parameter (userdata=0)
parameter (ncomp=1)
parameter (epsrel=1D-3)
parameter (epsabs=1D-12)
parameter (verbose=0)
parameter (last = 4)
parameter (mineval=0)
parameter (maxeval=50000)
integer key1, key2, key3
parameter (key1 = 47)
parameter (key2 = 1)
parameter (key3 = 1)
integer nstart,nincrease
parameter (nstart = 1000)
parameter (nincrease = 500)
integer nnew
double precision flatness
parameter (nnew = 1000)
parameter (flatness = 25D0)
integer key
parameter (key =0)
EXTERNAL INTG1
CALL CUHRE(ndim,ncomp,INTG1,userdata,
+ epsrel,epsabs,verbose+last,mineval,maxeval,
+ KEY,NREGIONS,neval,fail,INTEGRALG1,ERRORG1,PROBG1)
VALG1=INTEGRALG1(1)
VAL=3D0*VALG1/(16*PI**3D0)
RETURN
END
SUBROUTINE INTG1(NDIM,X,NCOMP,RESULT)
IMPLICIT NONE
DOUBLE PRECISION X(NDIM),RESULT(NCOMP)
DOUBLE PRECISION VAR(1),RANGE,JACOBIAN,PI
DOUBLE PRECISION UPPER(1)
COMMON/UBOUND/ UPPER
DOUBLE PRECISION LOWER(1)
COMMON/UBOUND/ LOWER
INTEGER NDIM,NCOMP,I
PARAMETER (PI=3.14159265358979D0)
Result = 0
VAR = 0
RANGE=0D0
JACOBIAN=1D0
LOWER(1)=0D0
UPPER(1)=1D0
DO I=1,NDIM
RANGE=UPPER(I)-LOWER(I)
JACOBIAN=JACOBIAN*RANGE
VAR(I)=LOWER(I)+X(I)*RANGE
ENDDO
CALL INTEGRANDG1(RESULT,VAR)
RESULT(1)=RESULT(1)*JACOBIAN
RETURN
END
SUBROUTINE INTEGRANDG1(RESULT,VAR)
IMPLICIT NONE
DOUBLE PRECISION VAR(1),RESULT(*)
DOUBLE PRECISION NORM,LAMBDA,ALPHA,K,M,G1
LAMBDA = 1
K=1
G1 = 0
ALPHA = VAR(1)
G1= -(LAMBDA**2*K*M*ALPHA)/(K**2+LAMBDA**2)**2
RESULT(1) = G1
RETURN
END
Related
Here is the Main Program:
PROGRAM integration
EXTERNAL funct
DOUBLE PRECISION funct, a , b, sum, h
INTEGER n, i
REAL s
PARAMETER (a = 0, b = 10, n = 200)
h = (b-a)/n
sum = 0.0
DO i = 1, n
sum = sum+funct(i*h+a)
END DO
sum = h*(sum-0.5*(funct(a)+funct(b)))
PRINT *,sum
CONTAINS
END
And below is the Function funct(x)
DOUBLE PRECISION FUNCTION funct(x)
IMPLICIT NONE
DOUBLE PRECISION x
INTEGER K
Do k = 1,10
funct = x ** 2 * k
End Do
PRINT *, 'Value of funct is', funct
RETURN
END
I would like the 'Sum' in the Main Program to print 10 different sums over 10 different values of k in Function funct(x).
I have tried the above program but it just compiles the last value of Funct() instead of 10 different values in sum.
Array results require an explicit interface. You would also need to adjust funct and sum to actually be arrays using the dimension statement. Using an explicit interface requires Fortran 90+ (thanks for the hints by #francescalus and #VladimirF) and is quite tedious:
PROGRAM integration
INTERFACE funct
FUNCTION funct(x) result(r)
IMPLICIT NONE
DOUBLE PRECISION r
DIMENSION r( 10 )
DOUBLE PRECISION x
END FUNCTION
END INTERFACE
DOUBLE PRECISION a , b, sum, h
DIMENSION sum( 10)
INTEGER n, i
PARAMETER (a = 0, b = 10, n = 200)
h = (b-a)/n
sum = 0.0
DO i = 1, n
sum = sum+funct(i*h+a)
END DO
sum = h*(sum-0.5*(funct(a)+funct(b)))
PRINT *,sum
END
FUNCTION funct(x)
IMPLICIT NONE
DOUBLE PRECISION funct
DIMENSION funct( 10)
DOUBLE PRECISION x
INTEGER K
Do k = 1,10
funct(k) = x ** 2 * k
End Do
PRINT *, 'Value of funct is', funct
RETURN
END
If you can, you should switch to a more modern Standard such as Fortran 90+, and use modules. These provide interfaces automatically, which makes the code much simpler.
Alternatively, you could take the loop over k out of the function, and perform the sum element-wise. This would be valid FORTRAN 77:
PROGRAM integration
c ...
DIMENSION sum( 10)
c ...
INTEGER K
c ...
DO i = 1, n
Do k = 1,10
sum(k)= sum(k)+funct(i*h+a, k)
End Do
END DO
c ...
Notice that I pass k to the function. It needs to be adjusted accordingly:
DOUBLE PRECISION FUNCTION funct(x,k)
IMPLICIT NONE
DOUBLE PRECISION x
INTEGER K
funct = x ** 2 * k
PRINT *, 'Value of funct is', funct
RETURN
END
This version just returns a scalar and fills the array in the main program.
Apart from that I'm not sure it is wise to use a variable called sum. There is an intrinsic function with the same name. This could lead to some confusion...
program prob_1
implicit real*8(a-h, o-z)
f(x) = x**2-cos(x)
df(x) = 2*x+sin(x)
x0 = 0, x1 = 1
do i = 1, 3
if (f((x0+x1)/2) < 0)
x0 = (x0+x1)/2
else
x1 = (x0+x1)/2
end do
print *,"x = ", x
end program
I'm just starting to use Fortran 90.
Now I'm using Code::blocks but I don't know exactly which line the error exists on.
I guess the problem is f((x0+x1)/2) < 0 but don't know actually what is the real error.
what's problem is here?
Be advised that statement functions, the function definitions the OP uses, are obsolescent.
B.3.4 Statement functions
Statement functions are subject to a number of non intuitive restrictions and are a potential source of error because their syntax is easily confused with that of an assignment statement.
The internal function is a more generalized form of the statement function and completely supersedes it.
source: F2018 Standard
Also the notation REAL*8 or anything of that form has never been part of any Fortran standard (see here):
I would suggest to rewrite the code as:
program prob_1
implicit none
double precision :: x1,x0
integer :: i
x0 = 0; x1 = 1
do i = 1, 3
if (f((x0+x1)/2.0D0) < 0) then
x0 = (x0+x1)/2.0D0
else
x1 = (x0+x1)/2.0D0
endif
end do
print *,"x = ", (x0+x1)/2.0D0
contains
function f(x)
double precision, intent(in) :: x
double precision :: f
f = x**2-cos(x)
end function f
function df(x)
double precision, intent(in) :: x
double precision :: df
df = 2.0D0*x+sin(x)
end function df
end program
If you change your program as follows then it will compile:
program prob_1
implicit real*8(a-h, o-z)
f(x) = x**2-cos(x)
df(x) = 2*x+sin(x)
x0 = 0; x1 = 1
do i = 1, 3
if (f((x0+x1)/2) < 0) then
x0 = (x0+x1)/2
else
x1 = (x0+x1)/2
endif
end do
print *,"x = ", x
end program
As mentionned in the comments, you have to add the semicolon ; to separate statements in one line and you have to add the then as well as endif to your if condition.
Hope it helps.
Here is the Main Program:
PROGRAM integration
EXTERNAL funct
DOUBLE PRECISION funct, a , b, sum, h
INTEGER n, i
REAL s
PARAMETER (a = 0, b = 10, n = 200)
h = (b-a)/n
sum = 0.0
DO i = 1, n
sum = sum+funct(i*h+a)
END DO
sum = h*(sum-0.5*(funct(a)+funct(b)))
PRINT *,sum
CONTAINS
END
And below is the Function funct(x)
DOUBLE PRECISION FUNCTION funct(x)
IMPLICIT NONE
DOUBLE PRECISION x
INTEGER K
Do k = 1,10
funct = x ** 2 * k
End Do
PRINT *, 'Value of funct is', funct
RETURN
END
I would like the 'Sum' in the Main Program to print 10 different sums over 10 different values of k in Function funct(x).
I have tried the above program but it just compiles the last value of Funct() instead of 10 different values in sum.
Array results require an explicit interface. You would also need to adjust funct and sum to actually be arrays using the dimension statement. Using an explicit interface requires Fortran 90+ (thanks for the hints by #francescalus and #VladimirF) and is quite tedious:
PROGRAM integration
INTERFACE funct
FUNCTION funct(x) result(r)
IMPLICIT NONE
DOUBLE PRECISION r
DIMENSION r( 10 )
DOUBLE PRECISION x
END FUNCTION
END INTERFACE
DOUBLE PRECISION a , b, sum, h
DIMENSION sum( 10)
INTEGER n, i
PARAMETER (a = 0, b = 10, n = 200)
h = (b-a)/n
sum = 0.0
DO i = 1, n
sum = sum+funct(i*h+a)
END DO
sum = h*(sum-0.5*(funct(a)+funct(b)))
PRINT *,sum
END
FUNCTION funct(x)
IMPLICIT NONE
DOUBLE PRECISION funct
DIMENSION funct( 10)
DOUBLE PRECISION x
INTEGER K
Do k = 1,10
funct(k) = x ** 2 * k
End Do
PRINT *, 'Value of funct is', funct
RETURN
END
If you can, you should switch to a more modern Standard such as Fortran 90+, and use modules. These provide interfaces automatically, which makes the code much simpler.
Alternatively, you could take the loop over k out of the function, and perform the sum element-wise. This would be valid FORTRAN 77:
PROGRAM integration
c ...
DIMENSION sum( 10)
c ...
INTEGER K
c ...
DO i = 1, n
Do k = 1,10
sum(k)= sum(k)+funct(i*h+a, k)
End Do
END DO
c ...
Notice that I pass k to the function. It needs to be adjusted accordingly:
DOUBLE PRECISION FUNCTION funct(x,k)
IMPLICIT NONE
DOUBLE PRECISION x
INTEGER K
funct = x ** 2 * k
PRINT *, 'Value of funct is', funct
RETURN
END
This version just returns a scalar and fills the array in the main program.
Apart from that I'm not sure it is wise to use a variable called sum. There is an intrinsic function with the same name. This could lead to some confusion...
I'm having some troubles to calcule the integral of e^x inside and interval [b.a] using fortran.
I think I'm doing something wrong in the funcion calls. Thanks for helping me.
program trapezium
implicit none
integer :: i, n, b, a
real :: sumation, mean, deltax, f(i), integral
! The value of the integral using the trapezium rule can be found using
! integral = (b - a)*((f(a) +f(b))/2 + sumation_1_n-1 )/n
write(*,*) "type the limits b, a and the number of intervals"
read *, b, a, n
deltax = (b - a)/n
mean = (f(a) + f(b))/2
sumation = 0
do i = 1, n-1
sumation = sumation + f(i)
end do
integral = deltax*(mean + sumation)
write (*,*) "the value of the integral using the trapezoidal method is", integral
end program
function f(x)
real :: f(x)
integer :: x
f(x) = EXP(x)
end function
There are a couple of issues with your code:
f is a function, but at the same time you define an array f(i)
When defining an array of fixed size, the size has to be known at compile time. So real :: f(i) is only valid for a constant i
exp() expects a real variable, not an integer
Integer arithmetic might lead to unexpected results: 1/2 = 0 and not 0.5!
What about (This does not try to fix the maths, though - see my comment):
module functions
contains
function f(x)
implicit none
real :: f
integer,intent(in) :: x
f = EXP(real(x))
end function
end module
program trapezium
use functions
implicit none
integer :: i, n, b, a
real :: sumation, mean, deltax, integral
! The value of the integral using the trapezium rule can be found using
! integral = (b - a)*((f(a) +f(b))/2 + sumation_1_n-1 )/n
write(*,*) "type the limits b, a and the number of intervals"
read *, b, a, n
deltax = real(b - a)/real(n)
mean = (f(a) + f(b))/2
sumation = 0
do i = 1, n-1
sumation = sumation + f(i)
end do
integral = deltax*(mean + sumation)
write (*,*) "the value of the integral using the trapezoidal method is", integral
end program
Note that the use of modules enables the compiler to check for the arguments of the function. Additionally, you do not need to define the return value of the function in the main program.
I am new in Fortran and i have this problem.
When i ran this DO is ok:
integer, parameter :: Int10Type = selected_int_kind (10)
INTEGER (Int10Type), PARAMETER :: TOTAL_TIME = 1000, TOTAL_INI = 200
INTEGER (Int10Type):: t, z
REAL (16), DIMENSION(TOTAL_Z, TOTAL_TIME) :: current
DO t = 1, TOTAL_TIME
current(TOTAL_Z, t) = TEMP_INI
END DO
DO t = 1, TOTAL_TIME - 1
DO z = 2, (TOTAL_Z - 1)
current(z, t + 1) = current (z, t) + KAPPA*DELTA_T*((current(z - 1, t) -2.0*current(z, t) + current(z + 1, t)) / DELTA_Z**2)
END DO
END DO
But, when i increment var limite
integer, parameter :: Int10Type = selected_int_kind (10)
INTEGER (Int10Type), PARAMETER :: TOTAL_TIME = 1000000000, TOTAL_INI = 200
INTEGER (Int10Type):: t, z
REAL (16), DIMENSION(TOTAL_Z, TOTAL_TIME) :: current
DO t = 1, TOTAL_TIME
current(TOTAL_Z, t) = TEMP_INI
END DO
DO t = 1, TOTAL_TIME - 1
DO z = 2, (TOTAL_Z - 1)
current(z, t + 1) = current (z, t) + KAPPA*DELTA_T*((current(z - 1, t) -2.0*current(z, t) + current(z + 1, t)) / DELTA_Z**2)
END DO
END DO
The output of the program is 'killed'
Why? what i do bad?
integer(10) means integer(kind=10), not an integer with at least 10 decimal digits. It is up to a compiler what kind=10 means. There is no guarantee that kind=10 even exists! If you want to specify 10 decimal digits you should use:
integer, parameter :: Int10Type = selected_int_kind (10)
integer (kind=Int10Type) :: i
Then write your program as:
integer, parameter :: Int10Type = selected_int_kind (10)
INTEGER (Int10Type), PARAMETER :: limite = 1000000000_Int10Type, lim = 200
INTEGER (Int10Type):: i, j
DO i = 1, limite
DO j = 1, lim
!I work with a matrix
END DO
END DO
Notice that the type has also been specified on the large constant value.
Alternatively, if your compiler provides the ISO Fortran Environment feature of Fortran 2003, you can request an 8 byte (64 bit) integer in a portable way:
use iso_fortran_env
INTEGER (INT64), PARAMETER :: limite = 1000000000_INT64, lim = 200
INTEGER (INT64):: i, j
DO i = 1, limite
DO j = 1, lim
!I work with a matrix
END DO
END DO
P.S. 1000000000 should fit into a 4-byte (signed) integer since 2**31 = 2,147,483,648, so the default integer of most Fortran compilers should work. You can probably just use integer without specifying a kind! With iso_fortran_env, INT32 should suffice. If this doesn't solve your problem, perhaps your array is too big ... you may need to show us more code.
P.P.S. In response to the additional source code. The t do loop goes from 1 to total_time, but you use the 2nd index as t+1, which means that the largest value will be total_time+1. This exceeds the 2nd dimension of current. You have an array subscripting error. If you compile with subscript bounds checking the compiler will find this for you. With gfortran, either use -fcheck=all or -fbounds-check.