Rainflow algorithm - Fortran conversion to Matlab - fortran

I am trying to convert a Rainflow cycle counting algorithm which is in Fortran, which is a language I am not familiar with, into Matlab.
There is a ready made Rainflow I've downloaded for Matlab but that does not fit the requirements of my project so I'm trying to build one from scratch.
Here is the Fortran code:
INTEGER BUFFER (4096), INDEX, VALUE, RANGE, MEAN, X, Y
INDEX = 0
10 CONTINUE
call 'get next peak/valley', VALUE
INDEX = INDEX + 1
BUFFER (INDEX) = VALUE
20 CONTINUE
IF (INDEX.LT.3) THEN
not enough points to form a cycle
GOTO 10
ELSE
X = ABS (BUFFER(INDEX) - BUFFER(INDEX - 1))
Y = ABS (BUFFER(INDEX - 1) - BUFFER(INDEX - 2))
IF (X.GE.Y) THEN
c -- cycle has been closed
RANGE = Y
MEAN = (BUFFER(INDEX-1) + BUFFER(INDEX-2))/2
c -- remove the cycle
INDEX = INDEX - 2
BUFFER(INDEX) = BUFFER(INDEX+2)
c -- see if this value closes any more cycles
GOTO 20
ELSE
GOTO 10
END IF
END IF
I had downloaded f2matlab (a Fortran to Matlab converter) but it requires a Fortran compiler which I do not have.
The bits I don't really understand how I can convert are:
The call 'get next… line (is this an input()?)
The BUFFER(4096) etc (is this a bit large to be a matrix in matlab?)
The GOTO/CONTINUE structure.
What do they mean, in English (or Matlab)?
I have seen
How to translate fortran goto state to matlab
and
translating loop from Fortran to MATLAB
but they do not help me very much.

This
call 'get next peak/valley', VALUE
isn't (currently) syntactically valid Fortran and I'm not sure whether any compiler of yore would have understood it either. I guess that it means get a VALUE for use in the following bits of code.
INTEGER BUFFER (4096)
is a simple declaration that BUFFER is a vector of 4096 integers, nothing to scare Matlab in that volume of data.
Finally, GOTO is an unconditional jump and the number following it is the label of the line to jump to, so GOTO 10 means execute the line with label 10 next. It was fairly common in FORTRAN of the vintage you are showing us to jump to a CONTINUE statement which is, in this context, a no-operation, execution continues to the next line.
In another context, with DO loops CONTINUE would have marked the end of the block of code inside the scope of the loop and would have a subtly different effect.

Related

Declaring variables in Python 2.7x to avoid issues later

