0

Thank you guys, all your advices are relevant, but I gave up of Fortran and translated my code to Python. There, with just 1 or 2 little bugs my code worked perfect

I wrote a program to solve a linear system using the Gauss method. I wrote all the algorithms, the forward elimination and the back substitution and I made a lot of others subroutines and I don't know anymore what's wrong, I don't if is something wrong with my code or if some problem programming in Fortran because I'm new in this language. I'll put my code below and the linear system that I should find a solution

PROGRAM metodo_Gauss
    IMPLICIT NONE

    REAL :: det_a_piv
    INTEGER :: n, i, j
    REAL, DIMENSION(:,:), ALLOCATABLE :: a, a_piv 
    INTEGER, DIMENSION(:), ALLOCATABLE :: p 
    REAL, DIMENSION(:), ALLOCATABLE :: b, x 

    PRINT*, "Entre com a dimensão n do sistema a ser resolvido"
    READ*, n

    ! allocate memory
    ALLOCATE(a(n, n))
    ALLOCATE(a_piv(n, n))
    ALLOCATE(p(n))
    ALLOCATE(b(n))
    ALLOCATE(x(n))

    CALL matriz_a(n, a)
    CALL vetor_b(n, b)

    a_piv(1:n, 1:n) = a(1:n, 1:n)

    DO i = 1, n
        x(i) = 0
    END DO

    CALL eliminacao(n, a, a_piv, p)

    det_a_piv = (-1) ** n
    DO j = 1, n
        det_a_piv = det_a_piv * a_piv(j, j)
    END DO

    IF (det_a_piv == 0) THEN

        PRINT*, "O sistema linear é indeterminado"

    ELSE IF (abs(det_a_piv) <= 1) THEN

        PRINT*, "O sistema linear é mal-condicionado"
    ELSE

        CALL substituicao(n, a_piv, p, b, x)
        PRINT*, "A solução do sistema é:"
        PRINT*, x
    END IF

END PROGRAM metodo_Gauss

SUBROUTINE matriz_a(n, a)
    IMPLICIT NONE

        INTEGER, INTENT(in) :: n
        REAL, DIMENSION(n,n), INTENT(inout) :: a


        INTEGER :: i, j !Indícios usados em loops para percorrer os arrays

    PRINT*, "Por favor digite os valores do elementos da matriz sistema linear seguindo pela ordem das linhas até o final:"

        DO i = 1, n
            DO j = 1, n
                READ*, a(i,j)
            END DO
        END DO

END SUBROUTINE matriz_a

SUBROUTINE vetor_b(n, b)
    IMPLICIT NONE

    INTEGER, INTENT(in) :: n
    REAL, DIMENSION(n), INTENT(inout) :: b

    INTEGER :: i 

    PRINT*, "Por favor entre com os elementos do vetor b:"

    DO i = 1, n
        READ*, b(i)
    END DO

END SUBROUTINE vetor_b

SUBROUTINE eliminacao(n, a, a_piv, p)
    IMPLICIT NONE


    INTEGER, INTENT(in) :: n
    REAL, DIMENSION(n, n), INTENT(in) :: a
    REAL, DIMENSION(n, n), INTENT(out) :: a_piv
    INTEGER, DIMENSION(n), INTENT(out) :: p


    INTEGER :: i, j, local, dim 
    REAL :: mult 

    DO i = 1, (n - 1)

        dim = n - 1

        CALL local_pivo(dim, a(i:n, i), local)

        a_piv(i, i:n) = a(local, i:n)
        a_piv(local, i:n) = a(i, i:n)

        p(i) = local

        DO j = (i + 1), n
                mult = (-1) * (a_piv(j,i) / a_piv(local,i))
                a_piv(j,i) = mult
                a_piv(j, j:n) = a_piv(j, j:n) + mult * a_piv(i, j:n)
        END DO

    END DO

END SUBROUTINE eliminacao

SUBROUTINE local_pivo(n, a, local)
    IMPLICIT NONE

    INTEGER, INTENT(in) :: n
    REAL, DIMENSION(n), INTENT(in) :: a
    INTEGER, INTENT(inout) :: local

    INTEGER :: i 

    local = 1


    DO i = 2, n
        IF ((ABS(a(i))) > ABS(a(local))) THEN
            local = i
        END IF
    END DO

END SUBROUTINE local_pivo

SUBROUTINE substituicao(n, a_piv, p, b, x)
    IMPLICIT NONE


    INTEGER, INTENT(in) :: n
    REAL, DIMENSION(n, n), INTENT(in) :: a_piv
    REAL, DIMENSION(n), INTENT(out) :: b, x
    INTEGER, DIMENSION(n), INTENT(in) :: p


    INTEGER :: i, j, k, l, pivo 
    REAL :: aux 


    DO i = 1, (n - 1)


        pivo = p(i)


        IF (pivo /= i) THEN
            aux = b(i)
            b(i) = b(pivo)
            b(pivo) = aux
        END IF

        DO j = (i + 1), n
            b(j) = a_piv(j, i) * b(j) + b(i)
        END DO

    END DO

    DO k = n, 1, -1
        IF (k == n) THEN
            x(n) = b(n) / a_piv(n, n)
        ELSE
            x(k) = (b(k) + a_piv(k, n) * x(n)) / a_piv(k, k)
            DO l = n, k, -1
                x(l) = x(l) + (a_piv(k, l) * x(l)) / a_piv(k, k)
            END DO
        END IF
    END DO



