I'm trying to understand some Fortran code that was passed to me. This is the argument list in a subroutine:
INTEGER, INTENT(IN) :: NKT
REAL, INTENT(IN) :: NW2(NKT), VAR, SUE
REAL, INTENT(INOUT) :: MYSPC(NKT,NKT)
I understand the declarations of NKT, VAR, and SUE. But what is the meaning of "(NKT)" and "(NKT,NKT)" in NW2(NKT), MYSPC(NKT,NKT)? Does NKT specify the dimensions of the arrays NW2 and MYSPC? Or is it saying the subroutine stores the passed value in the NKTth position of NW2?
I'm really confused by the usage of () after a variable. It's not covered in the "Introduction to FORTRAN 90" book by Nyhoff. Any help would be appreciated.
(Code is a modified segment of Wavewatch, http://polar.ncep.noaa.gov/waves/wavewatch/)
In your example, NW2(NKT), is an array with NKT elements, MYSPC(NKT,NKT) is a NKTxNKT 2D array. If your Fortran book doesn't cover this, really, get a better book. If you have some previous programming experience, I recommend "Modern Fortran Explained" by Metcalf, Reid, and Cohen.
It's the old style of declaring an array. Your book probably emphasizes the new style of dimension () before the ::. Some might consider it an advantage of this style that arrays and scalars can be mixed on the same declaration, as is done in the second line of your example. I prefer the new style.
To possibly help you reconcile this with your book, consider that
REAL, INTENT(IN) :: NW2(NKT)
REAL, INTENT(INOUT) :: MYSPC(NKT,NKT)
is equivalent to
REAL, INTENT(IN), DIMENSION(NKT) :: NW2
REAL, INTENT(INOUT), DIMENSION(NKT,NKT) :: MYSPC
These are two ways of saying the same thing when declaring arrays.
Related
I'm new to Fortran. I was given a file that is supposed to be in Fortran 90, but written to be compiled with the Lahey Fujitsu compiler (the sparse documentation states that it should be compiled with lf95 filename.f -out compiled_name #imsllf95.cmd). However, some lines are commented with c, which as I understand was the way to comment in Fortran 77. Also, matrices are declared like REAL*8, DIMENSION(23,8) :: xxx19, which again I think is from Fortran 77.
For the most part, I can compile the file with gfortran or ifort except for a section that requires the computation of a matrix inverse. Apparently, in the LF95 compiler (using a propietary module IMSLF90), a matrix inverse was computed with .i.. If I delete those inversions, the file compiles and runs with no problem (apart from the fact that it gives the wrong result).
I'm trying to find the version of Fortran this code is written in, so that I can then search for some code written in that same version so that I can invert the matrices in the code.
EDIT: The file has extension .f, even though the compiling instructions seem to imply that it is Fortran 95.
Here I have some sections of the code:
PROGRAM estimate_group
implicit none
INTEGER :: i,j,k,full,group1
REAL*8, DIMENSION(500) :: theta_start,theta_input
OPEN(68, STATUS="REPLACE",file='fit_measures.txt')
c OPEN(68, file='fit_measures.txt')
REWIND(68)
DO full=1,1
PRINT *, "=================================="
PRINT *, "FULL LOOP #: ", full
PRINT *, "=================================="
WRITE(68, *) "=================================="
WRITE(68, *) "FULL LOOP #: ", full
WRITE(68, *) "=================================="
DO group1=2,28
c Additional If statement to focus on top level and scale
c IF ( ((group1>=22) .AND. (group1<=28)) .OR. (group1==2)) THEN
IF ( group1==2) THEN
c READING IN THETA VECTOR FROM PREVIOUS ITERATIONS
c (starting values taken from prior runs theta output)
c ====================================================
IF ((group1==2) .AND. (full==1)) THEN
theta_input=0.0*theta_input
OPEN(67, file='theta_input1.txt')
REWIND(67)
DO i=1,500
READ(67,*) theta_input(i)
END DO
ELSE
theta_input=0.0*theta_input
OPEN(66,file='theta_input.txt')
REWIND(66)
DO i=1,500
READ(66,*) theta_input(i)
END DO
END IF
SUBROUTINE estimate(group1, theta_start)
INTEGER, INTENT(IN) :: group1
REAL*8, INTENT(IN), DIMENSION(500) :: theta_start
c Variable Declarations:\
INTEGER :: i,j,k,m,l,t0,i0,improve,max_m
REAL*8, DIMENSION(23,8) :: xxx19
xxx19(1:23,1) = (/554.0,541.1,583.3,593.2,615.8,582.0,582.5,546.5,
& 538.4,494.1,503.3,494.1,486.9,478.6,432.6,439.6,
& 380.4,355.4,305.9,271.8,254.6,208.8,202.8/)
Real*8 is not part of Fortran, and has never been part of Fortran. So the strict answer to your question is it is not Fortran of any vintage.
However going on what you have shown apart from Real*8 it is Fortran 90 or later. Fixed source form is still part of the language (though I would fail any students I have for using it) so it not an indicator of the vintage of the code. However after a quick look at the above I can see the following features which came into the standard language in Fortran 90:
Mixed case (outside character variables and constants)
Underscore in symbol name
Implicit None
:: in variable declarations and comma separated attribute lists
Variable names longer than 6 characters
Double inverted commas (") to delimit character strings
Do ... End Do (I assume you have missed out the End Do for some reason as otherwise the fragments above make no sense whatsoever)
== to test equality
Intent for dummy arguments
Array sections
Array constructors
There may be others.
I would like to use deferred-length character strings in a "simple" manner to read user input. The reason that I want to do this is that I do not want to have to declare the size of a character string before knowing how large the user input will be. I know that there are "complicated" ways to do this. For example, the iso_varying_string module can be used: https://www.fortran.com/iso_varying_string.f95. Also, there is a solution here: Fortran Character Input at Undefined Length. However, I was hoping for something as simple, or almost as simple, as the following:
program main
character(len = :), allocatable :: my_string
read(*, '(a)') my_string
write(*,'(a)') my_string
print *, allocated(my_string), len(my_string)
end program
When I run this program, the output is:
./a.out
here is the user input
F 32765
Notice that there is no output from write(*,'(a)') my_string. Why?
Also, my_string has not been allocated. Why?
Why isn't this a simple feature of Fortran? Do other languages have this simple feature? Am I lacking some basic understanding about this issue in general?
vincentjs's answer isn't quite right.
Modern (2003+) Fortran does allow automatic allocation and re-allocation of strings on assignment, so a sequence of statements such as this
character(len=:), allocatable :: string
...
string = 'Hello'
write(*,*)
string = 'my friend'
write(*,*)
string = 'Hello '//string
write(*,*)
is correct and will work as expected and write out 3 strings of different lengths. At least one compiler in widespread use, the Intel Fortran compiler, does not engage 2003 semantics by default so may raise an error on trying to compile this. Refer to the documentation for the setting to use Fortran 2003.
However, this feature is not available when reading a string so you have to resort to the tried and tested (aka old-fashioned if you prefer) approach of declaring a buffer of sufficient size for any input and of then assigning the allocatable variable. Like this:
character(len=long) :: buffer
character(len=:), allocatable :: string
...
read(*,*) buffer
string = trim(buffer)
No, I don't know why the language standard forbids automatic allocation on read, just that it does.
Deferred length character is a Fortran 2003 feature. Note that many of the complicated methods linked to are written against earlier language versions.
With Fortran 2003 support, reading a complete record into a character variable is relatively straight forward. A simple example with very minimal error handling below. Such a procedure only needs to be written once, and can be customized to suit a user's particular requirements.
PROGRAM main
USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY: INPUT_UNIT
IMPLICIT NONE
CHARACTER(:), ALLOCATABLE :: my_string
CALL read_line(input_unit, my_string)
WRITE (*, "(A)") my_string
PRINT *, ALLOCATED(my_string), LEN(my_string)
CONTAINS
SUBROUTINE read_line(unit, line)
! The unit, connected for formatted input, to read the record from.
INTEGER, INTENT(IN) :: unit
! The contents of the record.
CHARACTER(:), INTENT(OUT), ALLOCATABLE :: line
INTEGER :: stat ! IO statement IOSTAT result.
CHARACTER(256) :: buffer ! Buffer to read a piece of the record.
INTEGER :: size ! Number of characters read from the file.
!***
line = ''
DO
READ (unit, "(A)", ADVANCE='NO', IOSTAT=stat, SIZE=size) buffer
IF (stat > 0) STOP 'Error reading file.'
line = line // buffer(:size)
! An end of record condition or end of file condition stops the loop.
IF (stat < 0) RETURN
END DO
END SUBROUTINE read_line
END PROGRAM main
Deferred length arrays are just that: deferred length. You still need to allocate the size of the array using the allocate statement before you can assign values to it. Once you allocate it, you can't change the size of the array unless you deallocate and then reallocate with a new size. That's why you're getting a debug error.
Fortran does not provide a way to dynamically resize character arrays like the std::string class does in C++, for example. In C++, you could initialize std::string var = "temp", then redefine it to var = "temporary" without any extra work, and this would be valid. This is only possible because the resizing is done behind the scenes by the functions in the std::string class (it doubles the size if the buffer limit is exceeded, which is functionally equivalent to reallocateing with a 2x bigger array).
Practically speaking, the easiest way I've found when dealing with strings in Fortran is to allocate a reasonably large character array that will fit most expected inputs. If the size of the input exceeds the buffer, then simply increase the size of your array by reallocateing with a larger size. Removing trailing white space can be done using trim.
You know that there are "complicated" ways of doing what you want. Rather than address those, I'll answer your first two "why?"s.
Unlike intrinsic assignment a read statement does not have the target variable first allocated to the correct size and type parameters for the thing coming in (if it isn't already like that). Indeed, it is a requirement that the items in an input list be allocated. Fortran 2008, 9.6.3, clearly states:
If an input item or an output item is allocatable, it shall be allocated.
This is the case whether the allocatable variable is a character with deferred length, a variable with other deferred length-type parameters, or an array.
There is another way to declare a character with deferred length: giving it the pointer attribute. This doesn't help you, though, as we also see
If an input item is a pointer, it shall be associated with a definable target ...
Why you have no output from your write statement is related to why you see that the character variable isn't allocated: you haven't followed the requirements of Fortran and so you can't expect the behaviour that isn't specified.
I'll speculate as to why this restriction is here. I see two obvious ways to relax the restriction
allow automatic allocation generally;
allow allocation of a deferred length character.
The second case would be easy:
If an input item or an output item is allocatable, it shall be allocated unless it is a scalar character variable with deferred length.
This, though, is clumsy and such special cases seem against the ethos of the standard as a whole. We'd also need a carefully thought out rule about alloction for this special case.
If we go for the general case for allocation, we'd presumably require that the unallocated effective item is the final effective item in the list:
integer, allocatable :: a(:), b(:)
character(7) :: ifile = '1 2 3 4'
read(ifile,*) a, b
and then we have to worry about
type aaargh(len)
integer, len :: len
integer, dimension(len) :: a, b
end type
type(aaargh), allocatable :: a(:)
character(9) :: ifile = '1 2 3 4 5'
read(ifile,*) a
It gets quite messy very quickly. Which seems like a lot of problems to resolve where there are ways, of varying difficulty, of solving the read problem.
Finally, I'll also note that allocation is possible during a data transfer statement. Although a variable must be allocated (as the rules are now) when appearing in input list components of an allocated variable of derived type needn't be if that effective item is processed by defined input.
I would like to do something like:
(in pseudo code)
For all x in my_namelist_list
Read(unit_number,nml=x)
...
some other operations
...
end
What is the type of a namelist? Is it possible to pass it as an argument?
subroutine generic_reading_of_namelist(namelist_argument)
Does someone knows any workaround solution to manipulate many name lists all together?
In short: namelist has no type because it is a statement, not a variable declaration. This means its use is quite limited: only as the nml = argument to I/O operations.
It is also a very old feature, as discussed here, whose functionality has changed little since its introduction.
So, what is most straightforward depends on what exactly you want to do. You could try to use one namelist for multiple purposes, for example, or design your own input file format for which you have a custom reading routine.
Edit:
Suppose you have an abstract type and some extensions in several modules:
module absTypeMod
implicit none
type, abstract :: absType
integer :: i = 0
contains
procedure(info), pass(this), public, deferred :: info
end type
abstract interface
subroutine info(this)
import :: absType
class(absType), intent(in) :: this
end subroutine
end interface
end module
module typeAMod
use absTypeMod
implicit none
type, extends(absType) :: typeA
private
integer :: j = 1
contains
procedure :: info => info_A
end type
contains
subroutine info_A(this)
class(typeA), intent(in) :: this
print*, 'i:', this%i, 'j:', this%j
end subroutine
end module
module typeBMod
use absTypeMod
implicit none
type, extends(absType) :: typeB
private
real :: k = 2.0
contains
procedure :: info => info_B
end type
contains
subroutine info_B(this)
class(typeB), intent(in) :: this
print*, 'i: ', this%i, ' k: ', this%k
end subroutine
end module
You can then make a factory module, which provides the logic for instantiating the concrete extensions based on some input. An example:
module factoryMod
use typeAMod
use typeBMod
private
public :: absType, factory
contains
subroutine factory(t, switch)
class(absType), allocatable, intent(out) :: t
character(*), intent(in) :: switch
select case(switch)
case('A')
allocate(typeA :: t)
case('B')
allocate(typeB :: t)
end select
end subroutine
end module
And use it in a test program:
program test
use factoryMod
implicit none
class(absType), allocatable :: foo
call factory(foo, 'A')
call foo%info() ! Output: i: 0 j: 1
call factory(foo, 'B')
call foo%info() ! Output: i: 0 k: 2.000000
end program
You can make this as fancy as you wish. I use here a simple string to select the actual type to allocate in factory, but I've also used an implementation where I pass the iunit of a connected input namelist file to the factory. In that case, the factory can use this file not only to determine the type to create, but also to perform a further type-specific setup, whether in the factory itself or in some kind of type-bound initialisation routine (using the same input file).
Also note that this example factory is a subroutine and not a function, since the assignment foo = factory('A') is not allowed in Fortran 2003. It is no longer prohibited by F2008, but support is currently not universal.
In Fortran, is there a way to pass a statement label through a wrapper function?
To elaborate, I am writing a wrapper for open(), like so:
program test
contains
subroutine my_open(unit, file, err)
integer, intent(in) :: unit
character(*), intent(in) :: file
integer, intent(in), optional :: err
if (present(err)) then
open(unit, FILE=file, ERR=err)
else
open(unit, FILE=file)
end if
end subroutine my_open
end program test
(of course my actual procedure contains more logic …). But gfortran complains
open(unit, FILE=file, ERR=err)
1
Error: Invalid value for ERR specification at (1)
Is there a way to do this?
The label corresponding to err has to be a label in the scoping unit of the open. So what you want to do isn't possible. Also, to answer your more general question, passing labels as variable isn't possible in itself (at least, since Fortran 95 which deleted assigned formats and gotos).
However, for the specific case, using iostat instead, and passing control back to the calling subprogram is possible.
Something like (simplified):
call my_open(12, file, status)
! Instead of:
! 10 STOP
if (status.ne.0) then
!...
end if
end
subroutine my_open(unit, file, status)
integer, intent(in) :: unit
character(*), intent(in) ::file
integer, intent(out) :: status
open(unit, file=file, iostat=status)
if (iostat.ne.0) return
end subroutine
This is arguably much better than having what would essentially be a goto to a very different part of the code from the subroutine. [err isn't popular at the best of times.] Further, this status-passing can be generalized to other cases where you would want to pass labels.
I do not understand the behavior of the present() intrinsic function with pgf90 7.2. I wrote a 20 line sample program to test this, but the results still make no sense to me. Observe:
subroutine testopt(one,two,three,four,five)
implicit none
integer, intent(in) :: one,two
integer, intent(out) :: three
integer, intent(in), optional :: four
integer, intent(out), optional :: five
three = one + two
print *,"present check: ",present(four),present(five)
if (present(four) .and. present(five)) then
five = four*four
end if
end subroutine testopt
if I: call testopt(1,2,(any variable)) from my main program, it prints: "present check: T F". However if I: call testopt(1,2,(any variable)) from a subprogram it prints: "present check: T T". I expected to see "present check: F F" in either case, because I am only calling the subroutine with the 3 non-optional arguments, and neither of the optional ones. I cannot fathom why it would behave this way, and this is causing a major bug in a program I am working on. I appreciate any insight. Thanks.
Are you placing this subroutine in a module and then having a "use" statement for that module in the calling routine (main program or subroutine)? A typical rule is that many of the advanced / new features of Fortran 90 require an explicit interface so that both the caller and callee pass the arguments consistently. The easiest and best way to accomplish this is with module / use. Just a guess...
In Modern Fortran optional arguments must be declared as optional in the calling function (either through a module or an explicit interface). In Fortran 77 it was possible to simply leave out the last argument, if it was a scalar number, so optional arguments could be passed without extra declaration in the calling routine. This might not have been part of the Fortran standard, but it was a helpful feature provided by wise compiler implementations. Unfortunately, Modern Fortran killed this awesome feature.