I am new to Python, coming from MATLAB, and long ago from C. I have written a script in MATLAB which simulates sediment transport in rivers as a Markov Process. The code randomly places circles of a random diameter within a rectangular area of a specified dimension. The circles are non-uniform is size, drawn randomly from a specified range of sizes. I do not know how many times I will step through the circle placement operation so I use a while loop to complete the process. In an attempt to be more community oriented, I am translating the MATLAB script to Python. I used the online tool OMPC to get started, and have been working through it manually from the auto-translated version (was not that helpful, which is not surprising). To debug the code as I go, I use the
MATLAB generated results to generally compare and contrast against results in Python. It seems clear to me that I have declared variables in a way that introduces problems as calculations proceed in the script. Here are two examples of consistent problems between different instances of code execution. First, the code generated what I think are arrays within arrays because the script is returning results which look like:
array([[ True]
[False]], dtype=bool)
This result was generated for the following code snippet at the overlap_logix operation:
CenterCoord_Array = np.asarray(CenterCoordinates)
Diameter_Array = np.asarray(Diameter)
dist_check = ((CenterCoord_Array[:,0] - x_Center) ** 2 + (CenterCoord_Array[:,1] - y_Center) ** 2) ** 0.5
radius_check = (Diameter_Array / 2) + radius
radius_check_update = np.reshape(radius_check,(len(radius_check),1))
radius_overlap = (radius_check_update >= dist_check)
# Now actually check the overalp condition.
if np.sum([radius_overlap]) == 0:
# The new circle does not overlap so proceed.
newCircle_Found = 1
debug_value = 2
elif np.sum([radius_overlap]) == 1:
# The new circle overlaps with one other circle
overlap = np.arange(0,len(radius_overlap), dtype=int)
overlap_update = np.reshape(overlap,(len(overlap),1))
overlap_logix = (radius_overlap == 1)
idx_true = overlap_update[overlap_logix]
radius = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)
A similar result for the same run was produced for variables:
radius_check_update
radius_overlap
overlap_update
Here is the same code snippet for the working MATLAB version (as requested):
distcheck = ((Circles.CenterCoordinates(1,:)-x_Center).^2 + (Circles.CenterCoordinates(2,:)-y_Center).^2).^0.5;
radius_check = (Circles.Diameter ./ 2) + radius;
radius_overlap = (radius_check >= distcheck);
% Now actually check the overalp condition.
if sum(radius_overlap) == 0
% The new circle does not overlap so proceed.
newCircle_Found = 1;
debug_value = 2;
elseif sum(radius_overlap) == 1
% The new circle overlaps with one other circle
temp = 1:size(radius_overlap,2);
idx_true = temp(radius_overlap == 1);
radius = distcheck(1,idx_true) - (Circles.Diameter(1,idx_true)/2);
In the Python version I have created arrays from lists to more easily operate on the contents (the first two lines of the code snippet). The array within array result and creating arrays to access data suggests to me that I have incorrectly declared variable types, but I am not sure. Furthermore, some variables have a size, for example, (2L,) (the numerical dimension will change as circles are placed) where there is no second dimension. This produces obvious problems when I try to use the array in an operation with another array with a size (2L,1L). Because of these problems I started reshaping arrays, and then I stopped because I decided these were hacks because I had declared one, or more than one variable incorrectly. Second, for the same run I encountered the following error:
TypeError: 'numpy.ndarray' object is not callable
for the operation:
radius = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)
which occurs at the bottom of the above code snippet. I have posted the entire script at the following link because it is probably more useful to execute the script for oneself:
https://github.com/smchartrand/MarkovProcess_Bedload
I have set-up the code to run with some initial parameter values so decisions do not need to be made; these parameter values produce the expected results in the MATLAB-based script, which look something like this when plotted:
So, I seem to specifically be having issues with operations on lines 151-165, depending on the test value np.sum([radius_overlap]) and I think it is because I incorrectly declared variable types, but I am really not sure. I can say with confidence that the Python version and the MATLAB version are consistent in output through the first step of the while loop, and code line 127 which is entering the second step of the while loop. Below this point in the code the above documented issues eventually cause the script to crash. Sometimes the script executes to 15% complete, and sometimes it does not make it to 5% - this is due to the random nature of circle placement. I am preparing the code in the Spyder (Python 2.7) IDE and will share the working code publicly as a part of my research. I would greatly appreciate any help that can be offered to identify my mistakes and misapplications of python coding practice.
I believe I have answered my own question, and maybe it will be of use for someone down the road. The main sources of instruction for me can be found at the following three web pages:
Stackoverflow Question 176011
SciPy FAQ
SciPy NumPy for Matlab users
The third web page was very helpful for me coming from MATLAB. Here is the modified and working python code snippet which relates to the original snippet provided above:
dist_check = ((CenterCoordinates[0,:] - x_Center) ** 2 + (CenterCoordinates[1,:] - y_Center) ** 2) ** 0.5
radius_check = (Diameter / 2) + radius
radius_overlap = (radius_check >= dist_check)
# Now actually check the overalp condition.
if np.sum([radius_overlap]) == 0:
# The new circle does not overlap so proceed.
newCircle_Found = 1
debug_value = 2
elif np.sum([radius_overlap]) == 1:
# The new circle overlaps with one other circle
overlap = np.arange(0,len(radius_overlap[0]), dtype=int).reshape(1, len(radius_overlap[0]))
overlap_logix = (radius_overlap == 1)
idx_true = overlap[overlap_logix]
radius = dist_check[idx_true] - (Diameter[0,idx_true] / 2)
In the end it was clear to me that it was more straightforward for this example to use numpy arrays vs. lists to store results for each iteration of filling the rectangular area. For the corrected code snippet this means I initialized the variables:
CenterCoordinates, and
Diameter
as numpy arrays whereas I initialized them as lists in the posted question. This made a few mathematical operations more straightforward. I was also incorrectly indexing into variables with parentheses () as opposed to the correct method using brackets []. Here is an example of a correction I made which helped the code execute as envisioned:
Incorrect: radius = dist_check(idx_true,1) - (Diameter(idx_true,1) / 2)
Correct: radius = dist_check[idx_true] - (Diameter[0,idx_true] / 2)
This example also shows that I had issues with array dimensions which I corrected variable by variable. I am still not sure if my working code is the most pythonic or most efficient way to fill a rectangular area in a random fashion, but I have tested it about 100 times with success. The revised and working code can be downloaded here:
Working Python Script to Randomly Fill Rectangular Area with Circles
Here is an image of a final results for a successful run of the working code:
The main lessons for me were (1) numpy arrays are more efficient for repetitive numerical calculations, and (2) dimensionality of arrays which I created were not always what I expected them to be and care must be practiced when establishing arrays. Thanks to those who looked at my question and asked for clarification.