END SUBROUTINE substituicao

Here it is the system that I'm trying to solve

enter image description here

My input is:

4

4
3
2
2
2
1
1
2
2
2
2
4
6
1
1
2

5
8
3
1

My output is:

-40.5000000      -40.2500000      -3.75000000      -37.5000000 

But the output should be:

6.500000
-44.000000
72.000000
-16.500000
Giovana
  • 9
  • 4
  • What is the output you get, what are the problems? – albert May 10 '20 at 17:10
  • The output is giving me an array vector with elements all negatives and low numbers. It's not the linear system soluction. I don't know what are the problems, i already made a lot of changes – Giovana May 10 '20 at 17:17
  • Please add the result in the question and also the numbers you inputted into the program (probably 4 4 2 2 6 3 ....) – albert May 10 '20 at 17:21
  • i did it now, please help me D: – Giovana May 10 '20 at 17:41
  • You should, before you do anything else, put all your subroutines either into a module and *use-associate* them; or include them, in the same source file as the program, in a `contains` section. Either of these will enable the compiler to check that the subroutine calls match their expected signatures. See https://stackoverflow.com/questions/8412834/correct-use-of-modules-subroutines-and-functions-in-fortran for more on the topic, other questions and answers too. – High Performance Mark May 10 '20 at 17:48
  • This is not the error, i tried to do the INTERFACE that its de contains for subroutines and i had a lot of bugs – Giovana May 10 '20 at 18:26
  • 1
    Perhaps the fact that you found a lot of bugs when trying to implement features that check your code indicate that your code has a lot of bugs? – Ross May 10 '20 at 18:31
  • okay, challenge accepted – Giovana May 10 '20 at 18:41
  • tha bugs are all about assignments... – Giovana May 10 '20 at 18:49
  • It's probably not the what is causing the problem, but you have the intent for b wrong in the substituicao routine, it should be InOut, not Out. – Ian Bush May 10 '20 at 21:01
  • 1
    Two comments; 1) your matrix is singular, `det(A)=0`, 2) just out of curiosity, why are you trying to reinvent the wheel? Is it for educational purpose? My knowledge is that a lot of subroutines exist for solving this problem, have you checked math libraries written decades ago for solving this? – AboAmmar May 10 '20 at 22:24
  • Check your code on simple 2x2 matrix and find the issue this way. – rpoleski May 11 '20 at 10:44
  • 1
    @AboAmmar The matrix should not be singular - [Wolfram Alpha](https://www.wolframalpha.com/input/?i=Det%7B%7B4%2C+3%2C+2%2C+2%7D%2C+%7B2%2C+1%2C+1%2C+2%7D%2C+%7B2%2C+2%2C+2%2C+4%7D%2C+%7B6%2C+1%2C+1%2C+4%7D%7D+) – Vladimir F Героям слава May 11 '20 at 10:47
  • 3
    Note there is a difference between the image and the input data, bottom right element of the matrix! – albert May 11 '20 at 10:53
  • One problem is that in the `eliminacao` procedure, just before calling `local_pivo()`, you incorrectly set `dim=n-1`, instead it needs to be `dim=n-i+1`. There may still be other errors. Generally, I would recommend to set `n` inside `local_pivo` as `n=size(a)`, which is safer and cleaner. Similarly, I would use this everywhere else. – PetrH May 11 '20 at 16:41
  • Your input looks like it is listed as row major, and I am pretty sure fortran is column major... that could be an explation for the main problem. – Holmz May 11 '20 at 20:11
  • @IanBush you're right, i changed the intent to inout in this routine – Giovana May 11 '20 at 22:43
  • @AboAmmar the matrix isnt singular, but okay, ive already translated my code to python and everything gone well hahahahha it's for my numerical methods classes, and i'm studying physics that needs a lot of algorithms to do the models, its always important to know what goes on in the process – Giovana May 11 '20 at 22:46
  • @rpoleski good advice, thank you, i'll try this – Giovana May 11 '20 at 22:46
  • @PetrH you are right, i tried to make the dim=n-i+1 but how the bugs were still there i thought this was not the problem, but thats the right logical. Thank you for the advice, ill try to set n=size(a) later – Giovana May 11 '20 at 22:48
  • @Holmz im totally lost in fortran, i'm starting to use now and im totally confuse with matrix, because i use to work with arrays only in python, and fortran also is a stone age language hahahahhaa i dont know why the hell the teacher want us to use fortran omg – Giovana May 11 '20 at 22:50
  • Because Fortran is typically around 10 to 100 times faster than python for real work – Ian Bush May 12 '20 at 07:48
  • @IanBush Some of the Python is fast as fortran. At least the Python written in fortran seems to have the same performance. – Holmz May 13 '20 at 20:19
  • @Giovana don't complain about the teacher... my question was whether the data as show in the post, is intended to be row or column major? – Holmz May 13 '20 at 20:22

0 Answers0