difference between variable-status when opening a file - fortran

What is the difference between this two IOSTAT variable-status:
open(...., IOSTAT=openstatus)
open(...., IOSTAT=IOCHK)
Are they just two parameter that should give or get some result or the word iostat is a Fortran key to compile and has difference with openstatus or the other word?

openstatus and IOCHK are just to different integer variables. You can name them as you wish, it doesn't matter. The behavior is the same. If an error or end condition happens, the variable is set to some non-zero value.

Related

How to set a real number as a blank in Fortran?

I have a list of 500 numbers, and wanted to take a mean of every 10 numbers in that, successively, and thus create an output file with 50 data points. Then it will be further plotted.
But suppose in an interval of 10 all the 10 data are missing, i.e. blank, then I should be able to write correspondingly blank in the output file. But, if my output array is of real type, then I cannot write it as a blank character.
I even tried to create the output array as character type, but, it's showing problem that it cannot write real values to a character type variable.
My question has two points:-
Is there any way that I can store the real variable as blank?
or, How to store real values to character type variable?
I tried the following code to test :-
real r
r=''
write(*,*) r
The output 'r' shows some real value instead.
And for someone suggesting that I should write the output directly to file, I must tell, that I need that output array necessarily for further procedures upon it.
A Fortran real number is always a number, most often in the IEEE floating point format https://en.wikipedia.org/wiki/IEEE_754 . There are some special values, such as not-a-number (NaN) and +-infinity (+Inf, -Inf) but they won't be output as a blank either.
If I understand it correctly, you basically want some sort of an Option type.
You must either check whether the number contains this special value and output a blank if that is the case
if (ieee_is_nan(r)) then
write(*,*)
else
write (*,*) r
end if
or you would have to use some more complicated type
type my_type
real value
logical is_blank =.false.
end type
or you would have to use an allocatable real variable and liave it not allocated if it is blank
if (.not. allocated(r)) then
write(*,*)
else
write (*,*) r
end if

trying to write string in subroutine causing error

Due to some restriction on my assignment, F77 is used.
I am learning to use subroutine but I encounter error when trying to write string out.
PROGRAM test
IMPLICIT NONE
INTEGER a
CHARACTER*20 STR,str1
STR = 'Hello world'
a = 1
WRITE (*,*) a
WRITE (*,10) STR
CALL TEST(str1)
STOP
END
SUBROUTINE test(str2)
CHARACTER*20 str2
str2 = 'testing'
WRITE (*,10) STR2
RETURN
END
When trying to compile this code, it returns that 'Error: missing statement number 10'
Also, I have some other questions:
What does the *20 mean in CHARACTER*20 STR?
Is this the size of the string?
How about 10 in WRITE (*,10) STR? Is this the length of string to be written?
what does (*,*) mean in WRITE (*,*) a
As you can read for example here:
https://www.obliquity.com/computer/fortran/io.html
the second value given to write is an argument for the implicit format keyword, which is the label of a statement within the same program unit, a character expression or array containing the complete format specification, or an asterisk * for list-directed formatting.
Thus if you provide the data directly, you may want to use * there instead.
Otherwise, your program needs to have the label 10 at some line with formatting statement.
And yes, CHARACTER*20 STR means that the variable STR is of length 20, as you can read for instance here: https://www.obliquity.com/computer/fortran/datatype.html
The *20 after CHARACTER specifies the size of the CHARACTER variable (in this case 20 characters). FORTRAN doesn't use null-terminated strings like other languages, instead you have to reserve a specific number of characters. Your actual string can be shorter than the variable, but never longer.
The comma ( , ) in the write statement is used to separate the various arguments. Some versions of FORTRAN allow you to supply 'named' arguments but the default is the first argument is the file code to write to (a '*' implies the standard output). The second argument would be the line number of a FORMAT statement. There can be more arguments, you'd have to look up the specifics for the OPEN statement in your version of FORTRAN.
Some of your WRITE() statements are specifying to use the FORMAT statement found at lable '10'. But your sample doesn't provide any FORMAT statement, so this would be an error.
If you don't want to deal with a FORMAT statement, you can use an asterisk ( * ) as the second argument and then FORTRAN will use a general default format. That is what your first WRITE(,) is doing. It writes to 'stdout' using a general format.

How do I return the value after checking for a condition?

