Read file and find index of value in array in Fortran - arrays

I am making user subroutine file of Abaqus.
However, in reading a file I met with a difficulty.
Since, it is Fortran 77 based, it is so hard to find exact solution.
My intention is to read a file where an 1X1 array is include. Then, to find an index of a value in the array.
My code to read a file is :
open (unit=99,file='D:\SIMULATION\dist.txt',status='old')
read (99,*) dist
close (99)
And the code for finding index of value in array is:
loc=minloc(abs(dist-1),1)
I think minloc is for Fortran 90, right?
Is there any function in Fortran 77 similar to minloc?

The code you've shown should compile and run as expected. I'm assuming that you are actually reading a 1xN array and that when you said "1X1" it was a typo - otherwise, there's no point in using minloc.
However, the error message you reported in a comment (An array-valued argument is required in this context) only occurs if you use the minloc intrinsic on a scalar value. Thus, my guess is that you did not declare dist as an array. Here is a quick example of what I mean:
! The contents of 'values.txt' are: -3.1, 4.1, 5.9, 2.6, -5.4
! Values may be separated by commas or blanks.
program get_min_dist
implicit none
real :: x ! <-- Cannot be used to represent an array.
real, dimension(5) :: a ! <-- An array of 5 reals. Do this instead.
integer :: loc, funit1
open(newunit=funit1, file="values.txt", status="old")
read(funit1,*) x
rewind(funit1)
read(funit1,*) a
close(funit1)
loc = minloc(abs(a-1),1) ! <-- I'm assuming there is a reason to
! subtract 1 from all values in the array
! loc = minloc(abs(x-1),1) ! <-- Error 'An array-valued arg is required`
print*, "x=",x
print*, "a=",a
print*, "index=", loc
print*, "value=", a(loc)
end program get_min_dist
With read(funit1,*) x the first value will be assigned when the file is read, resulting in the error message you have seen. With the array a, however, you get the expected output.
Your confusion regarding the need to use F77 compatible code may be due to the fact that Abaqus continues to provide examples and docs with F77-style fixed-formatting, and requires Fortran source code to be given the .f or .for extension1. By default, this extension tells ifort to expect fixed-format code2. However, any Fortran features supported by the version of the compiler you use is still valid - even in fixed-format, if you must. For further information about the availability of features from different Fortran versions, see your (Intel Fortran) documentation.
1 I'd be glad to know if this can be changed somehow, e.g. to allow the .f90 extension.
2 This setting can be changed in the Abaqus environment file, at least for the versions I've used (6.9-6.14). I don't think that has changed with newer releases, but maybe. I don't recommend changing it if you share the environment with other users without their consent, especially for newbies.

Related

Can't write to file in Fotran90

I can't understand why my Fortran90 program does not write to file anymore. It used to work some hours ago. I haven't modified that part of the code, nor I have introduced some conditions by virtue of which it should not write to file . On the next line i have put a print command which writes on terminal the same values that should be written to file, and this works.
open(500, file='data.dat')
write(500,fmt='(E14.4,E14.4)') A,B !this SHOULD be printed on unit 500
write(*, fmt='(E14.4,E14.4)') A,B ! this is printed on terminal
I have tried to change unit, but nothing changes. I have tried to open a new file with a new name and writing onto it, also in other parts of the code, even at the beginning, just after variables declaration. This does not seem to work either. It is so frustrating, because everything worked properly previously. What could have happened?
Using gfortran 5.3 under Linux and the following program (that is your code copy-pasted and the minimal boilerplate).
program hop
implicit none
double precision :: A, B
A = 1
B = 2
open(500, file='data.dat')
write(500,fmt='(E14.4,E14.4)') A,B !this SHOULD be printed on unit 500
write(*, fmt='(E14.4,E14.4)') A,B ! this is printed on terminal
end program hop
outputs 0.1000E+01 0.2000E+01 in the terminal and the exact same content in the file data.dat.
Is the write instruction in a program that hangs? Not seeing output might be related to i/o buffering.
Is the behaviour changing if you add the line
flush(500)
after the write instruction?
I have to write to file in a cycle. Now I open the file in the cycle having added position='append' and I close it at the end of the cycle. Just like
program pro
implicit none
integer (kind=2) :: i, A, B
do i=1,10
A=i
b=i+1
open(500, file='file.dat', position='append')
write(500, *) A, B
close(500)
enddo
That seems to work now.

fortran pass allocated array to main procedure

