Two-column output format for a writing to .txt file - fortran

This is my code:
Program Output_manipulation
Implicit none
Integer::i, j, k, i_index_1, i_index_2
Integer,parameter:: Br_sn_cvo=3, Br_nn_cv=2, Br_nn_mre=2, Le=350
Character(Le),parameter:: fmtB_1_1 = "(*(2x,i3,'.',2x,f5.2,1x,'j',1x,f5.2))"
Complex,parameter:: S_pot=cmplx((2.3,3.4))
Open(Unit=15,File='Output.txt',Status='Unknown')
Do k = 1, Br_nn_mre
i_index_1= Br_sn_cvo + Br_nn_mre + 1 + Br_nn_cv*(k-1)
i_index_2= Br_sn_cvo + Br_nn_mre + 1 + k*Br_nn_cv-1
Write(15,fmtB_1_1)i_index_1,S_pot,i_index_2,S_pot
End Do
Close(Unit=15,Status='Keep')
End Program Output_manipulation
The content of Output.txt is:
6. 2.30 j 3.40 7. 2.30 j 3.40
8. 2.30 j 3.40 9. 2.30 j 3.40
I have a intention to get this content in Outpur.txt:
6. 2.30 j 3.40 8. 2.30 j 3.40
7. 2.30 j 3.40 9. 2.30 j 3.40
I do not have a idea how to create format for this kind of writing in .txt file.
Is there some way for doing that with implied do loop?
I want from code to write column afther column.

This is an old-school version with implied do-loop
Program Output_manipulation
Implicit none
Integer::i,j
Open(Unit=15,File='Output.txt',Status='Unknown')
Do j=1,3
Write(15,'(3(2x,i0,2x,"Thing_",i0))') (i+j,i,i=1,3)
End Do
Close(Unit=15,Status='Keep')
End Program Output_manipulation

In this snippet, only a single do-loop is used. The loop index irow ranges from 0:nrows-1, where nrows is any positive integer and so can be adjusted without changing the algorithm. The initial left-hand column label min can be calculated from any variables/parameters you want, e.g. min=a+b. You can also extend the technique shown here to write more than two columns using the same logic, but you will still only need one do-loop.
!! ... types used in this snippet:
implicit none
integer :: a, b, nrows, min, irow, idx_column1, idx_colum2
complex :: spot = complx(2.3,3.4)
character(len=48) :: form
!! ... other code, assignments, etc.
form = "(*(2x,i3,'.',2x,f5.2,1x,'j',1x,f5.2))"
min = a + b
do irow = 0, nrows-1
idx_column1 = min + irow
idx_column2 = min + nrows + irow
write(*, form) idx_column1, spot, idx_column2, spot
enddo
Example output, with nrows=3:
12. 2.30 j 3.40 15. 2.30 j 3.40
13. 2.30 j 3.40 16. 2.30 j 3.40
14. 2.30 j 3.40 17. 2.30 j 3.40
If the thing you're actually printing to each line is an array of variables, you can index into it using some combination of min, nrows, irow, idx_column1, idx_column2.
Style suggestions:
Please, use whitespace between your variables like you do between words when you write a sentence. For legibility, and all that.
Try to be more succinct in your loop indexing. For example, i=Br_sn_cvo+Br_nn_mre+1+Br_nn_cv*(k-1),Br_sn_cvo+Br_nn_mre+1+k*Br_nn_cv-1 is really hard to read, or (for me) to care to read. Do it at least for us poor souls on StackOverflow.
Notes:
You don't need to trim(adjustl("My Fun Format")). Try it, you'll see.

Related

loop was not vectorized because it contains a reference to a non-vector intrinsic

I am coding a large Fortran program where performance is extremely crucial. I'm using module to store common parameters and variables. But the problem is where ever there's a module variable is used for some kind of array operation the compiler doesn't vectorize it. Lets take this as an example,
module name
integer :: p
end module name
program name1
use name
real(kind=8) :: x(10,10), y(10)
integer :: i,j
p=9
do i=1,10
do j =1,10
x(i,j) = i+j
enddo
enddo
y = x(:,p)*x(:,p-1)
print *, y
end program name1
Now when I compile it on Cray (XC50) with ftn -eD file.f90, the produced .lst file shows,
9. program name1
10. ! implicit none
11. use name
12. real(kind=8) :: x(10,10), y(10)
13. integer :: i,j
14. do i=1,10
15. do j =1,10
16. x(i,j) = i+j
17. enddo
18. enddo
19.
20. y = x(:,p)*x(:,p-1)
ftn-6263 ftn: VECTOR NAME1, File = test.f90, Line = 20
A loop starting at line 20 was not vectorized because it contains a reference to a non-vector intrinsic on line 20.
21. print *, y
22. end program name1
23.
24.
I always thought that doing array operation with : will be easier for the compiler to vectorize it. But if using module variable is bad for vectorization then is it also bad to use module when performance is critical? Am I confusing something here? How to improve the performance for these cases?

