I've written a short Fortran program that uses teams, but it doesn't function as expected. I would like to know whether my programming syntax is correct, or if there's a bug in my compiler.
I've been reading a book about Fortran 2018 and some of its newer implementations, including teams. Very few textbooks talk about teams, and the only one I could find, doesn't offer any program examples. I've written, compiled, and run a very short program that is supposed to print a value from one team, while working within another. The syntax seems fairly straight-forward, but the program doesn't work. I've compiled the program using the OpenCoarrays 2.7.1 compiler, as well as version 2.8.0.
program remote_team2
use iso_fortran_enf
implicit none
type(team_type) :: new_team
integer, codimension[*] :: tempnum
form team(1+mod(this_image(),2),new_team)
change team(new_team)
tempnum = num_images()
sync team(new_team)
select case (team_number())
case(1)
print *, 1, ' ', tempnum[2], ' ', num_images()
case(2)
print *, 2, ' ', tempnum[1], ' ', num_images()
end select
end team
end program remote_team2
If I run the program with 5 processors, cafrun -np 5 remote_team2, I would expect something like the following to print out at the screen:
2 3 2
1 2 3
2 3 2
1 2 3
2 3 2
Instead, I get the following:
2 3 3
1 2 2
2 3 3
1 2 2
2 3 3
I don't understand why it's not printing the number of images in the opposite team number, and then printing the number of images in the current team number. Instead, it just prints the same thing twice, indicating that square brace indexing, "[ ]", isn't working.
What am I doing wrong? Are there any Fortran 2018 programmers who may be able to explain this?
Thanks for your time.
Steve Lionel, thanks for the suggestion about looking into the association option with the change team statement. My book mentions this option, but, unfortunately, once again, there are no examples.
Based on the syntax that's described in the book, I have revised my program to look like the following:
program remote_team2
use iso_fortran_enf
implicit none
type(team_type) :: new_team
integer, codimension[*] :: tempnum
integer, codimension[2,*] :: tn
form team(1+mod(this_image(),2),new_team)
change team(new_team, tempnum[*] => tn)
tempnum = num_images()
sync team(new_team)
select case (team_number())
case(1)
print *, 1, ' ', tempnum[1, team_number = 2], ' ', num_images()
case(2)
print *, 2, ' ', tempnum[1, team_number = 1], ' ', num_images()
end select
end team
end program remote_team2
However, now my compiler gives me a syntax error for my change team statement. The error reads:
change team(new_team, tempnum[*] = > tn)
1
Error: Syntax error in CHANGE TEAM statement at (1)
The compiler also gives the following error message:
print *, 1, ' ', tempnum[1, team_number = 2], ' ', num_images()
1
Error: Function 'team_number' requires an argument list at (1)
It seems to think that I'm trying to use team_number as a function, rather than as an indexing option, as described in the book.
Without any published working examples to speak of, not in the book nor online, I don't know what the compiler wants me to do. The book generally shows a "reference book" representation of these definitions. So I'm never quite sure how these statements are actually supposed to look. However, in the case of how I've written both statements, they use the same options that are described in the book. Any suggestions, or ideas, are greatly appreciated.
You're not asking for tempnum from the "opposite team number", but rather from image 1 or 2 in your current team. Since the number of images in that team is the same across all images in the team, the results you see are correct.
When a team is formed and you do a CHANGE TEAM, the current team's image indexes are an ordered set starting at 1. You may want to look at the optional "associating coarray" argument to CHANGE TEAM.
I've recently learned, from one of the authors of the book I've been reading, that the syntax of my updated program is correct, and can even be simplified. He suggested that my compiler doesn't yet support the feature of accessing information between different teams.
At least I now know that my syntax is correct.
Related
As shown in the following code that I use to practice fixed-form Fortran (because the code I am trying to learn is fixed form Fortran), the 4th format statement and the reading from file 1 are newly added. The code worked as expected prior to adding these statements, but now the intel ifort compiler with no additional flags will not compile the 4th format statement and returns the following error:
fortPractice.for(18): error #5082: Syntax error, found FORMAT_ELEMENT 'format' when expecting one of: <END-OF-STATEMENT> ;
4 format(i6,2x)
--------------^
fortPractice.for(26): error #6052: This label has not been defined as a FORMAT label.
write(2,3)
----------------------------------^
The code is:
c This is a script for practicing Fortran codes
program fortPractice
implicit none
integer :: x(0:5),y(2:7)
integer :: nph(1:6)
real :: z(4:9)
integer :: i
OPEN(unit=1,file='test.txt',status='old')
read(1,*) nph
close(unit=1)
open(unit = 2, file = 'output.txt')
2 format(i3,2x,i3,2x,2e11.2)
3 format(1x,78('*'))
4 format(i6,2x)
do i = 0,5
x(i) = i;
y(i+2) = i+2;
z(i+4) = x(i)**2 + y(i+2)**2
z(i+4) = sqrt(z(i+4)) + 10000
write(2,2) x(i),y(i+2),z(i+4)
write(2,3)
enddo
write(2,*) nph
close(unit = 2)
endprogram fortPractice
Output is a file created by the program. test.txt contains just a row of numbers: 1 2 3 4 5 6
When I comment or remove the 4th format statement then the code compiles and runs as expected. As I am just learning how fixed form Fortran works, I am just interested in why the 4th format statement won't compile.
Edit:
I have replaced all the tabs with spaces, and the program with some more modification shown below can now compile, but the program does not produce the output file, likely encountered some run-time error:
Edit 2:
Nevermind, I forgot to change the file identifiers.
Thanks everyone!
Now we have enough information to solve the problem. In the troublesome source line, the label 4 is preceded by a tab. Tabs in Fortran source are not standard, but Intel Fortran (and many other compilers) support something called "tab source form". The way it works in ifort is as follows:
If the line starts with a tab and then a nonzero digit, the digit is treated as if it were in column 6
If the line starts with a tab and then some other character, then the character is treated as if it were in column 7
If the line starts with a numeric statement label and then a tab, the next character is treated as if it were in column 7
Otherwise, a tab is treated as a blank (this last varies among compilers)
In your case, a tab preceded the 4 so it was taken to be a continuation of the previous line, resulting in an error. Either don't use tabs, or understand how the compiler treats them. Editors that automatically insert tabs will just give you trouble.
Suppose I'm trying to write out a CSV file header that looks like this:
STRING1 2001, 2002, 2003, 2004,
And some variable-format Fortran90 code that does this is
INTEGER X<Y
X=2001
Y=2004
WRITE(6,'(A,(999(5X,I4,",")))') ' STRING1',(y,y=X,Y)
The "999" repeats the (5X,I4,",") format structure as many times as it needs to (up to 999 times, at least) to complete. Assume X and Y are subject to change and therefore the number of loop iterations may also change.
But if I want the header to look like this, with an additional string on the end of the sequence, like
STRING1 2001, 2002, 2003, 2004, STRING2
...I have tried adding another A toward the end of the format string, but that repeated variable format structure apparently doesn't know that it needs to "escape" when the integers are done with and so it errors out.
I can work around this by including 'ADVANCE="no"' in the format string and printing the second string using a new WRITE statement to get what I fundamentally want, but is there a way I can do this all with a single format structure?
[NOTE: no angle-bracket answers please; this is for GNU gfortran, which doesn't support that extension]
C'mon folks, get with the program!
This is standard Fortran 2008:
WRITE(6,'(A,*(5X,G0,:,","))') ' STRING1',(y,y=X,Y), ' STRING2'
I am fairly sure that gfortran supports the "indefinite group repeat count". G format was extended in Fortran 2008 to support any intrinsic data type, and a width of zero means "minimum number of characters." The colon is a F77 feature that stops the trailing comma from being emitted.
With this, ifort gives me:
STRING1 2001, 2002, 2003, 2004, STRING2
FWIW, I am not happy with your reuse of y as the loop control variable, since this is NOT a statement entity and will get set to 2005 at the end of the loop. Use a separate variable, please!
program test
character(len=20) :: N_number
integer :: X,Y
X=2001
Y=2004
write(N_number,*) Y-X+1
write(6,'(A,('//TRIM(N_number)//'(5X,I4,","))A)') ' STRING1',(y,y=X,Y),' STRING2'
end program test
It's a shame that the variable-format extension isn't standard. Since it isn't, most people recommend the approach shown by #anonymous. That is, instead of using <N>, you first convert the integer into a string using an internal-write statement. This string representation of N is then inserted within the format expression to be used in the write or print statements.1
Alternatively, you could convert the numerical values from the array into a string.2 It's also pretty straightforward. In the example below, I've shown both of these approaches.
program writeheader
implicit none
character(len=80) :: string1, string2, string3, fmt, num
integer, dimension(10) :: array
integer :: x,y,len
continue
string1 = "begin"
string3 = "end"
array = [1:10]
x = 3
y = 7
!! Method 1: Convert the variable number of values into a string, then use it
!! to create the format expression needed to write the line.
write(num, "(i)") y - x + 1
fmt = "(a,', ',(" // trim(adjustl(num)) // "(i0:', ')), a)"
print fmt, trim(string1), array(x:y), trim(string3)
!! Method 2: Convert the desired range of array values into a character string.
!! Then concat, and write the entire line as a string.
write(string2, "(*(', ',i0))" ) array(x:y)
len = len_trim(string2) + 1
print "(a)", trim(string1) // string2(1:len) // trim(string3)
end program writeheader
In either case shown in the example, the output looks like: begin, 3, 4, 5, 6, 7, end
1 If I can find it, I'll add a link to a nice solution here on SO that created a function to generate the format expression.
2 I've used the array bounds directly here, as an alternative to implied do-loops.
Say for example,
>>> a=5
>>> b=10
>>> if a!=0 and b:print 'Hello'
Hello
The above snippet works fine on python console in every other os and online interpreters.!
Now on removing the space after a!=0 and logical and, on python console in Mac or in any other online interpreters for python like TIO.
>>> a=5
>>> b=10
>>> if a!=0and b:print 'Hello' # note the difference
Hello
PFB the screenshot!
But the same doesn't seem to work on a python console in linux and windows and also in IDE like Eclipse with pydev plugin installed(Mars)
It'd be great if anyone could
throw light on this behaviour!
is it really pythonic to use the second snippet?
Note: realised this while working on few challenges in code golf-PPCG where the space really matters!
P.S. please correct me if I'm wrong!
If you're code golfing, go for it. It's terrible practice in normal code, but code golf throws out all standards of normal code quality anyway.
Python splits the 0 from the and in if a!=0and b much the same way as it splits the != from the 0 or the a from the !=. The source code gets fed through a tokenizer that splits it into elements known as tokens. Python's tokens include such things as number literals (12, 1.2, 1e4, 0xabc, etc.), names (foo, eggs, steve, etc.), keywords (if, and, while, etc.), and so on. When the tokenizer hits this point:
if a!=0and b
^
it sees that the longest valid token starting at the 0 is just 0 - it can't continue on and include the a or anything after that, because that doesn't fit any possible token format. Thus, it splits the 0 from the and.
I have this code (In Fortran 77)
CHARACTER*20 DICT(12) C column 9
DATA DICT/'aa','bb','for','cry','lug','bye','fly','ugly',
M'test1','test2', C Column 6
M'parasympathomimetic','thigmotropism'/ C column 6
I'm getting an error on this line "M'test1','test2'," , saying that it's a syntax error/unclassifiable statement. That line and the next line " M'parasympathomimetic','thigmotropism'/" are both on column 6 on my editor, yet the previous line is giving me problems.
I've tried moving that line 1 column over, removing the 'M', and nothing seems to make the program compile.
I'm compiling it as such:
f77 test.for
I know Fortran is in fixed form, so I'm not sure what I'm doing wrong here, any help would be much appreciated.
If the C Column 9 and C Column 6 are just comments present in your code, then to add a comment at the end of a line use the ! symbol, not C.
C234567
CHARACTER*20 DICT(12) ! column 9
DATA DICT/'aa','bb','for','cry','lug','bye','fly','ugly',
M'test1','test2', ! Column 6
M'parasympathomimetic','thigmotropism'/ ! column 6
Fortran 90 introduced free source form. A source file with the *.f90 extension denotes free source form code, i.e., Fortran 90/95/03/08/15. Fortran 2015 is the most recent standard and many popular compilers, including gfortran, support most of Fortran 2008.
In free source form the maximum line length is 132 characters, compared to the older limit of 72 characters. This reduces the possibility of text exceeding the limit, which could lead the compiler to misinterpret names.
Line continuations in free source form are performed by using a trailing ampersand character, &, rather than entering a character in column 6 of the following line.
For example, the following would be a legally continued line in FORTRAN 77 (assuming that the number 1 is actually in column 6):
x = 1 + 2 + 3 + 4
1 + 5 + 6
In free source form, a line can extend to the next line by having an ampersand as its last character.
x = 1 + 2 + 3 + 4 &
+ 5 + 6
In fixed source form, the first six columns are reserved for statement labels, with column 1 also used to indicate comment lines. In modern code, using structured control statements, statement labels are rare.
In free source form, any statement can begin in column 1. Free source form always uses the in-line comment style, indicated by using an exclamation mark. In-line comments can begin in any column.
Here is the same code in fixed format and in free source format:
C FIXED SOURCE FORM COMMENT
DO 10, I=1, 42
....
10 CONTINUE
! Free source form comment
do i=1, 42 ! Comments begin in any column
....
end do
Most importantly, with free source form, the concept of significant blanks was introduced. Here is a sample of a FORTRAN 77 fixed form statement showing what are now considered significant blanks
DO I T ER = 1 , MAX ITE R
followed by an equivalent statement without the blanks:
DO ITER=1, MAXITER
Free source form offers a number of advantages over the older fixed source form code. We recommend that it always be used in new code.
[This is a heavily re-edited version. Please ignore past versions of this question.]
A small python script using a sophisticated regex was provided by eyquem to identify numbers in a string and sanitize them. The test results cover over 50 samples, which I won't repeat here.
The question is, can someone adjust that regexp or provide a new one so that commas are treated more sanely?
In particular, I would like to see the following 4 test inputs produce the associated outputs.
' 4,8.3,5 ' -> '4' '8.3' '5'
' 44,22,333,888 ' -> '44' '22,333,888' #### Note that 44,22 is never a single number.
' 11,333e22,444 ' -> '11,333e22' '444' #### 11,333 is accepted in front of e22, but 22,444 is not accepted after it.
' 1,999 people found the code "i+=1999;" to be crystal clear in meaning and to likely lead to less than 1999 kilobytes extra memory consumption; however, the gains in 1, 999, and 1999 KB disk space are anything but ideal, especially this being 1999 and us having over $1,999 to work with! ' -> '1,999' '1999' '1999' '1' '999' '1999' '1999' '1,999'
Despite all the information, your post is actually vague. For starters, you didn't ask any questions. What is it you want?
Are you asking how to find all possible matches? In Perl, you can use
local our #matches;
/(...)(?{ push #matches, $1 })(?!)/
The (?!) never matches, so it causes the regex engine to backtrack to find another match, but the code block saves what it did find before doing that.
If you're asking to find any match, then it's quite easy to solve: Don't bother looking for option 2, because option 1 will always match what option 2 matches.