Error: Rank mismatch in argument (rank-1 and scalar) - fortran

I am getting these kind of errors.
colsys.f:1367.51:
1 NOLD, ALDIF, K, NCOMP, M, MSTAR, 3,DUMM,0)
1
Warning: Rank mismatch in argument 'dmval' at (1) (rank-1 and scalar)
colsys.f:814.33:
1 EALPHA, A, IPIV, INTEGS, RNORM, 0, FSUB,
1
Warning: Actual argument contains too few elements for dummy argument 'integs' (1/3) at (1)
Here I an giving the program link. More errors are there in the link provided below. Some of the errors I fixed. But I don't know how to attach the updated program since it is too long to copy and paste.
http://www4.ncsu.edu/~mtchu/Teaching/Lectures/MA581/colsys.f

Either
a) in the declaration of a procedure (either a function or a subroutine) argument dumm is defined to be a rank-1 array (an array with 1 dimension if you prefer but 'rank-1' is the Fortran terminology that your compiler uses) and when your code calls the procedure it is given a scalar value. Note in particular that a scalar value is not the same (for argument matching) as a rank-1 array with only one element.
or
b) vice-versa.
Either way, there is a mismatch between the argument in the procedure definition and the argument passed when the procedure is called.
The second error you report is similar, it seems that when the procedure is called it expects a 3-element array but gets only a 1-element array. Or something like that.
Personally I'm not inclined to follow links off-site in search of more errors to fix.

