fortransequencereorganize

Re-organising the data with desired sequence


I revise my posted question. Here is my Fortran code.

line  1   PROGRAM COMPA
line  2   IMPLICIT NONE
line  3   
line  4   INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(15,14)
line  5   INTEGER            :: i, j, k, l
line  6   REAL (KIND=dp)     :: ap(116,6), lr(3,3), pl(3), ns(2,116)
line  7   
line  8   OPEN (UNIT=3, FILE='data.dat', STATUS='OLD')
line  9   READ (UNIT=3, FMT=*)
line 10   READ (UNIT=3, FMT=*)
line 11   DO i = 1, 3, 1
line 12      READ (UNIT=3, FMT=*) pl
line 13      lr(i,:) = pl
line 14   END DO
line 15   READ (UNIT=3, FMT=*)
line 16   DO i = 1, 116, 1
line 17      READ (UNIT=3, FMT=*) pl
line 18      ap(i,4:6) = pl
line 19      ns(:,i) = i
line 20   END DO
line 21   
line 22   DO i = 1, 116, 1
line 23      ap(i,1) = ap(i,4)*lr(1,1)+ap(i,5)*lr(2,1)+ap(i,6)*lr(3,1)
line 24      ap(i,2) = ap(i,4)*lr(1,2)+ap(i,5)*lr(2,2)+ap(i,6)*lr(3,2)
line 25      ap(i,3) = ap(i,4)*lr(1,3)+ap(i,5)*lr(2,3)+ap(i,6)*lr(3,3)
line 26   END DO
line 27   
line 28   DO i = 2, 116, 1
line 29      l = i
line 30      DO j = 1, i-1, 1
line 31         IF ((ap(l,1) < ap(j,1)) .OR. &
line 32            ((ap(l,1) == ap(j,1)) .AND. (ap(l,2) < ap(j,2))) .OR. &
line 33            ((ap(l,1) < ap(j,1)) .AND. (ap(l,2) == ap(j,2)) .AND. &
line 34            (ap(l,3) < ap(j,3)))) THEN
line 35            k = ns(1,i)
line 36            ns(1,j+1:i) = ns(1,j:i-1)
line 37            ns(1,j) = k
line 38            l = j
line 39         END IF
line 40      END DO
line 41   END DO
line 42   
line 43   OPEN (UNIT=4, FILE='compare.dat', STATUS='UNKNOWN')
line 44   DO i = 1, 116, 1
line 45      DO j = 1, 116, 1
line 46         IF (ns(1,j) == i) WRITE (UNIT=4, FMT=*) ns(:,j), ap(j,1:3)
line 47      END DO
line 48   END DO
line 49   
line 50   CLOSE (UNIT=3)
line 51   CLOSE (UNIT=4)
line 52   STOP
line 53   END PROGRAM COMPA

My code reads the following data.dat file content. and ap(i,4:6) stores the original data from the file; while, ap(i,1:3) stores the data after processing ap(i,4:6).

I want to re-organise the line number for each row, based on the ascending sequence for the 1st value in each row. If the 1st value is same in two or more rows; then, take the 2nd value for the ascending re-organising sequence. If the 2nd value is same in two or more rows; then, take the 3rd value for the ascending re-organising sequence.

Here is the data.dat file.

         116
 Parameter
   0.2951429939E+02    0.0000000000E+00    0.0000000000E+00
   0.0000000000E+00    0.1500000000E+02    0.0000000000E+00
   0.0000000000E+00   0.0000000000E+00   0.2510000038E+02
 Parameter
   0.000000000    0.500000000    0.300000012 
   0.041669998    0.500000000    0.328289986 
   0.041669998    0.500000000    0.384860009 
   0.000000000    0.500000000    0.413150012 
   0.000000000    0.500000000    0.469720006 
   0.041669998    0.500000000    0.498010010 
   0.041669998    0.500000000    0.554579973 
   0.000000000    0.500000000    0.582870007 
   0.083329998    0.500000000    0.300000012 
   0.125000000    0.500000000    0.328289986 
   0.125000000    0.500000000    0.384860009 
   0.083329998    0.500000000    0.413150012 
   0.083329998    0.500000000    0.469720006
