Understanding different types in Fortran - visual-studio

I was reading a Fortran code, came across the following code, couldn't understand what it does.
m%AllOuts( BAzimuth(k) ) = m%BEMT_u(indx)%psi(k)*R2D
I know that % here works like a pipe indicator to access values in a way similar to a dictionary in Python. I have a dictionary m let's say and the first key is AllOuts, but what does anything inside parentheses mean? Is it like another dictionary?

The percent sign is not denoting a dictionary. There are no native dictionaries in Fortran.
The percent sign denotes the component of a type. For example:
! Declare a type
type :: rectangle
integer :: x, y
character(len=8) :: color
end type rectangle
! Declare a variable of this type
type(rectangle) :: my_rect
! Use the type
my_rect % x = 4
my_rect % y = 3
my_rect % color = 'red'
print *, "Area: ", my_rect % x * my_rect % y
The parentheses could either indicate the index of an array, or the arguments of a call.
So, for example:
integer, dimension(10) :: a
a(8) = 16 ! write the number 16 to the 8th element of array a
Or, as a prodedure:
print *, my_pow(2, 3)
...
contains
function my_pow(a, b)
integer, intent(in) :: a, b
my_pow = a ** b
end function my_pow
In order to figure out what m is, you'd need to look at the declaration of m, which would be something like
type(sometype) :: m
or
class(sometype) :: m
Then you'd need to find out the type declaration, which would be something like
type :: sometype
! component declarations in here
end type
Now one of the components, BEMT_u, is almost certainly an array of a different type, which you'd also need to look up.

Related

Sml program -> confusion on "AS syntax error"

so I have to write a small program in SML ->>
a file named ‘p0.sml’ that contains a function named epoly, which accepts as parameters a list of real values a0 through an, and a single real value x. The list contains the coefficients of a polynomial of the form a0 + a1x + a2x 2 + … + anx n, where the real x used is the x parameter passed to your function. Your implementation must accept the list of coefficients as the first parameter and the value of x as the second. Your function must return the value of the polynomial specified by the parameters passed to it.
this is what I have so far but it won't compile because of a syntax error with as. "Error: syntax error found at AS". If you have any pointers that would be greatly appreciated.
fun epoly([], x:real) = 0.0
= epoly(L:real list as h::T, x:real) = h + (x * epoly(T, x));
It looks like you have a typo. Your second = should be a |.
fun epoly([], x:real) = 0.0
| epoly(L:real list as h::T, x:real) =
h + (x * epoly(T, x));
There is, further, no need to specify types. Your SML compiler can infer the types from data presented. Along with removing unnecessary bindings, this can be reduced to:
fun epoly([], _) = 0.0
| epoly(h::T, x) =
h + (x * epoly(T, x));
From fun epoly([], _) = 0.0 we know epoly will take a tuple of a list and some type and return real.
From:
| epoly(h::T, x) =
h + (x * epoly(T, x));
We know that x is being multiplied by a real, so x must be real. And since h is being added to a real, it must be a real, so the entire list is a real list.
Thus the type of epoly can be inferred correctly to be real list * real -> real.

Constant shape error in simple code

I have an error with this code and I don't understand why
-"The module or main program array 'u' at (1) must have constant shape."
-Moreover, how can I do this code with a choice of parameters, I mean [U]=vector(N) where I can chose N and it returns me U.
program vector
!declaration
implicit none
integer :: n
integer, parameter :: N=10
real, dimension(N,1) :: U
do n=1,N
U(1,N)=n
end do
print*,U
end program vector
First up, Fortran is caseINsensitive, so n and N are the same thing, and you can't declare two different variables/parameters n and N.
Then you declare U to have shape (N, 1), but seem to use it in the form (1, N).
As for how to auto-generate something like U, you could use something like this:
function vector(n) result(v)
integer, intent(in) :: n
integer :: v(n)
integer :: i
v = [ (i, i=1, n) ]
return
end function vector
One more thing:
You declare U with dimension(1, N) which creates a 2D array with one dimension having length 1. I'm wondering whether you wanted to create a 1D array with range from 1 to N, for which the declaration would need to be dimension(1:N) (or, since Fortran assumes indices start at 1, just dimension(N)).
Addressing the questions in your comment:
The purpose of intent(in) tells the compiler that n is only read, not written to, in this function. Considering that you want to use n as the size of array v, you want that.
With result(v) I tell the compiler that I want to use the name v to refer to the result of the function, not the default (which is the function name). I do this to avoid confusion.
integer :: v(n) is the same as integer, dimension(n) :: v

