I'm executing a f90 script in Cygwin using gfortran and when i execute (run) the output with ./a it leaves a blank space asking for input without printing out the prompt (write) command.
program circle
real r, area
write (*,*) 'Give radius r:'
read (*,*) r
area = 3.14159*r*r
write (*,*) 'Area = ', area
stop
end
$ gfortran circle.f
$ ./a
1
Give radius r:
Area = 3.1415901
It's suppose to be
$ ./a
Give radius r:
1
Area = 3.1415901
What is happening here? Please help.
If your compiler supports Fortran 2003 you could use the flush statement:
program circle
use, intrinsic :: iso_fortran_env, only: stdin=>input_unit, &
stdout=>output_unit, &
stderr=>error_unit
implicit none
real :: r, area
write (stdout,*) 'Give radius r:'
flush(stdout)
read (stdin,*) r
area = 3.14159*r*r
write (stdout,*) 'Area = ', area
end program
Related
I've been trying to run this on Scilab, but I can't get it to work.
global ke Yxs Va Kg A D cx cxa cxamax fbc Kp Yps Ypx umax rho V mg mga mbc nxa
ke=0.003/(10^9);
Yxs=45*10^9;
Va=0.005;
Kg=0.04;
A=0.004657;
D=4.5*10^(-10);
cx=10^9;
cxa=10^9;
cxamax=1163*10^9;
fbc=0.01;
Kp=0.01;
Yps=0.9;
Ypx=0.01125;
umax=1.6;
rho=1030;
V=0.2;
function ydot=g(t,y)
ydot=zeros(y);
ydot(1)=((umax*((y(3)/Va)/((y(3)/Va)+Kg)))-ke*Yxs)*y(1);
ydot(2)=-(D*A*(((y(2)/V)-(y(3)/Va))/((y(4)/(rho*fbc))/A)));
ydot(3)=(D*A*(((y(2)/V)-(y(3)/Va))/((y(4)/(rho*fbc))/A)))-((umax*((y(3)/Va)/((y(3)/Va)+Kg)))/Yxs+(Ypx*(umax*((y(3)/Va)/((y(3)/Va)+Kg)))*(y(3)/Va)/(cga+Kp))/Yps)*y(1);
ydot(4)=(Ypx*(umax*((y(3)/Va)/((y(3)/Va)+Kg)))*(y(3)/Va)/(cga+Kp))*y(1);
endfunction
t0=0;
t=0:1:50;
y0=ones(0,4,4,0);
y=ode(y0,t0,t,g);
This is what the console returns when I run it.
lsoda-- neq (=i1) .lt. 1
where i1 is : 0
Illegal input detected (see printed message).
at line 52 of executed file C:\Users\pandrade\Documents\Pessoal\Ufla\modelagem artigo.sce
ode: lsoda exit with state -3.
Line 52 is the last line of the code, where the ode command is. Does anyone know what's wrong with it?
Your intialization of y0 is incorrect. Maybe you meant:
y0=[0;4;4;0]
or
y0=ones(4,1)
In any case y0 should be a column vector of 4 elements. Moreover you probably misspelled cga instead of cxa in the code of g(t,y).
Remember to always test that your right hand side function (here g) works outside the context of the ode call, by typing something like
g(0,y0)
on the Scilab command line.
I learnt how to differentiate on octave through this. But I now want to plot graph of the same function on octave. I am not able to do so. I want to know what the right command for plotting the 'ffd' equation in the code is.
`f = #(x) x.^2 + 3*x - 1 + 5*x.*sin(x);
pkg load symbolic
syms x;
ff = f(x);
ffd = diff(ff, x) `
What I have tried so far: I have tried adding these lines of code to the end and it didn't work. The graph was empty and I got an error.
real
ffd = (sym) 5⋅x⋅cos(x) + 2⋅x + 5⋅sin(x) + 3
error: __go_line__: invalid value for array property "ydata", unable to create graphics handle
error: called from
__plt__\>__plt2vs__ at line 466 column 15
__plt__\>__plt2__ at line 245 column 14
__plt__ at line 112 column 18
plot at line 229 column 10
real at line 10 column 1\`
I was expecting it to plot the graph of (sym) 5⋅x⋅cos(x) + 2⋅x + 5⋅sin(x) + 3 i.e., ffd, but it didn't work
In order to draw graphs of the differentiated functions we need to have code similar to this and in this case I am using pkg symbolic
pkg load symbolic
syms x;
x = sym('x');
y = #(x) x.^3;
yy = y(x);
ffd = diff(diff(yy,x));
ffe = diff(yy,x);
ez1=ezplot(y,[-10,10])
hold on
ez2=ezplot(ffe,[-10,10])
hold on
ez3=ezplot(ffd,[-10,10])
note: hold on function is used to draw more than one graphs on the same screen. However, if you modify the program and run it again it doesn't clear the screen of the previous graphs, if anyone knows how to do this, please leave a comment.
I'm changing a code for serial execution adjusting it to parallel execution (openmp), but I get a bad aproximation of the desired result (pi value). I show both codes below.
Is there something wrong?
program trap
use omp_lib
implicit none
double precision::suma=0.d0 ! sum is a scalar
double precision:: h,x,lima,limb
integer::n,i, istart, iend, thread_num, total_threads=4, ppt
integer(kind=8):: tic, toc, rate
double precision:: time
double precision, dimension(4):: pi= 0.d0
call system_clock(count_rate = rate)
call system_clock(tic)
lima=0.0d0; limb=1.0d0; suma=0.0d0; n=10000000
h=(limb-lima)/n
suma=h*(f(lima)+f(limb))*0.5d0 !first and last points
ppt= n/total_threads
!$ call omp_set_num_threads(total_threads)
!$omp parallel private (istart, iend, thread_num, i)
thread_num = omp_get_thread_num()
!$ istart = thread_num*ppt +1
!$ iend = min(thread_num*ppt + ppt, n-1)
do i=istart,iend ! this will control the loop in different images
x=lima+i*h
suma=suma+f(x)
pi(thread_num+1)=suma
enddo
!$omp end parallel
suma=sum(pi)
suma=suma*h
print *,"The value of pi is= ",suma ! print once from the first image
!print*, 'pi=' , pi
call system_clock(toc)
time = real(toc-tic)/real(rate)
print*, 'Time ', time, 's'
contains
double precision function f(y)
double precision:: y
f=4.0d0/(1.0d0+y*y)
end function f
end program trap
!----------------------------------------------------------------------------------
program trap
implicit none
double precision::sum ! sum is a scalar
double precision:: h,x,lima,limb
integer::n,i
integer(kind=8):: tic, toc, rate
double precision:: time
call system_clock(count_rate = rate)
call system_clock(tic)
lima=0.0d0; limb=1.0d0; sum=0.0d0; n=10000000
h=(limb-lima)/n
sum=h*(f(lima)+f(limb))*0.5d0 !first and last points
do i=1,n-1 ! this will control the loop in different images
x=lima+i*h
sum=sum+f(x)
enddo
sum=sum*h
print *,"The value of pi is (serial exe)= ",sum ! print once from the first image
call system_clock(toc)
time = real(toc-tic)/real(rate)
print*, 'Time serial execution', time, 's'
contains
double precision function f(y)
double precision:: y
f=4.0d0/(1.0d0+y*y)
end function f
end program trap
Compiled using:
$ gfortran -fopenmp -Wall -Wextra -O2 -Wall -o prog.exe test.f90
$ ./prog.exe
and
$ gfortran -Wall -Wextra -O2 -Wall -o prog.exe testserial.f90
$ ./prog.exe
In serial execution I get good aproximations of pi (3.1415) but using parallel I get (I show several parallel executions):
The value of pi is= 3.6731101425922810
Time 3.3386986702680588E-002 s
-------------------------------------------------------
The value of pi is= 3.1556004791445953
Time 8.3681479096412659E-002 s
------------------------------------------------------
The value of pi is= 3.2505952856717966
Time 5.1473543047904968E-002 s
There is a problem in your openmp parallel statement.
You keep on adding up onto the variable suma.
Therefore, you need to specify a reduction statement.
Also, you did not specify the variable x to be private.
I also changed some more parts of your code
You explicitly told each thread which index range it should use. Most often the compiler can figure that out more efficiently by itself. I changed parallel to parallel do for that.
It is good practice to set variable attributes in the openmp parallel region to be default(none). You will need to set each variables attribute explicitly.
program trap
use omp_lib
implicit none
double precision :: suma,h,x,lima,limb, time
integer :: n, i
integer, parameter :: total_threads=5
integer(kind=8) :: tic, toc, rate
call system_clock(count_rate = rate)
call system_clock(tic)
lima=0.0d0; limb=1.0d0; suma=0.0d0; n=10000000
h=(limb-lima)/n
suma=h*(f(lima)+f(limb))*0.5d0 !first and last points
call omp_set_num_threads(total_threads)
!$omp parallel do default(none) private(i, x) shared(lima, h, n) reduction(+: suma)
do i = 1, n
x=lima+i*h
suma=suma+f(x)
end do
!$omp end parallel do
suma=suma*h
print *,"The value of pi is= ", suma ! print once from the first image
call system_clock(toc)
time = real(toc-tic)/real(rate)
print*, 'Time ', time, 's'
contains
double precision function f(y)
double precision:: y
f=4.0d0/(1.0d0+y*y)
end function
end program
Could someone tell me if I've coded this correctly? This is my code for solving for the sides of a triangle given its perimeter, altitude, and angle (for the algebra see http://www.analyzemath.com/Geometry/challenge/triangle_per_alt_angle.html)
Prompt P
Prompt H
Prompt L [the angle]
(HP^2)/(2H(1+cos(L))+2Psin(L))→Y
(-P^2-2(1+cos(L))Y/(-2P)→Z
(Z+sqrt(Z^2-4Y))/2→N
[The same as above but Z-sqrt...]→R
If N>0
N→U
If R>0
R→U
Y/U→V
sqrt(U^2+V^2-2UVcos(L))→W
Disp U
Disp V
Disp W
Also, how would I fix this so that I can input angle = 90?
Also, in this code does it matter if the altitude is the one between b and c (refer to the website again)?
Thanks in advance
The code already works with L=90°.
Yes, the altitude must be the distance from point A to the base a between points B and C, forming a right-angle with that base. The derivation made that assumption, specifically with respect to the way it used h and a in the second area formula 1/2 h a. That exact formula would not apply if h was drawn differently.
The reason your second set of inputs resulted in a non-real answer is that sometimes a set of mathematical parameters can be inconsistent with each other and describe an impossible construct, and your P, h, and L values do exactly that. Specifically, they describe an impossible triangle.
Given an altitude h and angle L, the smallest perimeter P that can be achieved is an isosceles triangle split down the middle by h. With L=30, this would have perimeter P = a + b + c = 2h tan15 + h/cos15 + h/cos15, which, plugging in your h=3, results in P=7.819. You instead tried to use P=3+sqrt(3)=4.732. Try using various numbers less than 7.819 (plus a little; I've rounded here) and you'll see they all result in imaginary results. That's math telling you you're calculating something that cannot exist in reality.
If you fill in the missing close parenthesis between the Y and the / in line 5, then your code works perfectly.
I wrote the code slightly differently from you, here's what I did:
Prompt P
Prompt H
Prompt L
HP²/(2H(1+cos(L))+2Psin(L))→Y
(HP-Ysin(L))/H→Z
Z²-4Y→D
If D<0:Then
Disp "IMAGINARY"
Stop
End
(Z+√(D))/2→C
Y/C→B
P-(B+C)→A
Disp A
Disp B
Disp C
Edit: #Gabriel, there's nothing special (with respect to this question) about the angles 30-60-90; there is an infinite number of sets of P, h, and L inputs that describe such triangles. However, if you actually want to arrive at such triangles in the answer, you've actually changed the question; instead of just knowing one angle L plus P and h, you now know three angles (30-60-90) plus P and h. You've now over-specified the triangle, so that it is pretty well certain that a randomly generated set of inputs will describe an impossible triangle. As a contrived example, if you specified h as 0.0001 and P as 99999, then that's clearly impossible, because a triangle with a tiny altitude and fairly unextreme angles (which 30-60-90 are) cannot possibly achieve a perimeter many times its altitude.
If you want to start with just one of P or h, then you can derive equations to calculate all parameters of the triangle from the known P or h plus the knowledge of the 30-60-90 angles.
To give one example of this, if we assume that side a forms the base of the triangle between the 90° and 60° angles, then we have L=30 and (labelling the 60° angle as B) we have h=b, and you can get simple equations for all parameters:
P = a + h + c
sin60 = h/c
cos60 = a/c
=> P = c cos60 + c sin60 + c
P = c(cos60 + sin60 + 1)
c = P/(cos60 + sin60 + 1)
b = h = c sin60
a = c cos60
Plugging in P=100 we have
c = 100/(cos60 + sin60 + 1) = 42.265
b = h = 36.603
a = 21.132
If you plug in P=100, h=36.603, and L=30 into the code, you'll see you get these exact results.
Always optimize for speed, then size.
Further optimizing bgoldst's code:
Prompt P,H,L
HP²/(2H(1+cos(L))+2Psin(L
.5(Z+√((HP-sin(L)Ans)/H)²-4Ans
{Y/C→B,P-B-Ans,Ans
I try to draw something in OCaml (try.ocamlpro.com).
I'm not sure how to draw a line, for example x=y using the function "plot x y". Eventually I tried something like this which clearly doesn't work:
open Graphics;;
Graphics.open_graph " 200x200";;
for i = 0 to x do
plot i (f i)
done
let g x = 2*x
read_line ();;
Any help (or examples) ?
Thank you.
There is also Graphics.lineto, which is based on a turtle-type system:
Graphics.open_graph " 200x200";;
Graphics.lineto 100 100;;
Changes the current point (defaults to 0, 0) to the supplied x y point and draws a line connecting the two.
You can set the current point with moveto : int -> int -> unit.
See the docs for more.
I can't see what is your problem. When I try your code, modified a little bit, I can draw a line as you want. First you need to initialize your window:
open Graphics;;
Graphics.open_graph " 200x200";;
Then you need to define your function f:
let f x = x + 1;;
And then just draw the line using the function plot
for i = 0 to 200 do
plot i (f i)
done;;
Voilà !