...

Here is the compare.dat file, which was written by the code for the re-organised data.

   1.0000000000000000        1.0000000000000000        0.0000000000000000        7.5000000000000000        7.5300004152000044     
   2.0000000000000000        7.0000000000000000        1.2298607965527013        7.5000000000000000        13.919957533040389     
   3.0000000000000000        8.0000000000000000        0.0000000000000000        7.5000000000000000        14.630037397190604     
   4.0000000000000000        6.0000000000000000        1.2298607965527013        7.5000000000000000        12.500051440243805     
   5.0000000000000000        5.0000000000000000        0.0000000000000000        7.5000000000000000        11.789972329093603     
   6.0000000000000000        13.000000000000000        2.4594265091401013        7.5000000000000000        11.789972329093603     
   7.0000000000000000        16.000000000000000        2.4594265091401013        7.5000000000000000        14.630037397190604     
   8.0000000000000000        4.0000000000000000        0.0000000000000000        7.5000000000000000        10.370065458197006     
   9.0000000000000000        21.000000000000000        4.9191481317598029        7.5000000000000000        11.789972329093603     
   10.000000000000000        102.00000000000000        15.042847316209118        7.5000000000000000        14.464879495090205     
   11.000000000000000        114.00000000000000        13.527288986990197        7.5000000000000000        13.589893105343398     
   12.000000000000000        91.000000000000000        0.0000000000000000        7.5000000000000000        6.4399073735966041     
   13.000000000000000        69.000000000000000        23.365586106424487        7.5000000000000000        9.6599863721468040     
   14.000000000000000        83.000000000000000        27.054873530174486        7.5000000000000000        7.5300004152000044     
   15.000000000000000        84.000000000000000        28.284437826075518        7.5000000000000000        8.2400787733501950     
   16.000000000000000        24.000000000000000        4.9191481317598029        7.5000000000000000        14.630037397190604     
   17.000000000000000        104.00000000000000        17.216575554825518        7.5000000000000000        15.719879815290209     
   18.000000000000000        89.000000000000000        28.284437826075518        7.5000000000000000        13.919957533040389     
   19.000000000000000        64.000000000000000        20.905862978575517        7.5000000000000000        12.500051440243805     
   20.000000000000000        36.000000000000000        9.8380015632401978        7.5000000000000000        10.370065458197006     
   21.000000000000000        80.000000000000000        25.825011966250003        7.5000000000000000        12.500051440243805

Obviously, this re-organisation is wrong because the row was not written based on the ascending order.

Would anyone please give me some suggestions on what is wrong with my code? Thank you very much.


Solution

  • First for code clarity let's define a utility function tells if a row is "smaller" or not compared to another row (because it uses assumed shape arguments, this function must be in a module, or in the contain section of the main program):

    logical function is_smaller(rowa,rowb) result(s)
    real(dp), intent(in) :: rowa(:), rowb(:)
    s = .false.
    if (rowa(1) < rowb(1)) then
        s = .true.
    else if (rowa(1) == rowb(1)) then 
        if (rowa(2) < rowb(2)) then
            s = .true.
        else if (rowa(2) == rowb(2)) then 
            if (rowa(3) < rowb(3)) s= .true.
        end if
    end if
    end function
    

    Then let's use it with an insertion sort algorithm, which is is fine for such a number of elements to sort. For code clarity again we move the data instead of using indexes (indexes would be more efficient).

       real(dp) :: tmp(6)
       ...
       do i = 2, 116 
           ! the first (i-1) rows are sorted, we are now looking at row i
          do j = 1, i-1
             if (is_smaller(ap(i,:),ap(j,:))) then
                ! insertion of row i at position j
                tmp(:) = ap(i,:)
                ap(j+1:i,:) = ap(j:i-1,:)
                ap(j,:) = tmp(:)
                exit
             end if
          end do
       end do