I have a module with a function which takes a starting and ending point and reads in a .txt some float value.
I wish that function to return a table which I do not know how large it will be before it starts.
I wish to use this function twice in the main program to make a third real array. But Fortran doesn't like it much.
Here is my code for the function :
module ReadData
!in this part, you need to know :
! -the starting (cannot be the first or second point)
! -end point
! -the file name (here : cham/comp or flow)
! change line 40 in case it is not AL026_Pd anymore
! -where it is on the file
implicit none
INTERFACE ReadP
MODULE PROCEDURE ReadDataPressure
END INTERFACE
private :: ReadDataPressure
contains
function ReadDataPressure (whereabout,StartingPoint,EndingPoint) result (P1)
!**********************
!**decla in variables**
character(50) :: whereabout !needed : cham/comp or flow
real(8) :: StartingPoint,EndingPoint
!************************
!**decla used variables**
character(50) :: FileNameConstructed
real(8) :: deltat,CurrentTime,pressure
integer(8) :: i,k
!**********************
!**decla out variable**
real(8),allocatable :: P1(:)
!start of the programe itself
write (FileNameConstructed,'(a,a,a)') "AL026_pd",whereabout,".txt"
open(20,file=FileNameConstructed,status='old',action='read')
read (20,*) deltat,pressure
read (20,*) CurrentTime,pressure
deltat=CurrentTime-deltat
!now deltaT is the loop counter, but we "lost" two usable line in the process
allocate (P1(1:int(((EndingPoint-StartingPoint)/deltat+1))))
k=1
do i=0,int((EndingPoint-2*deltat)/deltat)
read (20,*) CurrentTime,pressure
if (CurrentTime>StartingPoint) then
P1(k)=pressure
k=k+1
write(*,*) p1(k)
end if
end do
end function ReadDataPressure
End module
and I wish to do something like this in the main program
a=ReadP(comp,350,750)
b=ReadP(flow,350,750)
do i=1; lenght_of_a
m_ox(i)=squarreroot(a(i)-b(i))
end do
end then write it in another file.
I found : Share allocatable Arrays
FORTRAN - allocatable array in subroutine
but they did not help me.
One thinks perhaps
http://www.stanford.edu/class/me200c/tutorial_90/09_modules.html
is closer to the solution.
But they don't want a table at the end, they use Prod_A = PRODUCT(A) so you do not know the dimension of a, but can do product or sum. But I want to keep it whole.
In the main program you should be able to declare an allocatable array A and, if you have a Fortran 2003 compiler, do:
A = ReadDataPressure
Which is what you wish. This is allocation on assignment, which is part of Fortran 2003.
Why do you say that "fortran doesn't like it"? What are the specific error messages?
With compilers that don't support this it will be easier though less elegant to make the procedure a subroutine. Declare the array as allocatable in both the main program and the subroutine. Make it an intent (out) argument and allocate it in the subroutine.
P.S. Unless there are other aspects that you are not showing, setting up a module procedure for a single procedure seems pointless. I would leave off the interface and module procedure and make ReadDataPressure public so that it is directly called.
the mistake was :
character(50) :: whereabout
because there was
write (FileNameConstructed,'(a,a,a)') "AL026_pd",whereabout,".txt"
except that FileNameConstructed is also a character(50). (So i try to fit a 8+50+4 into 50).
But I was not able to see it before removing the private.
So thank MSB. You helped me a lot. I change whereabout in character(4) (since it feet my need perfectly) and so it is running

Icarus verilog dump memory array ($dumpvars)