The linked code is an old code written in 1981 (more than 35 years ago!), and it seems that all the warning messages come from the now obsolete way of using one-element arrays as assumed-size arrays, e.g.,
DIMENSION M(1), ZETA(1), IPAR(1), LTOL(1), TOL(1),
So, I guess it will probably be OK to just ignore all the warning messages as long as it compiles successfully. If desired, the warnings may be suppressed by some compiler options, or by modifying such arrays to assumed-size ones, e.g.
DIMENSION M(*), ZETA(*), IPAR(*), LTOL(*), TOL(*),
Another problem is that the author passes a scalar variable named DUMM etc to a dummy array argument that is not used in the subroutine. So, to avoid warnings, we also need to declare those variables explicitly as DUMM(1) in the caller side.
To actually modify the code, replace dummy arguments with (1) and ,1) in the DIMENSION statement by (*) and ,*) (which could be done by hand or by sed/awk). Then the difference between the original and modified codes becomes as follows. Although it is still not clear whether the code works correctly, this at least eliminates all the warnings by gfortran and ifort.
457,458c457,461
< DIMENSION M(1), ZETA(1), IPAR(1), LTOL(1), TOL(1),
< 1 FIXPNT(1), ISPACE(1), FSPACE(1)
---
> DIMENSION M(*), ZETA(*), IPAR(*), LTOL(*), TOL(*),
> 1 FIXPNT(*), ISPACE(*), FSPACE(*)
>
> dimension dum1(1), dum2(1), dum3(1), dum4(1)
>
769,771c772,774
< DIMENSION XI(1), XIOLD(1), XIJ(1), ALPHA(1), ALDIF(1), RHS(1)
< DIMENSION A(1), VALSTR(1), SLOPE(1), ACCUM(1), IPIV(1), INTEGS(1)
< DIMENSION DALPHA(1), EALPHA(1) , FIXPNT(1)
---
> DIMENSION XI(*), XIOLD(*), XIJ(*), ALPHA(*), ALDIF(*), RHS(*)
> DIMENSION A(*), VALSTR(*), SLOPE(*), ACCUM(*), IPIV(*), INTEGS(*)
> DIMENSION DALPHA(*), EALPHA(*) , FIXPNT(*)
1260,1261c1263,1266
< DIMENSION D1(40), D2(40), ZV(40), SLOPE(1), ACCUM(1), VALSTR(1)
< DIMENSION XI(1), XIOLD(1), XIJ(1), ALDIF(1), FIXPNT(1)
---
> DIMENSION D1(40), D2(40), ZV(40), SLOPE(*), ACCUM(*), VALSTR(*)
> DIMENSION XI(*), XIOLD(*), XIJ(*), ALDIF(*), FIXPNT(*)
>
> dimension dumm(1)
1755c1760,1762
< DIMENSION XIOLD(1), ALDIF(1), VALSTR(1), WORK(MSTAR,1)
---
> DIMENSION XIOLD(*), ALDIF(*), VALSTR(*), WORK(MSTAR,*)
>
> dimension dumm(1)
1899,1900c1906,1907
< DIMENSION ALPHO(1), XI(1), XIOLD(1), XIJ(1), ALPHA(1)
< DIMENSION ALDIF(1), RHS(1), A(1), IPIV(1), INTEGS(3,1)
---
> DIMENSION ALPHO(*), XI(*), XIOLD(*), XIJ(*), ALPHA(*)
> DIMENSION ALDIF(*), RHS(*), A(*), IPIV(*), INTEGS(3,*)
1901a1909,1910
>
> dimension dummy(1)
2163,2164c2172,2173
< DIMENSION Q(NROW,1), Z(1), DF(NCOMP,1)
< DIMENSION XI(1), BASEF(620), ALPHO(1), DG(40)
---
> DIMENSION Q(NROW,*), Z(*), DF(NCOMP,*)
> DIMENSION XI(*), BASEF(620), ALPHO(*), DG(40)
2329c2338,2341
< DIMENSION Z(1), FSPACE(1), ISPACE(1)
---
> DIMENSION Z(*), FSPACE(*), ISPACE(*)
>
> dimension dumm(1)
>
2332c2344,2345
< CALL APPROX (ISPACE(5), X, Z, FSPACE(IS6), FSPACE, ISPACE,
---
> CALL APPROX (ISPACE(5), X, Z, FSPACE(IS6), FSPACE, ISPACE(1),
> c CALL APPROX (ISPACE(5), X, Z, FSPACE(IS6), FSPACE, ISPACE,
2374c2387
< DIMENSION Z(1), VN(1), XI(1), ALDIF(1), M(1), DMVAL(1)
---
> DIMENSION Z(*), VN(*), XI(*), ALDIF(*), M(*), DMVAL(*)
2482c2495
< DIMENSION VN(1), M(1)
---
> DIMENSION VN(*), M(*)
2532c2545
< DIMENSION VN(1), XI(1), M(1)
---
> DIMENSION VN(*), XI(*), M(*)
2612c2625
< DIMENSION BASEF(1), VN(1), XMESH(1)
---
> DIMENSION BASEF(*), VN(*), XMESH(*)
2889c2902
< DIMENSION ALDIF(1), ALPHA(1), XI(1), M(1)
---
> DIMENSION ALDIF(*), ALPHA(*), XI(*), M(*)
3004,3005c3017,3018
< DIMENSION UHIGH(1) , AR(20), ARM1(20)
< DIMENSION ALDIF(1), XIOLD(1)
---
> DIMENSION UHIGH(*) , AR(20), ARM1(20)
> DIMENSION ALDIF(*), XIOLD(*)

Related

MergeSort vs. antialising rule

I have the following implementation of the MergeSort algorithm in Fortran.
My question is about call merge(work(1 : half), A(half + 1:), A).
Obviously I have overlapping memory, but from looking at the code in merge, this should be no problem, as long as the input arrays are sorted. (Which they are assumed to be anyway.)
On the other hand Fortran compilers may assume non aliased memory,
so I always think "don't do this".
I have two questions now:
When and how can I run into problems with my merge subroutine.
If I cannot implement MergeSort like this, how do I do it without creating a temporary array.
!> Merge sorted arrays A and B into C while preversing order.
subroutine merge(A, B, C)
implicit none
integer, intent(in) :: A(:), B(:)
integer, intent(inout) :: C(:)
integer :: i, j, k
if (size(A) + size(B) > size(C)) abort
i = 1; j = 1
do k = 1, size(C)
if (i <= size(A) .and. j <= size(B)) then
if (A(i) <= B(j)) then
C(k) = A(i)
i = i + 1
else
C(k) = B(j)
j = j + 1
end if
else if (i <= size(A)) then
C(k) = A(i)
i = i + 1
else if (j <= size(B)) then
C(k) = B(j)
j = j + 1
end if
end do
end subroutine merge
recursive subroutine MergeSort(A, work)
implicit none
integer, intent(inout) :: A(:)
integer, intent(inout) :: work(:)
integer :: half
half = (size(A) + 1) / 2
if (size(A) < 2) then
continue
else if (size(A) == 2) then
call naive_sort(A)
else
call MergeSort(A( : half), work)
call MergeSort(A(half + 1 :), work)
if (A(half) > A(half + 1)) then
work(1 : half) = A(1 : half)
! TODO: Non aliasing rule.
call merge(work(1 : half), A(half + 1:), A)
endif
end if
end subroutine MergeSort
PS: As you perhaps notice, the array C in the merge subroutine is declared as an inout parameter, because it is later used with overlapping memory.
This use of aliasing in calling merge is erroneous.
With
call merge(work(1 : half), A(half + 1:), A)
the dummy argument B is associated with A(half+1:) and the dummy argument C with A which is the understood overlap.
This aliasing means that the elements of B may not be defined (which is additionally required by the intent) and that the last few elements of C may not be defined.
However, if we look at the main loop in merge we see that in general every element of C appears in a statement looking like C(k)=...: we expect at least one of those conditions inside to be true. This is therefore invalid.
To be clear: a statement like C(k)=B(j) would be an illegal definition even if the value of C(k) doesn't change as a result.
Fortunately, perhaps, there is an easy way to create a temporary array to avoid aliasing: give the dummy argument B the value attribute. You could even do the same to A and remove the workspace array.

OpenMP reduction into array of C++ template-specified size causes undefined behaviour

I'm new to OpenMP, but am trying to use it to accelerate some operations on entries of a 2D array with a large number of rows and a small number of columns. At the same time, I am using a reduction to calculate the sum of all the array values in each column. The code looks something like this (I will explain the weird bits in a moment):
template <unsigned int NColumns>
void Function(int n_rows, double** X, double* Y)
{
#pragma omp parallel for reduction(+:Y[:NColumns])
for (int r = 0; r < n_rows; ++r)
{
for (int c = 0; c < NColumns; ++c)
{
X[r][c] = some_complicated_stuff(X[r], X[r][c]);
Y[c] += X[r][c];
}
}
}
To clarify, X is a n_rows x NColumns-sized 2D array allocated on the heap, and Y is a NColumns-sized 1D array. some_complicated_stuff isn't actually implemented as a separate function, but what I do to X[r][c] in that line only depends on X[r][c] and other values in the 1D array X[r].
The reason that NColumns is passed in as a template parameter rather than as a regular argument (like n_rows) is that when NColumns is known at compile-time, the compiler can more aggressively optimise the inner loop in the above function. I know that NColumns is going to be one of a small number of values when the program runs, so later on I have something like this code:
cin >> n_cols;
double** X;
double Y[n_cols];
// initialise X and Y, etc. . .
for (int i = 0; i < n_iterations; ++i)
{
switch (n_cols)
{
case 2: Function< 2>(X, Y); break;
case 10: Function<10>(X, Y); break;
case 60: Function<60>(X, Y); break;
default: throw "Unsupported n_cols."; break;
}
// . . .
Report(i, Y); // see GDB output below
}
Through testing, I have found that having this NColumns "argument" to Update as a template parameter rather than a normal function parameter actually makes for an appreciable performance increase. However, I have also found that, once in a blue moon (say, about every 10^7 calls to Function), the program hangsā€”and even worse, that its behaviour sometimes changes from one run of the program to the next. This happens rarely enough that I have been having a lot of trouble isolating the bug, but I'm now wondering whether it's because I am using this NColumns template parameter in my OpenMP reduction.
I note that a similar StackOverflow question asks about using template types in reductions, which apparently causes unspecified behaviour - the OpenMP 3.0 spec says
If a variable referenced in a data-sharing attribute clause has a type
derived from a template, and there are no other references to that
variable in the program, then any behavior related to that variable is
unspecified.
In this case, it's not a template type per se that is being used, but I'm sort of in the same ballpark. Have I messed up here, or is the bug more likely to be in some other part of the code?
I am using GCC 6.3.0.
If it is more helpful, here's the real code from inside Function. X is actually a flattened 2D array; ww and min_x are defined elsewhere:
#pragma omp parallel for reduction(+:Y[:NColumns])
for (int i = 0; i < NColumns * n_rows; i += NColumns)
{
double total = 0;
for (int c = 0; c < NColumns; ++c)
if (X[i + c] > 0)
total += X[i + c] *= ww[c];
if (total > 0)
for (int c = 0; c < NColumns; ++c)
if (X[i + c] > 0)
Y[c] += X[i + c] = (X[i + c] < min_x * total ? 0 : X[i + c] / total);
}
Just to thicken the plot a bit, I attached gdb to a running process of the program which hanged, and here's what the backtrace shows me:
#0 0x00007fff8f62a136 in __psynch_cvwait () from /usr/lib/system/libsystem_kernel.dylib
#1 0x00007fff8e65b560 in _pthread_cond_wait () from /usr/lib/system/libsystem_pthread.dylib
#2 0x000000010a4caafb in omp_get_num_procs () from /opt/local/lib/libgcc/libgomp.1.dylib
#3 0x000000010a4cad05 in omp_get_num_procs () from /opt/local/lib/libgcc/libgomp.1.dylib
#4 0x000000010a4ca2a7 in omp_in_final () from /opt/local/lib/libgcc/libgomp.1.dylib
#5 0x000000010a31b4e9 in Report(int, double*) ()
#6 0x3030303030323100 in ?? ()
[snipped traces 7-129, which are all ?? ()]
#130 0x0000000000000000 in ?? ()
Report() is a function that gets called inside the program's main loop but not within Function() (I've added it to the middle code snippet above), and Report() does not contain any OpenMP pragmas. Does this illuminate what's happening at all?
Note that the executable changed between when the process started running and when I attached GDB to it, which required referring to the new (changed) executable. So that could mean that the symbol table is messed up.
I have managed to partly work this out.
One of the problems was with the program behaving nondeterministically. This is just because (1) OpenMP performs reductions in thread-completion order, which is non-deterministic, and (2) floating-point addition is non-associative. I assumed that the reductions would be performed in thread-number order, but this is not the case. So any OpenMP for construct that reduces using floating-point operations will be potentially non-deterministic even if the number of threads is the same from one run to the next, so long as the number of threads is greater than 2. Some relevant StackOverflow questions on this matter are here and here.
The other problem was that the program occasionally hangs. I have not been able to resolve this issue. Running gdb on the hung process always yields __psynch_cvwait () at the top of the stack trace. It hangs around every 10^8 executions of the parallelised for loop.
Hope this helps a little.

Why does it output error crash?

I am writing a code to analyze a game, and I have a problem.
This code goes through every combination of 7 six-sided dices (from 1111111 to 6666666) and for every combination it sees if the combination makes some points or not. So I tried to check if it could put in the console every dice-combinations and the points associated just to check and it ran fine until 1223353 but at 1223354 it "crashed", as the image shows.Here we can see the console running my code.
So I don't understand why it just stops after ~10'000 iterations.
P.S.: I tried to run it in code blocks and it didn't work either...
Thank you for your answers!
Ok, when the debugger gets to this line it crashes:
if (sptopt[k]==sptopt[j]){ // here k == 3 and sptopt.size() == 3
sptopt.erase(sptopt.begin()+k); // this line crashes
sdesopt.erase(sdesopt.begin()+k);
soptch.erase(soptch.begin()+k);
}
I have looked at the state of the variables at the time of the crash and indeed:
k == 3 and
sptopt.size() == 3
Basically you are looping and erasing from a vector (which is very very inefficient from a memory perspective), and not checking that value of k is not equal/higher than the size of your vectors.
This is the stack I got:
Thread 1Queue : com.apple.main-thread (serial)
#0 0x00007fff95687f49 in _platform_memmove$VARIANT$Haswell ()
#1 0x000000010001b8ab in std::__1::enable_if<(is_same<std::__1::remove_const<int>::type, int>::value) && (is_trivially_copy_assignable<int>::value), int*>::type std::__1::__move<int, int>(int*, int*, int*) [inlined] at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:1904
#2 0x000000010001b856 in int* std::__1::move<int*, int*>(int*, int*, int*) [inlined] at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:1913
#3 0x000000010001b802 in std::__1::vector<int, std::__1::allocator<int> >::erase(std::__1::__wrap_iter<int const*>) [inlined] at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1676
#4 0x000000010001b675 in main at /Users/**/Documents/iosapps/Chat App/newdaf/newdaf/main.cpp:604
Every time you are about to access a vector that changed in size in a loop, you must add checks such as:
if ( ( k < sptopt.size() ) && ( j < sptopt.size()) &&
( k < sdesopt.size() ) && ( j < sdesopt.size()) &&
( k < soptch.size() ) && ( j < soptch.size()) ...
Otherwise you access/erase an element that does not exist. In the case of deletion you get a runtime error. When accessing only, C++ may not be so kind as telling you that you are not where you thought you were (it did enter the function with k being an invalid index), and your program from then on behaves very strangely.
So you need to look at your functions and make sure your variables never go over the dimensions of the vectors you are using.

Issues with Halide select statement

I'm trying to do some stencil computation using Halide. So assuming a basic 5 point 2D stencil, to evaluate some value at cell i,j I need the values of i-1,j i-2,j, i+1,j i+2,j. Now the way this works in C++ is that I have a for statement:
for(int i = 2; i < max_i - 2; i++)
for(int j = 2; j < max_j - 2; j++)
Calculate out = some_function_of(in(i,j), in(i-1,j), in(i-2,j), in(i+1,j), in(i+2,j))
Now I'm trying to do the same thing with Halide. so I have a Buffer called in which has the same value as my input array in the C++ code. And I have a Func called out:
out(i,j) = select(i >= 2 && j >= 2, some_function_of(in(i,j), in(i-1,j), in(i-2,j), in(i+1,j), in(i+2,j)) ,0.0f)
When I run this code I get the following error:
Error:
Input buffer b0 is accessed at -1, which is before the min (0) in dimension 0
Aborted (core dumped)
From my understanding, the reason for this error is that the select statement evaluates both statements so eventhough I don't want to calculate anything for i and j values less than two, the function is evaluated at i = 0 and j = 0 and thus the invalid address access.
So is there anyway to do this in Halide? Are there any other equivalents for if/else statements?
Using a boundary condition will do what you want:
Func unbounded;
unbounded(i, j,) = some_function_of(in(i,j), in(i-1,j), in(i-2,j), in(i+1,j), in(i+2,j));
out(i, j) = BoundaryConditions::constant_exterior(unbounded, 0.0f, 2, width - 4, 2, height - 4)(i, j);
I believe you can use "Expr()" instead of "width - 4" or "height - 4" if you want the maximum unbounded.
The use if BoundaryConditions functions allows hinting the compiler which direction of the if/else construct is more likely.

Segmentation fault - invalid memory reference

Hey I am trying to get my LAPACK libraries to work and I have searched and searched but I can't seem to figure out what I am doing wrong.
I try running my code, and I get the following error
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 0x7FFB23D405F7
#1 0x7FFB23D40C3E
#2 0x7FFB23692EAF
#3 0x401ED1 in sgesv_
#4 0x401D0B in MAIN__ at CFDtest.f03:? Segmentation fault (core dumped)
I will paste my main code here, hopefully someone can help me with this problem.
****************************************************
PROGRAM CFD_TEST
USE MY_LIB
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
DIMENSION ET(0:10), VN(0:10), WT(0:10)
DIMENSION SO(0:10), FU(0:10), DMA(0:10,0:10)
DIMENSION DMA2(0:10,0:10), QN(0:10), WKSPCE(0:10)
INTEGER*8 :: pivot(10), inf
INTEGER*8 :: N
EXTERNAL SGESV
!SET THE PARAMETERS
SIGMA1 = 0.D0
SIGMA2 = 0.D0
TAU = 1.D0
EF = 1.D0
EXP = 2.71828182845904509D0
COST = EXP/(1.D0+EXP*EXP)
DO 1 N=2, 10
!COMPUATION OF THE NODES, WEIGHTS AND DERIVATIVE MATRIX
CALL ZELEGL(N,ET,VN)
CALL WELEGL(N,ET,VN,WT)
CALL DMLEGL(N,10,ET,VN,DMA)
!CONSTRUCTION OF THE MATRIX CORRESPONDING TO THE
!DIFFERENTIAL OPERATOR
DO 2 I=0, N
DO 2 J=0, N
SUM = 0.D0
DO 3 K=0, N
SUM = SUM + DMA(I,K)*DMA(K,J)
3 CONTINUE
OPER = -SUM
IF(I .EQ. J) OPER = -SUM + TAU
DMA2(I,J) = OPER
2 CONTINUE
!CHANGE OF THE ENTRIES OF THE MATRIX ACCORDING TO THE
!BOUNDARY CONDITIONS
DO 4 J=0, N
DMA2(0,J) = 0.D0
DMA2(N,J) = 0.D0
4 CONTINUE
DMA2(0,0) = 1.D0
DMA2(N,N) = 1.D0
!CONSTRUCTION OF THE RIGHT-HAND SIDE VECTOR
DO 5 I=1, N-1
FU(I) = EF
5 CONTINUE
FU(0) = SIGMA1
FU(N) = SIGMA2
!SOLUTION OF THE LINEAR SYSTEM
N1 = N + 1
CALL SGESV(N,N,DMA2,pivot,FU,N,inf)
DO 6 I = 0, N
FU(I) = SO(I)
6 CONTINUE
PRINT *, pivot
1 CONTINUE
RETURN
END PROGRAM CFD_TEST
*****************************************************
The commands I run to compile are
gfortran -c MY_LIB.f03
gfortran -c CFDtest.f03
gfortran MY_LIB.o CFDtest.o -o CFDtest -L/usr/local/lib -llapack -lblas
I ran the command
-fbacktrace -g -Wall -Wextra CFDtest
CFDtest: In function _fini':
(.fini+0x0): multiple definition of_fini'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o:/build/buildd/glibc-2.19/csu/../sysdeps/x86_64/crti.S:80: first defined here
CFDtest: In function data_start':
(.data+0x0): multiple definition ofdata_start'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o:(.data+0x0): first defined here
CFDtest: In function data_start':
(.data+0x8): multiple definition of__dso_handle'
/usr/lib/gcc/x86_64-linux-gnu/4.9/crtbegin.o:(.data+0x0): first defined here
CFDtest:(.rodata+0x0): multiple definition of _IO_stdin_used'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o:(.rodata.cst4+0x0): first defined here
CFDtest: In function_start':
(.text+0x0): multiple definition of _start'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o:(.text+0x0): first defined here
CFDtest: In function_init':
(.init+0x0): multiple definition of _init'
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crti.o:/build/buildd/glibc-2.19/csu/../sysdeps/x86_64/crti.S:64: first defined here
/usr/lib/gcc/x86_64-linux-gnu/4.9/crtend.o:(.tm_clone_table+0x0): multiple definition of__TMC_END'
CFDtest:(.data+0x10): first defined here
/usr/bin/ld: error in CFDtest(.eh_frame); no .eh_frame_hdr table will be created.
collect2: error: ld returned 1 exit status
You haven't posted your code for MY_LIB.f03 so we cannot compile CFDtest.f03 exactly as you have supplied it.
(As an aside, the usual naming convention is that f90 in a .f90 file is not supposed to imply the language version being targeted. Rather, .f90 denotes free format while .f is used for fixed format. By extension, your .f03 files would be better (i.e., more portable if) named as .f90.)
I commented out the USE MY_LIB line and ran your code through nagfor -u -c cfd_test.f90. The output, broken down, is
Extension: cfd_test.f90, line 13: Byte count on numeric data type
detected at *#8
Extension: cfd_test.f90, line 15: Byte count on numeric data type
detected at *#8
Byte counts are not portable. The kind value for an 8-byte integer is selected_int_kind(18). (Similarly you might like to use a kind(0.0d0) kind value for your double precision data.)
Error: cfd_test.f90, line 48: Implicit type for I
detected at 2#I
Error: cfd_test.f90, line 50: Implicit type for J
detected at 2#J
Error: cfd_test.f90, line 54: Implicit type for K
detected at 3#K
Error: cfd_test.f90, line 100: Implicit type for N1
detected at N1#=
You have these implicitly typed, which implies they are 4-byte (default) integers. You should probably declare these explicitly as 8-byte integers (using the 8-byte integer kind value above) if that's what you intend.
Questionable: cfd_test.f90, line 116: Variable COST set but never referenced
Questionable: cfd_test.f90, line 116: Variable N1 set but never referenced
Warning: cfd_test.f90, line 116: Unused local variable QN
Warning: cfd_test.f90, line 116: Unused local variable WKSPCE
You need to decide what you intend to do with these, or whether they are just deletable cruft.
With the implicit integers declared explicitly, there is further output
Warning: cfd_test.f90, line 116: Variable SO referenced but never set
This looks bad.
Obsolescent: cfd_test.f90, line 66: 2 is a shared DO termination label
Your DO loops would probably be better using the modern END DO terminators (not shared!)
Error: cfd_test.f90, line 114: RETURN is only allowed in SUBROUTINEs and FUNCTIONs
This is obviously easy to fix.
For the LAPACK call, one source of explicit interfaces for these routines is the NAG Fortran Library (through the nag_library module). Since your real data is not single precision, you should be using dgesv instead of sgesv. Adding USE nag_library, ONLY: dgesv and switching to call dgesv instead of sgesv, then recompiling as above, reveals
Incorrect data type INTEGER(KIND=4) (expected INTEGER) for argument N (no. 1) of DGESV
so you should indeed be using default (4-byte integers) - at least for the LAPACK build on your system, which will almost certainly be using 4-byte integers. Thus you might want to forget all about kinding your integers and just use the default integer type for all. Correcting this gives
Array supplied for scalar argument LDA (no. 4) of DGESV
so you do need to add this argument. Maybe pass size(DMA2,1)?
With this argument added to the call the code compiles successfully, but without the definitions for your *LEGL functions I couldn't go through any run-time testing.
Here is my modified (and pretty-printed) version of your program
Program cfd_test
! Use my_lib
! Use nag_library, Only: dgesv
Implicit None
Integer, Parameter :: wp = kind(0.0D0)
Real (Kind=wp) :: ef, oper, sigma1, sigma2, tau
Integer :: i, inf, j, k, n, sum
Real (Kind=wp) :: dma(0:10, 0:10), dma2(0:10, 0:10), et(0:10), fu(0:10), &
so(0:10), vn(0:10), wt(0:10)
Integer :: pivot(10)
External :: dgesv, dmlegl, welegl, zelegl
Intrinsic :: kind, size
! SET THE PARAMETERS
sigma1 = 0._wp
sigma2 = 0._wp
tau = 1._wp
ef = 1._wp
Do n = 2, 10
! COMPUATION OF THE NODES, WEIGHTS AND DERIVATIVE MATRIX
Call zelegl(n, et, vn)
Call welegl(n, et, vn, wt)
Call dmlegl(n, 10, et, vn, dma)
! CONSTRUCTION OF THE MATRIX CORRESPONDING TO THE
! DIFFERENTIAL OPERATOR
Do i = 0, n
Do j = 0, n
sum = 0._wp
Do k = 0, n
sum = sum + dma(i, k)*dma(k, j)
End Do
oper = -sum
If (i==j) oper = -sum + tau
dma2(i, j) = oper
End Do
End Do
! CHANGE OF THE ENTRIES OF THE MATRIX ACCORDING TO THE
! BOUNDARY CONDITIONS
Do j = 0, n
dma2(0, j) = 0._wp
dma2(n, j) = 0._wp
End Do
dma2(0, 0) = 1._wp
dma2(n, n) = 1._wp
! CONSTRUCTION OF THE RIGHT-HAND SIDE VECTOR
Do i = 1, n - 1
fu(i) = ef
End Do
fu(0) = sigma1
fu(n) = sigma2
! SOLUTION OF THE LINEAR SYSTEM
Call dgesv(n, n, dma2, size(dma2,1), pivot, fu, n, inf)
Do i = 0, n
fu(i) = so(i)
End Do
Print *, pivot
End Do
End Program
In general your development experience will be the most pleasant if you use as good a checking compiler as you can get your hands on and if you make sure you ask it to diagnose as much as it can for you.
As far as I can tell, there could be a number of problems:
Your integers with INTEGER*8 might be too long, maybe INTEGER*4 or simply INTEGER would be better
You call SGESV on double arguments instead of DGESV
Your LDA argument is missing, so your code should perhaps look like CALL DGESV(N,N,DMA2,N,pivot,FU,N,inf) but you need to check whether this is what you want.