gfortran and ifort gives different results

I am making a small code that will read numbers from 2.txt which is bunch of random real numbers, save it in a 2d array and pass it on the information to a subroutine. In the subroutine, I am assigning a particular dimension of this array to another matrix to save this for future calculation.
implicit none
double precision, allocatable :: x1(:,:)
integer :: nstep, nheatoms, k, i, j
open(unit=999,file="2.txt",status="old")
nstep = 5
nheatoms = 2
allocate(x1(3,nheatoms))
do k = 1, nstep
do i = 1, 3
do j = 1, nheatoms
read(999,*) x1(i,j)
end do
read(999,*)
end do
call diffusion(nstep,nheatoms,x1)
end do
stop
end
subroutine diffusion(nstep,nheatoms,qhecent)
implicit none
integer, intent (in) :: nheatoms, nstep
double precision :: qhecent(3,nheatoms)
integer :: j
double precision, allocatable :: qhestep(:,:)
integer :: nstepdiff, ncross
integer, save :: l = 0
double precision :: diff
l = l + 1
allocate(qhestep(nstep,nheatoms))
do j = 1, nheatoms
qhestep(l,j) = qhecent(3,j)
end do
if (l .gt. 1) then
do j = 1, nheatoms
write(*,*)qhestep(l,j), qhestep(l-1,j)
end do
end if
end subroutine
The 2.txt file is as follows:
1.0
2.1
3.2
-1.1
-2.2
-3.3
5.0
3.5
4.4
1.9
2.1
1.5
6.0
3.5
4.4
1.9
2.8
2.5
6.0
3.5
4.4
1.9
2.1
3.2
6.0
3.5
4.4
1.9
-4.3
7.9
Now if I compile with gfortran, most of the time I obtain the output as:
2.1000000000000001 -2.2000000000000002
1.5000000000000000 -3.2999999999999998
2.7999999999999998 2.1000000000000001
2.5000000000000000 1.5000000000000000
2.1000000000000001 2.7999999999999998
3.2000000000000002 2.5000000000000000
-4.2999999999999998 2.1000000000000001
7.9000000000000004 3.2000000000000002
which is expected. But if I run the code several times, an unknown number appear in the output, such as the example:
2.1000000000000001 -2.2000000000000002
1.5000000000000000 -3.2999999999999998
2.7999999999999998 1.2882297539194267E-231
2.5000000000000000 0.0000000000000000
2.1000000000000001 2.7999999999999998
3.2000000000000002 2.5000000000000000
-4.2999999999999998 2.1000000000000001
7.9000000000000004 3.2000000000000002
If I compile with ifort, then I obtain the output that have two zeros, which is wrong.
2.10000000000000 -2.20000000000000
1.50000000000000 -3.30000000000000
2.80000000000000 0.000000000000000E+000
2.50000000000000 0.000000000000000E+000
2.10000000000000 2.80000000000000
3.20000000000000 2.50000000000000
-4.30000000000000 2.10000000000000
7.90000000000000 3.20000000000000
I must stress that compiling on ifort most of the time gives correct results as in the case for gfortran. I am on a Mac OS High Sierra.
Thanks in advance.
Both compilers should give garbage results, as you are allocating qhestep in diffusion for each DO k loop. On exiting diffusion, qhestep is deallocated, so the accumulated information should be lost. That ifort returns the same heap address for qhestep on each call is misleading.
To overcome the problem, you should use allocate (qhestep(nstep,nheatoms)) before entering the DO k loop, then transfer the accumulation array in call diffusion.
That ifort gives your expected result is unfortunate, as it disguises a significant logic error. Each ALLOCATE basically provides a new memory location for the array.
You also provide no error tests when reading the file. I would recommend using iostat= for the reads and also report the data as it is read.
In summary, your approach gives the wrong result, which both compilers provide. The ifort results you provided are also wrong in some cases, but correct in others, which is misleading.