How Declare Global variables [duplicate]

This question already has an answer here:
How to avoid declaring and setting the value of a variable in each subroutine?
(1 answer)
Closed 5 years ago.
I have a program that calls functions within the same program but I want to declare and initialize the variables on the top and access them at the end of the program.
!Declaration
INTEGER TOPCHORD,BOTCHORD, SUPPS, PURLINS;
!Initialization
! Define Layers for connecting lines
TOPCHORD = 32
BOTCHORD = 32
SUPPS = 36
PURLINS = 30
INTEGER FUNCTION IFLANGE1(IEND1,IEND2,ISUP)
IFLANGE1=TOPCHORD
SELECT CASE(IEND1)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
SELECT CASE(IEND2)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
RETURN
END
I get error that variable 'SUPPS' referenced but not set
You might want to have a look at the documentation - you're missing a couple of important statements. (Also try to always include implicit none -- this is very helpful for catching certain issues).
A slightly modified code that should compile is
!Declaration
INTEGER TOPCHORD,BOTCHORD, SUPPS, PURLINS;
!Initialization
! Define Layers for connecting lines
TOPCHORD = 32
BOTCHORD = 32
SUPPS = 36
PURLINS = 30
contains !Indicate that the program unit contains other procedures
INTEGER FUNCTION IFLANGE1(IEND1,IEND2,ISUP)
IFLANGE1=TOPCHORD
SELECT CASE(IEND1)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
SELECT CASE(IEND2)
CASE(2,4,6,8,9,10)
IFLANGE1=BOTCHORD
IF(ISUP.EQ.1)IFLANGE1=SUPPS
END SELECT
RETURN
END FUNCTION !End the function definition
END !This is a required end statement to say we've reached the end of the program
This isn't the nicest style etc. but has the minimum number of changes to compile.
For any slightly more complex program I would strongly recommend using modules for storing variables (and also procedures) that you want to access from different parts of the code.

ThinkPython Exercise 5.4 Koch Curve