I try to dump an array (reg [31:0] data [31:0]) but I can't do it successfully.
I've tried the way that is in the iverilog wiki:
integer idx;
for (idx = 0; idx < 32; idx = idx + 1)
$dumpvars(0,cpu_tb.cpu0.cpu_dp.cpu_regs.data[idx]);
It works, but 2 things happen.
A warning shows up: VCD warning: array word cpu_tb.cpu0.cpu_dp.cpu_regs.data[0] will conflict with an escaped identifier.
In GTKWave I have something like this in SST window: \data[0][31:0]
Is there any solution about that?
Thanks in advance and sorry for my English.
I have e-mailed the mailing list of Icarus Verilog. Here are some answers:
To dump an array word Icarus needs to escape the name so it is
compatible with the VCD dump format. That's what \data[0][31:0] is. It
is the zeroth 32-bit word of the data array. Because an escaped name
and an array name could now conflict Icarus produces the warning. It
would be best if it could check for an escaped identifier conflict and
only print a message when there is a problem, but as I remember this
was not possible.
We chose to use escaped identifiers so that all the dumpers could
handle array words. The other common choice is to only support them
using a special dump command that only works with certain dump
formats.
I agree it would be nice if we could make the warning more accurate,
but we are usually busy working on other things so minor annoyances
that appear to be complicated to fix do not often get fixed. As I
remember, and it has been a number of years, the issue is if you
search for the escaped identifier it find the array element and there
is no way in the VPI to search for the next occurrence. It's possible
that finding the array element in the Icarus search by name
implementation is a bug.
Cary
"To dump an array word Icarus needs to escape the name so it is
compatible with the VCD dump format. That's what \data[0][31:0] is.
It is the zeroth? 32-bit word of the data array. Because an escaped
name and an array name could now conflict Icarus produces the
warning. It would be best if it could check for an escaped identifier
conflict and only print a message when there is a problem, but as I
remember this was not possible."
...I don't think that there's a need to escape the names. Both VCS
(followed by fsdb2vcd) and CVC emit the name directly with no
problems. Cut and paste example shown below:
$var wire 5 `' IC_DrAd0 [3][4:0] $end $var wire 5 a' IC_DrAd0 [2][4:0]
$end $var wire 5 b' IC_DrAd0 [1][4:0] $end $var wire 5 c' IC_DrAd0
[0][4:0] $end
I realize the VCD spec doesn't define this, but I've had to fold in a
lot of these kinds of extensions into gtkwave over the years as other
tools generate these constructs. The escapes can cause save file
incompatibilities (missing signals) when trying to simulate on
iverilog versus VCS.
Over time, SV constructs likely will cause further things added to the
VCD files. AFAIK, the VCD part of the 1364 spec hasn't updated at all
since Verilog-XL. CVC gets around possible incompatibilities by
adding a +dump_arrays plusarg (and no, you don't have to loop on each
array element either).
-Tony
I also sent a mail to GTKWave creator Tony Bybell:
Hello,
The problem is that the compiler is not emitting those values into the
dump file. You'll have to get in contact with the iverilog
developers. I see the same problem if I run sim and compare against
another simulator such as CVC with +dump_arrays turned on which does
dump the arrays and they are visible in gtkwave.
http://iverilog.wikia.com/wiki/Release_Notes_Icarus_Verilog_0_9_2 |
Allow $dumpvars to accept array members for dumping,
...it looks like during "initial" time you might need to add a
$dumpvars statement for each array element you want dumped. I don't
know if the array name by itself works. Assigning each element to a
"wire" might work too.
I have never tried this functionality in iverilog so I don't know if
it works. You might have to experiment or ask the developers.
-Tony
I had a similar issue recently:
When dumping vars with the for cycle like the question, this vcd error happens:
ERROR: $dumpvars cannot dump a vpiConstant.
My workaround is to generate n wires with assign statement assigning it the respective array word like this:
reg [31:0] registers [31:0];
generate
genvar idx;
for(idx = 0; idx < 32; idx = idx+1) begin: register
wire [31:0] tmp;
assign tmp = registers[idx];
end
endgenerate
Now in GTKWave I have the generate blocks dumped correctly.

Writing in two different places unformatted files in Fortran

I am trying to write in two different places (the main program and a subroutine) unformatted files in my Fortran code. The problem is that when I do it, the results change and I suspect that it is because the memory assignment is overwriting the data that I am using to make the simulation in my CFD code. I ask: Is it possible that one can just use the unformatted file (to write) once in the code? I mean, I have to use the same file to save all my data and not with different files.
I copy and past the two parts of the code to show what I am want to describe:
In the main program, the loop is:
call numcar (isave,suffix)
longueur=index(nchamp,' ')-1
nfichier=nchamp(1:longueur)//suffix
longueur=index(nfichier,' ')-1
open(10,file=nfichier(1:longueur),form='unformatted')
write(10) real(uxn,4),real(uyn,4),real(wzn,4),real(ppo,4)
close(10)
! *****************************************
isave=isave+1
and in the subroutine, the loop is:
call numcar (isavediv,suffix1)
longueur1=index(ndiv,' ')-1
nfichier1=ndiv(1:longueur1)//suffix1
longueur1=index(nfichier1,' ')-1
open(20,file=nfichier1(1:longueur1),form='unformatted')
write(20) real(ppm,4)
close(20)
! *****************************************
isavediv=isavediv+1
All the variables all declared as IMPLICIT NONE in both main program and subroutine.
I solved my problem.
The problem was that I was using the channel number 20 and a colleague of mine told me that this channel is used by the computer or some devices to process data.
I changed it for channel number 10 and it worked good again.
Thank you for your comments.
Now it looks so:
open(10,file=nfichier1(1:longueur1),form='unformatted')
write(10) real(ppm,4)
close(10)

Ocaml implementation

I got a slight problem implementing arrays in ocaml. For example, when on the terminal(konsole) and I type
let tab = Array.make 5 6;
I have
val tab : int array = [|6; 6; 6; 6; 6|]
as an output. So it creates an array with a length of 5 and fills all the cases with 6. Okay I understand that part. But when I type it on a text editor like kate for example, save it and compile it it I get this error:
Error: Unbound value Array.make
I don't understand why it takes Array. make as a value in kate and it takes Array.make as a function in the terminal. I saved the file with the ".ml" extension and I compile it using ocamlc -o test name_of_file.
Any suggestions please? Thanks.
I compiled your program with ocamlc and it went fine (using OCaml 3.12.0).
I would guess that you are calling an old version of the compiler when you try to compile, perhaps one from when Array.make was still named Array.create. Perhaps when you installed the new version, you overwrote some of the files (such as the toplevel) but not others (such as the compiler). In order to check, compare the versions given by ocamlc -v and ocaml.
As for the message “Unbound value”, in OCaml, functions are values. The implementors did not differentiate between “Unbound value that is not a function” and “Unbound value that is a function”, but this is not the cause of the problem. The cause of your problem is that Array.make is unbound at all.
I found the error. It's a very stupid one. I saved my file as "array.ml". So during the compilation it created an array.cmi file and I think it kinda confused this file with the one found in .../lib/ocaml/array.cmi. I'm not really sure. So I renamed the file to "table.ml" and it compiled perfectly. It's crazy that it confused these two files

Resources