The following code has to check for an 'e' value such that the gcd(h,e)=1. Where 1
module great(p,q,e,d);
input p,q;
output e,d;
reg e,d;
h=((p-1)*(q-1));
always
begin
for(e=2;e<h;e=e+1)
begin
g1=gcd(h,e);
if(g1==1)
return e;
If, by "return a value", you mean spit out a value you can use in another module, you would use the output of this module as your "return" value. But even ignoring the return e, I don't think your code will work if you tried to run it, because it is too much like a programming language. There's several major things wrong:
You already declared output e,d so you can't declare two reg with the same name. You probably want output reg e,d instead.
You didn't declare a type for h or g1.
You have a for loop for e but e can never be anything other than 0 or 1 because you didn't set a size for it, so by default it is only 1-bit long. Even if it was big enough that you could increment it past 1, it's a wire type by default, and you can't make those kind of increments to a wire directly.
I assume gcd is some module you made somewhere else, but this isn't how you interconnect modules together. You can't call it like it's a function. You have to use wire and reg to connect the inputs and outputs of two modules together, almost like you're plugging components in.
Those are what stick out the most to me, anyway. I think you are coding your Verilog as if it were Python and that's what's causing these misunderstandings. Verilog is very, very different.

Converting integer to character in Fortran90

I am trying to convert an integer to character in my program in Fortran 90.
Here is my code:
Write(Array(i,j),'(I5)') Myarray(i,j)
Array is an integer array and Myarray is a character array, and '(I5)', I don't know what it is, just worked for me before!
Error is:
"Unit has neither been opened not preconnected"
and sometimes
"Format/data mismatch"!
'(I5)' is the format specifier for the write statement: write the value as an integer with five characters in total.
Several thing could go wrong:
Make sure that Myarray really is an integer (and not e.g. a real)
Make sure array is a character array with a length of at least five characters for each element
Take care of the array shapes
Ensure that i and j hold valid values
Here is a working example:
program test
implicit none
character(len=5) :: array(2,2)
integer,parameter :: myArray(2,2) = reshape([1, 2, 3, 4], [2, 2])
integer :: i, j
do j=1,size(myArray,2)
do i=1,size(myArray,1)
write(array(i,j), '(I5)' ) myArray(i,j)
enddo !i
enddo !j
print *, myArray(1,:)
print *, myArray(2,:)
print *,'--'
print *, array(1,:)
print *, array(2,:)
end program
Alexander Vogt explains the meaning of the (I5) part. That answer also points out some other issues and fixes the main problem. It doesn't quite explicitly state the solution, so I'll write that here.
You have two errors, but both have the same cause. I'll re-state your write statement explicitly stating something which is implicit.
Write(unit=Array(i,j),'(I5)') Myarray(i,j)
That implicit thing is unit=. You are, then, asking to write the character variable Myarray(i,j) to the file connected to unit given by the integer variable Array(i,j).
For some values of the unit integer the file is not pre-connected. You may want to read about that. When it isn't you get the first error:
Unit has neither been opened not preconnected
For some values of Array(i,j), say 5, 6 or some other value depending on the compiler, the unit would be pre-connected. Then that first error doesn't come about and you get to
Format/data mismatch
because you are trying to write out a character variable with an integer edit descriptor.
This answer, then, is a long way of saying that you want to do
Write(Myarray(i,j),'(I5)') array(i,j)
You want to write the integer value to a character variable.
Finally, note that if you made the same mistake with a real variable array instead of integer, you would have got a different error message. In one way you just got unlucky that your syntax was correct but the intention was wrong.

Check the input data type and whether it is empty or null

I am asking user to give a value at run time to do some calculations.
I want to test if the user entered value is a real/integer number, and if not then give a warning that the program is expecting a real/integer number here.
In addition, I would as well like to know how do we check if a particular variable at the moment is null or empty. i.e. I have declared a variable but what if at the time of calculation its value is null or empty or not yet set, in that case, the program shouldn't crash instead give a warning to provide a correct value.
Both these operations are much more easier in C++ and C#, but I couldn't find a way to do that in Fortran.
I guess that "null or empty" you mean whether a variable has been initialized: "not yet set". "null" has a particular meaning for Fortran pointer variables, but I suppose that this is not your question.
Fortran doesn't automatically give variables a special value before they are intentionally initialized so there is no easy way to check whether a variable has been initialized. One approach is to initialize the variable its declaration with a special value. That means that you need to know a special value that it will never obtain in the operation of the program. One possibility is to use the huge intrinsic:
program TestVar
real :: AVar = huge (1.0)
if ( AVar < huge (1.0) ) then
write (*, *) "Test 1: Good"
else
write (*, *) "Test 1: Bad"
end if
AVar = 2.2
if ( AVar < huge (1.0) ) then
write (*, *) "Test 2: Good"
else
write (*, *) "Test 2: Bad"
end if
end program TestVar
As warned by #arbautjc, this only works once, even in a subroutine. In a procedure, the initialization with declaration is only done with a first call. Also, if you change the variable type from this example, be sure to understand how huge works (e.g., Long ints in Fortran).