I do not understand how the Koch Curve is drawn from using this function.
def koch(t, n):
"""Draws a koch curve with length n."""
if n<3:
fd(t, n)
return
m = n/3.0
koch(t, m)
lt(t, 60)
koch(t, m)
rt(t, 120)
koch(t, m)
lt(t, 60)
koch(t, m)
The fd(t, n) command means object 't' will move forward by amount 'n'.
The rt(t, 120) and lt(t, 60) commands means object 't' will turn right or left by the given angles.
So I gather that the author uses recursion in the function but I do not understand how it reiterates so many times with itself as I am a beginner and have very limited logic skills.
As an example say I called koch(t, 100) the if clause is by passed as n > 3 which leads to the next line of code which is m/3.0 so 100/3.0 is 33.3. This then leads to koch(t, 33.3) and as n > 3 still holds it reiterates again to produce koch(t, 11.1) and so forth until we reiterate it until we come to koch(t, 1.23).
Now as n = 1.23 and the if clause activates as soon as n < 3 we can run through the if conditionals block of code replacing all the koch(t, m) statements with fd(t, 1.23). As I see it fd(), lt(), fd(), rt(), fd, lt(), fd() should be activated only one time as n < 3 as soon as n = 1.23 or does it reiterate again with 1.23 / 3.0 and the code is ran again with koch(t, 0.41)? Maybe because an else clause does not exists to cancel the function, however the function does end and if I choose a higher value for n the koch curve is also larger making me more confused as there I can see no line in the code which tells me to reiterate this function n number of times.
I apologize for the lack of clarity as I do not understand how to explain this clearly.
I think you may be looking at this from the wrong end to try to work it out. Consider first what happens if you call koch(t,1). The if statement evaluates to false, and you can see that something like this is drawn:
_/\_
Now what if you call koch(t,3)? Try on a piece of paper and you'll see that each of the straight lines in the picture above is replaced by similar shape...
I found out my problem after reading about recursion and testing some print statements in my console. What I did not understand was why choosing a larger n (length) produced a larger fractal. Basically because choosing a larger n produces more nodes (children) on a recursive tree so choosing a larger n will produce more children nodes and only the last nodes (null nodes) when n < 3 occurs will the turtle t begin to draw and by this time there will be many null nodes if n is large.
To understand recursion even further including how recursion works when there are two or more recursive functions in the block of code as posed by this question I have included a link to a helpful thread and hopes it helps anybody else who is stuck on this question and needs help in understanding recursion.
Understanding recursion

Fortran's warning on a program for evaluating elliptic integrals