Calling Fortran subroutine from Julia. Arrays work, but integers don't

I have this simple Fortran 90 program:
subroutine apc_wrapper(i, j, k)
implicit none
integer*8, intent(in) :: i, j
integer*8, intent(out) :: k
double precision t
k = i + js
end subroutine
compiled as a shared library
gfortran -O2 -shared -fPIC apc_wrapper.f90 -o apc_wrapper.so
Now, I want to call this subroutine from Julia, with all integer arguments, like this
i = 2
j = 3
k = 0
ccall( (:apc_wrapper_, "./apc_wrapper.so"), Void, (Ptr{Int64}, Ptr{Int64}, Ptr{Int64}), &i, &j, &k)
But it won't work. k won't change its value and keep evaluating to 0.
But, if I do this
i = 2
j = 3
kk = [0]
ccall( (:apc_wrapper_, "./apc_wrapper.so"), Void, (Ptr{Int64}, Ptr{Int64}, Ptr{Int64}), &i, &j, kk)
That is, use an array to store the output, it works! After calling the subroutine, kk evaluates to
1-element Array{Int64,1}:
5
And I didn't change the Fortran code at all, it didn't even know it was dealing with an array, just a block of memory.
So, if Fortran is able to read blocks of memory (i and j were properly red) why isn't able to write into them?
I don't have any problem with this. Actually, I want to use an array as output but still, this behavior surprised me.
Well, Julia is a fast-paced developing language and it turns out that the &variable syntax is deprecated.
This would be the proper way to do this:
i = 2
j = 3
k = 0
i_ref = Ref{Int64}(i)
j_ref = Ref{Int64}(j)
k_ref = Ref{Int64}(k)
ccall( (:apc_wrapper_, "./apc_wrapper.so"), Void,
(Ref{Int64}, Ref{Int64}, Ref{Int64}),
i_ref, j_ref, k_ref)
and then k_ref.x will evaluate to 5.

DO loop increment problem in Fortran

I have a problem while using a do loop in fortran,
REAL W,V,X
DO 50 W = 0.5,5.0,0.5
DO 50 V = 10.0,1000.0,10.0
DO 50 X = 1.0,10,1.0
C=(W*V*X)/1000.0
WRITE(*,*) W,V,X,C
50 CONTINUE
STOP
END
If I gave this it is showing that only integers needs to be used in do loop, is there any way to give integers in do loop or any other way to do it?
Use integers as your looping indices
REAL W,V,X
INTEGER I,J,K
DO 50 I = 1,10
DO 50 J = 1,100
DO 50 K = 1,10
W = 0.5 * I
V = 10.0 * J
X = 1.0 * K
C=(W*V*X)/1000.0
WRITE(*,*) W,V,X,C
50 CONTINUE
STOP
END
You should be able to accomplish the same thing by incrementing a real variable by adding your step value, and using an if then to exit the loop. Clunky, but should work.
The last time I programmed in Fortran, I used punch cards and an IBM-360, so I'm not going to pretend I remember the syntax.

Formatting 2D Arrays in a fortran namelist input file

Im writing a namelist input file for a Fortran code. I know that if you have a 1D array, you can populate a range of elements by,
&namelist
array(10) = 0, 1, 2, ......., n
&END
is the equivalent of
&namelist
array(10) = 0
array(11) = 1
array(12) = 2
...
array(10 + n) = n
&END
I need to now write a 2d array. I want to do the shortest equivalent to
&namelist
array2d(1,1) = 1
array2d(1,2) = 2
&END
Can I write that as
&namelist
array2d(1) = 1, 2
&END
or do I need to write this as
&namelist
array2d(1,1) = 1, 2
&END
Wow, thanks for the question -- never heard of namelists before :) This is useful!! :) After a little testing, older gfortran versions have a problem with this. Let's say you have
program nltest
implicit none
integer :: a(3,3)
namelist /mylist/ a
a = 0
open(7, file='nlinput.txt')
read(7, nml = mylist)
write(*,*) a
end program nltest
read a whole array, a=1,2,3,4,5,6,7,8,9 : this works fine and reads a(1,1), a(2,1), ... as expected regardless of the compiler.
read an array slice, e.g. a(2,:)=1,2,3 : this works fine with ifort and gfortran 4.6.1, but with gfortran 4.3 it does not.
So to do what you want you should be able to write array2d(1,:) = 1,2 if the code is compiled with a recent compiler.