How to read 2 vectors from a matrix in .dat in Fortran

I want to create a program in Fortran that multiplies vectors from a .dat file that has the following format:
x1 y1 z1
x2 y2 z2
The index 1 and 2 refer to the vector 1 and 2, respectively. First I want do identify the vectors, so far I have
program ex2
implicit none
real*8 x
integer i
write(6,*) "Insert the vectors from vet_in.dat"
open (10, file ="vet_in.dat")
read (10,*) x(i), i=1,3
end program ex2
The line of the read(10,*) was sugested to me, I don't quite get it, I thought fortran identified the ij matrix index. And then I wanted to multiply x1.x2, y1.y2 and z1.z2, maybe the loop and de if could be used. Can you help me to proceed?
First, you need to declare x and also y as an array of rank 1 and size 3:
real*8 x(3), y(3)
And also a scalar variable for the result
real*8 result
Don't write to unit 6, but use *:
write(*,*) "Insert..."
but I wouldn't write anything at all.
Now you can read the vectors. If they are stored in rows you can read them in one go
read(10,*) x
or
read(10,*) (x(i), i=1, 3)
(read about implied do in any textbook).
and then the same for y.
Then you can make a scalar product of them:
result = dot_product(x, y)
(see https://gcc.gnu.org/onlinedocs/gfortran/DOT_005fPRODUCT.html)
or
result = sum(x*y)
or
result = 0
do i = 1, 3
result = result + x(i) * y(i)
end do
Note that real*8 is not legal standard Fortran, just a non-standard extension. You can use double precision instead until you learn kinds.

Error with argument and procedure

I have to use a subroutine (neqnf) included in IMSL library, which let me solve non-linear systems. (link to users manual, neqnf page here)
main.f90, is:
program prova_sistema_in_un_modulo
include "link_fnl_shared.h"
use neqnf_int
use modx
implicit none
call d_neqnf(FCN, x, xguess=x_guess, fnorm=f_norm)
end program prova_sistema_in_un_modulo
where subroutine FCN is coded in an external module, modx.f90:
module modx
implicit none
integer, parameter :: ikind = selected_real_kind(8,99)
integer :: n=3
real(kind=ikind) :: f_norm
real(kind=ikind), dimension(3) :: x, x_guess=(/ 4.0, 4.0, 4.0/)
contains
subroutine FCN(x,f,n)
integer :: n !dummy var
real(kind=ikind), dimension(3) :: x, f !dummy var
f(1)=x(1)+A(x(1))+(x(2)+x(3))*(x(2)+x(3))-27.0 ! =0
f(2)=B(x(1),x(2))+x(3)*x(3)-10.0 ! =0
f(3)=Z(x(2),x(3)) ! =0
end subroutine FCN
function A(x)
real(kind=ikind) :: x !dummy var
real(kind=ikind) :: A !function var
A=exp(x-1.0)
end function A
function B(x,y)
real(kind=ikind) :: x,y !dummy var
real(kind=ikind) :: B !function var
B=exp(y-2.0)/x
end function B
function C(x)
real(kind=ikind) :: x !dummy var
real(kind=ikind) :: C !function var
C=sin(x-2.0)
end function C
function Z(x,y)
real(kind=ikind) :: x,y !dummy var
real(kind=ikind) :: Z !function var
Z=y+C(x)+x*x-7.0
end function Z
end module modx
but I get these three errors:
Error 1 error #7061: The characteristics of dummy argument 1 of the associated actual procedure differ from the characteristics of dummy argument 1 of the dummy procedure. (12.2) [FCN]
Error 2 error #7062: The characteristics of dummy argument 2 of the associated actual procedure differ from the characteristics of dummy argument 2 of the dummy procedure. (12.2) [FCN]
Error 3 error #7063: The characteristics of dummy argument 3 of the associated actual procedure differ from the characteristics of dummy argument 3 of the dummy procedure. (12.2) [FCN]
NB: if I put all code in the main program, all goes fine! while if I code using module (as I've done, the actually posted code) I get that errors!
can anyone help me?
The problem is that you provide a fixed dimension for the dummy arguments x(3) and f(3) in your custom function FCN, while IMSL expects a variable dimension x(n), f(n):
subroutine FCN(x,f,n)
integer :: n !dummy var
! real(kind=ikind), dimension(3) :: x, f !<- wrong
real(kind=ikind), dimension(n) :: x, f !<- correct
f(1)=x(1)+A(x(1))+(x(2)+x(3))*(x(2)+x(3))-27.0 ! =0
f(2)=B(x(1),x(2))+x(3)*x(3)-10.0 ! =0
f(3)=Z(x(2),x(3)) ! =0
end subroutine FCN
A working example to reproduce this is (interface borrowed from HYBRD1):
module test_int
contains
subroutine final(FCN, x, f, n)
interface
SUBROUTINE FCN (X, F, N)
INTEGER N
DOUBLE PRECISION X(N), F(N)
END SUBROUTINE
end interface
integer :: n
double precision :: x(n), f(n)
call FCN(x,f,n)
end subroutine
end module
module test_fct
contains
subroutine FCN(X, F, N)
integer :: n
double precision :: x(n), f(n)
print *,X ; print *,F ; print *,N
end subroutine
end module
program prova
use, intrinsic :: iso_fortran_env
use test_int
use test_fct
implicit none
integer,parameter :: n=2
double precision :: x(n), f(n)
x = [ 1.d0, 2.d0 ]
f = [ 3.d0, 4.d0 ]
call final(FCN, x, f, n)
end program prova

ML Expression, help line by line

val y=2;
fun f(x) = x*y;
fun g(h) = let val y=5 in 3+h(y) end;
let val y=3 in g(f) end;
I'm looking for a line by line explanation. I'm new to ML and trying to decipher some online code. Also, a description of the "let/in" commands would be very helpful.
I'm more familiar with ocaml but it all looks the same to me.
val y=2;
fun f(x) = x*y;
The first two lines bind variables y and f. y to an integer 2 and f to a function which takes an integer x and multiplies it by what's bound to y, 2. So you can think of the function f takes some integer and multiplies it by 2. (f(x) = x*2)
fun g(h) = let val y=5
in
3+h(y)
end;
The next line defines a function g which takes some h (which turns out to be a function which takes an integer and returns an integer) and does the following:
Binds the integer 5 to a temporary variable y.
You can think of the let/in/end syntax as a way to declare a temporary variable which could be used in the expression following in. end just ends the expression. (this is in contrast to ocaml where end is omitted)
Returns the sum of 3 plus the function h applying the argument y, or 5.
At a high level, the function g takes some function, applies 5 to that function and adds 3 to the result. (g(h) = 3+h(5))
At this point, three variables are bound in the environment: y = 2, f = function and g = function.
let val y=3
in
g(f)
end;
Now 3 is bound to a temporary variable y and calls function g with the function f as the argument. You need to remember that when a function is defined, it keeps it's environment along with it so the temporary binding of y here has no affect on the functions g and f. Their behavior does not change.
g (g(h) = 3+h(5)), is called with argument f (f(x) = x*2). Performing the substitutions for parameter h, g becomes 3+((5)*2) which evaluates to 13.
I hope this is clear to you.

Resources