On internet, I found this program that demonstrate Evaluating elliptic integrals of first and second kinds (complete)
implicit none
real*8 e,e1,e2,xk
integer i, n
e=1.d-7
print *,' K K(K) E(K) STEPS '
print *,'------------------------------------------'
xk=0.d0
do i = 1, 20
call CElliptic(e,xk,e1,e2,n)
write(*,50) xk,e1,e2,n
xk = xk + 0.05d0
end do
print *,'1.00 INFINITY 1.0000000 0'
stop
50 format(' ',f4.2,' ',f9.7,' ',f9.7,' ',i2)
end
Complete elliptic integral of the first and second kind. The input parameter is xk, which should be between 0 and 1. Technique uses Gauss' formula for the arithmogeometrical mean. e is a measure of the convergence accuracy. The returned values are e1, the elliptic integral of the first kind, and e2, the elliptic integral of the second kind.
Subroutine CElliptic(e,xk,e1,e2,n)
! Label: et
real*8 e,xk,e1,e2,pi
real*8 A(0:99), B(0:99)
integer j,m,n
pi = 4.d0*datan(1.d0)
A(0)=1.d0+xk ; B(0)=1.d0-xk
n=0
if (xk < 0.d0) return
if (xk > 1.d0) return
if (e <= 0.d0) return
et n = n + 1
! Generate improved values
A(n)=(A(n-1)+B(n-1))/2.d0
B(n)=dsqrt(A(n-1)*B(n-1))
if (dabs(A(n)-B(n)) > e) goto et
e1=pi/2.d0/A(n)
e2=2.d0
m=1
do j = 1, n
e2=e2-m*(A(j)*A(j)-B(j)*B(j))
m=m*2
end do
e2 = e2*e1/2.d0
return
end
I have compiled it but I have received the following errors:
gfortran -Wall -c "gauss.f" (nel direttorio: /home/pierluigi/Scrivania)
gauss.f:53.9:
50 format(' ',f4.2,' ',f9.7,' ',f9.7,' ',i2)
1
Error: Invalid character in name at (1)
gauss.f:83.72:
if (dabs(A(n)-B(n)) > e) goto et
1
Warning: Deleted feature: Assigned GOTO statement at (1)
gauss.f:83.35:
if (dabs(A(n)-B(n)) > e) goto et
1
Error: ASSIGNED GOTO statement at (1) requires an INTEGER variable
gauss.f:48.18:
write(*,50) xk,e1,e2,n
1
Error: FORMAT label 50 at (1) not defined
Compilation failed.
Any suggestions please?
EDIT
I have read all your answers and thanks to you I managed to compile the program. I also have another curiosity and I do not know whether to write another question. In the meantime I modify this question. In my program, xk is increased by 0.05. Now I will that the program to read data from a file containing: the minimum value of xk; the maximum value of xk; the number of intervals. I thought:
open (10,file='data/test')
read (10,*) xkmi, xkma
read (10,*) nk
close (10)
lkmi = dlog(xkmi)
lkma = dlog(xkma)
ldk = (lkma-lkmi)/dfloat(nk-1)
In addition, the program must be modified in such a way that the result is written to another file. How can I change the rest of the program? Thank you very much.
Your source code file extension is f which, I think (check the documentation), tells gfortran that the file contains fixed source form. Until Fortran 90 Fortran was still written as if onto punched cards and the location of various bits and pieces of a line is confined to certain columns. A statement label, such as 50 in the first of the error messages, had to be in columns 1 - 6. Two solutions:
Make sure the label is in (some of) those columns. Or, better
Move to free source form, perhaps by changing the file extension to f90, perhaps by using a compilation option (check your documentation).
The error raised by the goto et phrase is, as your compiler has told you, an example of a deleted feature, in which the goto jumps to a statement whose label is provided at run-time, ie the value of et. Either tell your compiler (check ...) to conform to an old standard, or modernise your source.
Fix those errors and, I suspect, the other error messages will disappear. They are probably raised as a consequence of the compiler not correctly parsing the source after the errors.
Because the file has type ".f" gfortan is interpreting it as fixed-source layout. Trying compiling with the free-form layout by using compiler option -ffree-form and see if that works. This probably explains the error about the "invalid character". That statement not being recognized explains the "format not defined error". The "computed goto" is obsolete but valid Fortran. You can ignore that warning. If you wish, later you can modernize the code. For the remaining error, for the "assigned goto", declare "et" as an integer.
I would just do this
10 n = n + 1
! Generate improved values
A(n)=(A(n-1)+B(n-1))/2.d0
B(n)=dsqrt(A(n-1)*B(n-1))
if (dabs(A(n)-B(n)) > e) goto 10
and possibly compile as free form source as others have shown. The label et seems weird and non-standard, possibly a rare vendor extension.
You could also change the lines above to a do-loop with an exit statement (Fortran 90).
(The program compiled for me after the change).
I tested the subroutine and compared with matlab and it was not the same. It is very similar to the algorithm used in Abramowitz's book. Here is the one I wrote that works well, just for comparing.
subroutine CElliptic(m,K,E)
implicit none
real*8 m,alpha,E,K,A,B,C,A_p,B_p,C_0,pi,suma
integer j,N
N=100
alpha=asin(sqrt(m))
pi = 4.d0*datan(1.d0)
A_p=1.0
B_p=cos(alpha)
C_0=sin(alpha)
suma=0.0
do j=1,N
A=(A_p+B_p)/2.0d0
B=dsqrt(A_p*B_p)
C=(A_p-B_p)/2.0d0
suma=suma+2**(j)*C**2
A_p=A
B_p=B
end do
K=pi/(2*A)
E=(1-1.d0/2.d0*(C_0**2+suma))*K
end Subroutine CElliptic
best regards
Ed.

Need to convert following FORTRAN code to C++

