fortran tutorial, Q&A

  • 0 Replies
  • 47 Views

0 Members and 1 Guest are viewing this topic.

Offline ker2x

  • *
  • Fractal Fanatic
  • ***
  • Posts: 21
« on: September 15, 2019, 10:56:42 AM »
Friendly greetings !

i'm in the mood of sharing the fortran love.
i heavily documented some of my code in the form of a small tutorial.
There isn't much but fortran is so easy and so powerful... feel free to ask questions.

EDIT : ho no... it's really hard to read without syntax highlighting... copy paste the code in notepad++, it come with fortran highlighting.


Code: [Select]
! this is a comment
! every program start with "PROGRAM <name of the program>"
! and end with "END PROGRAM <name is optional here with modern compiler>"
! module (stuff you import) start with "module <name of the module>"

program main ! the main can be called anything, it's just my personnal preference to call it main

! "use" is like import, or include, in other language
! it's good practice (or so i think) to only import what you need
use m_control, only : init_menu, init_controls, init_screen
use m_globals, only : is_started, is_looping, myscreen
use m_flowa
use appgraphics

implicit none ! it forbid implicit declaration of variable.
! the compiler will throw an error when using an indeclared variable (usually a typo)
! it's optional, but always use it please.

! usually you declare your variable after "implicit none".
! it just happen that i don't have any variable to declare here
! they are imported from other module.
!
! by the way, everything is pretty much global unless specified otherwise
! and this "specified otherwise" is only when using the object oriented fortran
! (latest norm that your compiler may or may not support)
! that's why i use "only" when importing stuff, unless it's unpractical
       
    ! you execute subroutine with "CALL subroutine_name(optional, parameters)"
