fortran tutorial, Q&A

  • 0 Replies

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()
            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

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 = ''
    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"

! 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...

! 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
! 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
            pts_x(iter) = nx
            pts_y(iter) = ny
            pts_z(iter) = 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


3D buddhabrot cloudpoint (fortran code)

Started by ker2x on Programming

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

Started by meletou on Mandelbulb Maniacs

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

Started by bloosey on Meet & Greet

0 Replies
Last post June 08, 2018, 05:04:48 AM
by bloosey
Tutorial Mandelbulber Français

Started by meletou on Francais

3 Replies
Last post July 20, 2018, 09:44:59 AM
by meletou
Amazing Underwater Object tutorial

Started by timemit on Fractal Image Gallery

0 Replies
Last post October 29, 2017, 01:20:20 PM
by timemit