Im a very poor programmer, and i was given a program to supposedly help me on my aerodynamic hw. but its in fortran, and im trying to use MATLAB to run this program. any help on converting it to a language matlab understands? (preferabbly c++)
program joukow
c
c computes joukowski airfoil and finds pressure coefficient
c currently set up for symmetric airfoil with sharp trailing edge
c and chord length equal to one.
c profile is written onto prof.dat and cp onto cp.dat
c implicit real*8(a-h,o-z)
complex z,zeta,cw
dimension uz(100),vz(100),xi(100),eta(100),cp(100)
dimension xout(100),yout(100)
open(unit=8,file='prof.dat',status='unknown')
open(unit=9,file='cp.dat',status='unknown')
b=1.d0
write(6,98)
format(2x,'input the radius of the a-circle in z plane')
read(5,99)a
format(f10.0)
xl=2.*a-1.+1./(2.*a-1.)
c xl=a+1./a
c chord=2.*xl
chord=2.+xl
del=a-b
c del =0.1d0
do 50 i=1,100
ri=i
theta=6.2832d0*ri/101.d0
x=-del+a*cos(theta)
y=a*sin(theta)
z=cmplx(x,y)
zeta=z+b**2/z
c
c xi and eta are coordinates of points on airfoil
c
xi(i)=real(zeta)
eta(i)=aimag(zeta)
cw=(1.-a**2/(z+del)**2)/(1.-b**2/z**2)
c
c uz and vz are velocity components on the airfoil assuming the free-stream
c speed is one.
c
uz(i)=real(cw)
vz(i)=-aimag(cw)
c
c xout and yout are airfoil coordinates where the leading edge is at (0,0)
c and the chordlength is one.
c
xout(i)=(xl+xi(i))/chord
yout(i)=eta(i)/chord
write(8,100)xout(i),yout(i)
format(2x,2f10.4)
continue
c
c now calculate the pressure coefficient cp
c
write(6,200)
format(2x,'pressure coefficients')
do 70 i=1,50
cp(i)=1.-(uz(i)**2+vz(i)**2)
write(9,100)xout(i),cp(i)
continue
stop
end
Matlab understands Fortran just fine -- check the documentation. And if that doesn't satisfy you, most of the lines in the program which do any computation could be typed into the Matlab console with very little modification. If you are a poor programmer, I suggest that you spend your time modifying the program into Matlab rather than into C++. I'll write more later if you don't get any better help than I have time for right now.
EDIT: first off, some information on using Fortran source files from Matlab. If you really don't want to (or can't or have performance reasons for not doing so) rewrite the Fortran into Matlab then turn it into a MEX file. Using f2c (or anything else, including your own time and effort) to first translate the Fortran into C or C++ seems pointless to me.
If you don't like that idea, here are some ideas on turning Fortran into Matlab.
First, all lines beginning with C or c are comments so you don't need to translate them. Start with your code:
complex z,zeta,cw
dimension uz(100),vz(100),xi(100),eta(100),cp(100)
dimension xout(100),yout(100)
These lines declare a number of variables. You don't have to declare variables before you use them in Matlab but, there are sometimes good reasons to do so. You don't have to in Fortran either, though this is universally considered a bad idea these days. You could 'declare' these variables in Matlab with statements such as:
uz = zeros(100,1);
vz = zeros(100,1);
By declaring these in advance in your Matlab you allocate memory for them once, and avoid some performance-reducing problems.
The next 2 lines:
open(unit=8,file='prof.dat',status='unknown')
open(unit=9,file='cp.dat',status='unknown')
open a couple of files for output. They are used later in write statements - forget them, write Matlab statements such as save xout instead.
The next line is Fortran but identical in Matlab:
b=1.d0
The next lines get a value for the radius from the console:
write(6,98)
format(2x,'input the radius of the a-circle in z plane')
read(5,99)a
format(f10.0)
again, I suggest you forget these, just use the Matlab console to set the value of a. More Fortran that doesn't need to be translated (though I suggest you either drop the decimal points without following 0s or put a space between them and the subsequent * -- .* is a specific operator in Matlab):
xl=2.*a-1.+1./(2.*a-1.)
chord=2.+xl
del=a-b
A Fortran do loop is the same as a Matlab for loop. Rewrite:
do 50 i=1,100
as
for i = 1:100
As one of the other respondents has noted it's not clear where the matching end statement goes, you'll have to figure that out. Note that I'm just offering a line-by-line translation of Fortran into Matlab. It's not well-written Fortran, and I'm not offering well-written Matlab, I'll leave that to you.
This lot doesn't need to be translated:
ri=i
theta=6.2832d0*ri/101.d0
x=-del+a*cos(theta)
y=a*sin(theta)
cmplx is a Fortran function which returns a complex number which has real part x and imaginary part y:
z=cmplx(x,y)
In Matlab this would be z = x + y * i. Fortran uses ** for exponentiation, Matlab uses ^
zeta=z+b**2/z
and so on and so on.
Hope that helps.
I used f2matlab and a little touching up afterward. Here is the cleaned up and compilable fortran90 code:
program joukow
!
! computes joukowski airfoil and finds pressure coefficient
! currently set up for symmetric airfoil with sharp trailing edge
! and chord length equal to one.
! profile is written onto prof.dat and cp onto cp.dat
! implicit real*8(a-h,o-z)
complex z,zeta,cw
dimension uz(100),vz(100),xi(100),eta(100),cp(100)
dimension xout(100),yout(100)
open(unit=8,file='prof.dat',status='unknown')
open(unit=9,file='cp.dat',status='unknown')
b=1.d0
write(6,98)
98 format(2x,'input the radius of the a-circle in z plane')
read(5,99)a
99 format(f10.0)
xl=2.*a-1.+1./(2.*a-1.)
! xl=a+1./a
! chord=2.*xl
chord=2.+xl
del=a-b
! del =0.1d0
do i=1,100
ri=i
theta=6.2832d0*ri/101.d0
x=-del+a*cos(theta)
y=a*sin(theta)
z=cmplx(x,y)
zeta=z+b**2/z
!
! xi and eta are coordinates of points on airfoil
!
xi(i)=real(zeta)
eta(i)=aimag(zeta)
cw=(1.-a**2/(z+del)**2)/(1.-b**2/z**2)
!
! uz and vz are velocity components on the airfoil assuming the free-stream
! speed is one.
!
uz(i)=real(cw)
vz(i)=-aimag(cw)
!
! xout and yout are airfoil coordinates where the leading edge is at (0,0)
! and the chordlength is one.
!
xout(i)=(xl+xi(i))/chord
yout(i)=eta(i)/chord
write(8,100)xout(i),yout(i)
100 format(2x,2f10.4)
end do
!
! now calculate the pressure coefficient cp
!
write(6,200)
200 format(2x,'pressure coefficients')
do i=1,50
cp(i)=1.-(uz(i)**2+vz(i)**2)
write(9,100) xout(i),cp(i)
end do
stop
end program joukow
Here is the resulting matlab code:
function hw1(varargin)
%
% computes joukowski airfoil and finds pressure coefficient
% currently set up for symmetric airfoil with sharp trailing edge
% and chord length equal to one.
% profile is written onto prof.dat and cp onto cp.dat
% implicit real*8(a-h,o-z)
format_99=['%10.0f'];
format_100=[repmat(' ',1,2),repmat('%10.4f',1,2),'\n'];
format_200=[repmat(' ',1,2),'pressure coefficients \n'];
fid_8=fopen('prof.dat','w+');
fid_9=fopen('cp.dat','w+');
b=1.0d0;
a=input('input the radius of the a-circle in z plane');
xl=2..*a-1.+1../(2..*a-1.);
% xl=a+1./a
% chord=2.*xl
chord=2.+xl;
del=a-b;
% del =0.1d0
for i=1:100;
ri=i;
theta=6.2832d0.*ri./101.0d0;
x=-del+a.*cos(theta);
y=a.*sin(theta);
z=complex(x,y);
zeta=z+b.^2./z;
%
% xi and eta are coordinates of points on airfoil
%
xi(i)=real(zeta);
eta(i)=imag(zeta);
cw=(1.-a.^2./(z+del).^2)./(1.-b.^2./z.^2);
%
% uz and vz are velocity components on the airfoil assuming the free-stream
% speed is one.
%
uz(i)=real(cw);
vz(i)=-imag(cw);
%
% xout and yout are airfoil coordinates where the leading edge is at (0,0)
% and the chordlength is one.
%
xout(i)=(xl+xi(i))./chord;
yout(i)=eta(i)./chord;
fprintf(fid_8,format_100,xout(i),yout(i));
end; i=100+1;
%
% now calculate the pressure coefficient cp
%
fprintf(1,format_200);
for i=1:50;
cp(i)=1.-(uz(i).^2+vz(i).^2);
fprintf(fid_9,format_100, xout(i),cp(i));
end; i=50+1;
end %program joukow
They both give the same results for me. I didn't check the algorithm for correctness, though, just converted the code.
I don't know how well it's still supported - - but the easiest way used to be f2c which translates fortran directly into c code.