! subroutine doesn't return anything, but can modify a parameter if requested specifically
! (google "fortran intent", you can declare a parameter in, out, or inout)
! if you need to return a value (eg : y = sin(x) you use a "function" instead of a "subroutine"
    call init_screen()
    call init_menu()
    call init_controls()
    call init_flowa()

! just regular variable assignment
! you'll see a lot of .something. in fortran, that's just how it is. (history...)
! the 2 variable below are of type LOGICAL ("boolean" in other language)
    is_started = .FALSE.
    is_looping = .TRUE.

! fortran have many variant of do loop, just google it
! fortran doesn't have block, so everything need an "END something"
    do while(is_looping)
        if(.NOT. is_started) then
            call loop()
        else
            call update_flowa()
        end if
    end do
   
    ! EXIT
    call close_flowa
    call closewindow(myscreen)

! if you need to write subroutine or function
! you use the keyword "contains" and then declare your stuff below
! i don't need  one here but i'll make one just for the show
! for more usefull exemple see one of my module
contains

subroutine donothing()
! nothing here
end subroutine
 
end program main


Code: [Select]
! this is a module, it end with end module, of course.
module m_flowa

    use m_globals
    implicit none
   
! now we have a bunch of variable declaration here.
! it's like this :
! TYPE (optional stuff), more optional stuff :: name (and optional assignment)

! the "PARAMETER" option mean it's a constant and can't be modified after declaration.
    CHARACTER ( len = 255 ), PARAMETER :: filename = 'flowa.xyz'
    INTEGER, PARAMETER :: file_out_unit = 10
    INTEGER, PARAMETER :: miniter = 200
    INTEGER, PARAMETER :: maxiter = 2000
    INTEGER, PARAMETER :: batchsize = 1000
    INTEGER*8 :: i = 1, j=1 ! this syntax *8 is a non-portable shortcut to "integer (kind=8)"
! it mean i asked for a 8 byte integer (64bit)
    INTEGER :: iter = 0

! i just declared an array of real ("float" in C) of size "maxiter +1".
! by the way, in fortran array start with 1, not 0. unless specified otherwise (history...)
    REAL :: pts_x(maxiter+1)
    REAL :: pts_y(maxiter+1)
    REAL :: pts_z(maxiter+1)
   
   
    REAL :: xmin = -1.0, xmax = 2.0, ymin = -1.3, ymax =1.3
    REAL :: x=0 ,y=0 ,z=0 ,nx=0 ,ny=0 ,nz=0 ,r=0 ,r2p=0 ,th=0 ,ph=0 , p=2

! module doesn't have code in the wild unlike "program"
! i declare my code in subroutine and function below "contains"
contains

! a subroutine with no parameters.
! remember, subroutine doesn't return anything so no "return"
! the "&" is a line continuation character, the 2 line below are the same as :
! open ( unit = file_out_unit, file = filename, status = 'replace', form = 'formatted', access = 'sequential')
    subroutine init_flowa()
        open ( unit = file_out_unit, file = filename, status = 'replace', &
        form = 'formatted', access = 'sequential')
    end subroutine init_flowa
   
    subroutine update_flowa()

    DO i=1, batchsize ! it's like a "for" loop
! yes, i messed up the indentation, i know...
   
        CALL RANDOM_NUMBER(x)
        CALL RANDOM_NUMBER(y)
        CALL RANDOM_NUMBER(z)

! remember, pts_x y z are arrays.
! if you do not specify an index it change all the elements of the array.
! basically, i just set all elements of the three arrays to 0.
! i could also have used a 2 dimension array, but i didn't.
        pts_x = 0
        pts_y = 0
        pts_z = 0
       
        x = (x * 2.6) - 1.3
        y = (y * 2.6) - 1.3
        z = (z * 2.6) - 1.3
        iter = 0
        nx = x
        ny = y
        nz = z
        r=sqrt(x*x+y*y+z*z)
        th=atan(y/x)*p
        ph=asin(z/r)*p
       
! an absurdly long while condition.
! .and. is the logical "and", as opposed to bitwise and.
! it's just like "&&" in C
! "/=" it the equivalent of "!=" in C. but since "!" is for comments it's "/"
        DO WHILE((iter < MAXITER) .AND. (r < 2.0) .AND. (nx /= 0.0) .AND. (r /= 0.0) .AND. (nx /= -0.0) .AND. (r /= -0.0))
       
            r2p = r*r
            th=atan(ny/nx)*p
            ph=asin(nz/r)*p
            nx=r2p*cos(ph)*cos(th)+x
            ny=r2p*cos(ph)*sin(th)+y
            nz=r2p*sin(ph)+z
       
            pts_x(iter) = nx
            pts_y(iter) = ny
            pts_z(iter) = nz
            r=sqrt(nx*nx+ny*ny+nz*nz)
            iter = iter +1
       
        END DO

        if((r < 2.0) .AND. (iter > miniter)) THEN
           
            DO j=miniter, iter -1 , 1
! write format are a pain in the ass in fortran. i won't cover it here.
! history again. fortran come from punch card with many limitation.
! it evolved to "free form" on the compiler side. but it's still very strict on I/O
                write ( file_out_unit, '(f9.5,f9.5,f9.5)' ) pts_x(j), pts_y(j), pts_z(j)
            END DO
        END IF
    END DO
end subroutine update_flowa

subroutine close_flowa
    close ( unit = file_out_unit ) ! parameters can be named, have optional value, etc.
! i just specify the value of the "unit" parameter
! and leave every other parameters to their default values.
end subroutine close_flowa
   
end module m_flowa


Linkback: https://fractalforums.org/programming/11/fortran-tutorial-qanda/3078/


xx
3D buddhabrot cloudpoint (fortran code)

Started by ker2x on Programming

12 Replies
280 Views
Last post September 20, 2019, 05:36:02 PM
by gerson
xx
Tutorial French

Started by meletou on Mandelbulb Maniacs

0 Replies
162 Views
Last post July 15, 2018, 03:52:37 PM
by meletou
xx
Tutorial for latest mandelbulb 1.9.1

Started by bloosey on Meet & Greet

0 Replies
137 Views
Last post June 08, 2018, 05:04:48 AM
by bloosey
xx
Tutorial Mandelbulber Franais

Started by meletou on Francais

3 Replies
362 Views
Last post July 20, 2018, 09:44:59 AM
by meletou
xx
tutorial 04 by default no images show up

Started by charPixel on Fragmentarium

5 Replies
362 Views
Last post December 24, 2017, 03:06:36 AM
by 3DickUlus