{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "10d0e3c5",
   "metadata": {},
   "source": [
    "## Introduction to structured programming with Fortran\n",
    "\n",
    "### Why to learn Fortran ?\n",
    "\n",
    "* Because of the execution speed of a program\n",
    "* Well suited for numerical computations : more than **45% of scientific applications** are in Fortran\n",
    "\n",
    "## Getting started\n",
    "\n",
    "### Hello World"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "00ec1776",
   "metadata": {},
   "outputs": [],
   "source": [
    "program hello_world\n",
    "\n",
    "  implicit none ! important\n",
    "\n",
    "  print *, \"Hello World!\"\n",
    "\n",
    "end program hello_world"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c4b788f0",
   "metadata": {},
   "source": [
    "### Data Type Declarations and Assignments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ffd3f0c3",
   "metadata": {},
   "outputs": [],
   "source": [
    "program data_type\n",
    "\n",
    "  implicit none\n",
    "  \n",
    "  real x, y\n",
    "  integer i, j\n",
    "  logical flag\n",
    "  \n",
    "  integer matrix(2,2) \n",
    "  character(80) month\n",
    "  character(len=80) months(12)\n",
    "  \n",
    "  character family*16\n",
    "  \n",
    "  real, dimension(12) :: small_array\n",
    "  character(len=80), dimension(24) :: screen\n",
    "  \n",
    "  integer, parameter :: it = 100\n",
    "  \n",
    "  i = 1\n",
    "  j = i+2\n",
    "  x = 85.8\n",
    "  y = 3.5*cos(x)\n",
    "\n",
    "  month=\"december\"\n",
    "  \n",
    "  months(:)=\"empty\"\n",
    "  \n",
    "  months(12)=month\n",
    "  \n",
    "  flag = .TRUE.\n",
    "  \n",
    "  family = \"GEORGE P. BURDELL\"\n",
    "  print*,family(:6)\n",
    "  print*,family(8:9)\n",
    "  print*,family(11:)\n",
    "  print*,family(:6)//FAMILY(10:)\n",
    "  \n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "133046ed",
   "metadata": {},
   "source": [
    "### Arithmetic Assignments\n",
    "\n",
    "The result of any integer divide is truncated to the integer value less than the correct decimal answer for the division. The result of this is that changing the order of operations can make a big difference in the answers.  Notice how parentheses force more expected results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13343800",
   "metadata": {},
   "outputs": [],
   "source": [
    "program arith\n",
    "\n",
    "  implicit none\n",
    "  \n",
    "  real r2,r3,r4,r5,r6,ans1,ans2,ans3\n",
    "  integer i2,i3,i4,i5,i6,ians1,ians2,ians3,ians4\n",
    "  \n",
    "  data r2/2./,r3/3./,r4/4.0/,r5/5.0/\n",
    "  data i2,i3,i4,i5/2,3,4,5/\n",
    "  \n",
    "  ians1=i2*i3/i5\n",
    "  ians2=i3/i5*i2\n",
    "  ians3=i2*(i3/i5)\n",
    "  ians4=(i3/i5)*i2\n",
    "  print *, '2*3/5 =', ians1, ', 3/5*2 =',ians2,', 2*(3/5) =',ians3 ,', (3/5)*2 =',ians4\n",
    "  \n",
    "end program arith"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cabea667",
   "metadata": {},
   "source": [
    "Real arithmetic behaves more uniformly:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e1de5730",
   "metadata": {},
   "outputs": [],
   "source": [
    "program arith\n",
    "\n",
    "  implicit none\n",
    "  \n",
    "  real r2,r3,r4,r5,r6,ans1,ans2,ans3\n",
    "  integer i2,i3,i4,i5,i6,ians1,ians2,ians3,ians4\n",
    "  \n",
    "  data r2/2./,r3/3./,r4/4.0/,r5/5.0/\n",
    "  data i2,i3,i4,i5/2,3,4,5/\n",
    "  \n",
    "  ans1=r2*r3/r5\n",
    "  ans2=r3/r5*r2\n",
    "  ans3=(r3/r5)*r2\n",
    "  print *, '2.0*3.0/5.0 =', ans1, ', 3.0/5.0*2.0 =',ans2,', (3.0/5.0)*2.0 =',ans3\n",
    "      \n",
    "end program arith      "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f18b85ec",
   "metadata": {},
   "source": [
    "Watch how precedence of operations effects the following:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9a362858",
   "metadata": {},
   "outputs": [],
   "source": [
    "program arith\n",
    "\n",
    "  implicit none\n",
    "  \n",
    "  real r2,r3,r4,r5,r6,ans1,ans2,ans3\n",
    "  integer i2,i3,i4,i5,i6,ians1,ians2,ians3,ians4\n",
    "  \n",
    "  data r2/2./,r3/3./,r4/4.0/,r5/5.0/\n",
    "  data i2,i3,i4,i5/2,3,4,5/\n",
    "\n",
    "  ians1=i2+i5*i3**i2\n",
    "  ians2=i5*i3**i2+i2\n",
    "  ians3=i3**i2*i5+i2\n",
    "  print *, '2+5*3**2 =',ians1,', 5*3**2+2 =',ians2, ', 3**2*5+2 =',ians3\n",
    "      \n",
    "end program arith      "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5297b017",
   "metadata": {},
   "source": [
    "You can mix real and integers, but watch what happens"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d50669e",
   "metadata": {},
   "outputs": [],
   "source": [
    "program arith\n",
    "\n",
    "  implicit none\n",
    "  \n",
    "  real r2,r3,r4,r5,r6,ans1,ans2,ans3\n",
    "  integer i2,i3,i4,i5,i6,ians1,ians2,ians3,ians4\n",
    "  \n",
    "  data r2/2./,r3/3./,r4/4.0/,r5/5.0/\n",
    "  data i2,i3,i4,i5/2,3,4,5/\n",
    "\n",
    "  ans1=r5+i3/i2\n",
    "  ans2=5.0+3/2\n",
    "  print *, '5.0+3/2 =',ans1\n",
    "  print *, '5.0+3/2 =',ans2\n",
    "      \n",
    "end program arith      "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "222cabbc",
   "metadata": {},
   "source": [
    "Look at what happens when I put a real in either the numerator or denominator of the division term"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "78929c6e",
   "metadata": {},
   "outputs": [],
   "source": [
    "program arith\n",
    "\n",
    "  implicit none\n",
    "  \n",
    "  real r2,r3,r4,r5,r6,ans1,ans2,ans3\n",
    "  integer i2,i3,i4,i5,i6,ians1,ians2,ians3,ians4\n",
    "  \n",
    "  data r2/2./,r3/3./,r4/4.0/,r5/5.0/\n",
    "  data i2,i3,i4,i5/2,3,4,5/\n",
    "\n",
    "  ans1=r5+i3/r2\n",
    "  ans2=r5+r3/i2\n",
    "  print *, '5.0+3/2.0 =',ans1, ', 5.0+3.0/2 =', ans2\n",
    "      \n",
    "end program arith           "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7d37bc2",
   "metadata": {},
   "source": [
    "Although Fortran normally works from left to right at a given level of precedence (does all multiply and divide from left to right before moving on to adds and subtracts). It works exponentiation from right to left when it hits 2 or more sequential exponentiation operations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3c2da1a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "program arith\n",
    "\n",
    "  implicit none\n",
    "  \n",
    "  real r2,r3,r4,r5,r6,ans1,ans2,ans3\n",
    "  integer i2,i3,i4,i5,i6,ians1,ians2,ians3,ians4\n",
    "  \n",
    "  data r2/2./,r3/3./,r4/4.0/,r5/5.0/\n",
    "  data i2,i3,i4,i5/2,3,4,5/\n",
    "\n",
    "  ians1= i5**i3**i2\n",
    "  ians2= (i5**i3)**i2\n",
    "  ians3= i5**(i3**i2)\n",
    "  print *, '5**3**2 =',ians1, ', (5**3)**2 =',ians2,  ', 5**(3**2) =',ians3\n",
    "      \n",
    "end program arith           "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8387be7a",
   "metadata": {},
   "source": [
    "When in doubt use parentheses to get the answer that you really want.\n",
    "\n",
    "### Assignments exercise"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "14f6e7e2",
   "metadata": {},
   "outputs": [],
   "source": [
    "program sphere  \n",
    "\n",
    "  implicit none\n",
    "      \n",
    "  real pi,radius,volume,area  \n",
    "          \n",
    "  radius = 1.0\n",
    "  pi = 0.0\n",
    "      \n",
    "  write(*,*) 'The value of pi is ', pi\n",
    "  write(*,*) \n",
    "\n",
    "  area = 0.0\n",
    "  volume = 0.0\n",
    "      \n",
    "  write(*,*) 'For a radius ', radius \n",
    "  write(*,*) 'the area of a sphere is ', area\n",
    "  write(*,*) 'and the volume is ', volume\n",
    "      \n",
    "end "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a1702f7",
   "metadata": {},
   "source": [
    "### Execution Control"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41f9a8f0",
   "metadata": {},
   "outputs": [],
   "source": [
    "PROGRAM gcd\n",
    "  ! Computes the greatest common divisor, Euclidean algorithm\n",
    "  IMPLICIT NONE\n",
    "  INTEGER :: m, n, t\n",
    "  WRITE(*,*) \"Give positive integers m and n :\"\n",
    "  m=5464\n",
    "  n=484682\n",
    "  WRITE(*,*) 'm:', m,' n:', n\n",
    "  positive_check: IF (m > 0 .AND. n > 0) THEN\n",
    "    main_algorithm: DO WHILE (n /= 0)\n",
    "      t = MOD(m,n)\n",
    "      m = n\n",
    "      n = t\n",
    "    END DO main_algorithm\n",
    "    WRITE(*,*) \"Greatest common divisor: \",m\n",
    "  ELSE\n",
    "    WRITE(*,*) 'Negative value entered'\n",
    "  END IF positive_check\n",
    "END PROGRAM gcd"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cef2ad42",
   "metadata": {},
   "source": [
    "### File-Directed Input and Output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8fd042c4",
   "metadata": {},
   "outputs": [],
   "source": [
    "program plot\n",
    "\n",
    "  ! Program to provide plots of Sin(x)\n",
    "\n",
    "  implicit none\n",
    "  character label*150\n",
    "  real x\n",
    "  integer i\n",
    "  character xlabel*32,ylabel*32,title*32\n",
    "  real fx\n",
    "  !\n",
    "  ! label   -   Character string \n",
    "  ! xlabel  -   Contains a label for the x-axis\n",
    "  ! ylabel  -   Contains a label for the y-axis\n",
    "  ! title   -   Contains a title for the plot\n",
    "  !\n",
    "  ! Drive a separate true graphics program (gnuplot)\n",
    "  !\n",
    "  ! First set up the command file for gnuplot\n",
    "  !\n",
    "  xlabel=\"'x'\"\n",
    "  ylabel=\"'y'\"\n",
    "  title=\"'sin(x)'\"\n",
    "  open (112,file='03_gnuxy')\n",
    "  !\n",
    "  label='set xlabel '//xlabel\n",
    "  write(112,*)label\n",
    "  write(112,*)'set xrange [0:6]'\n",
    "  label='set ylabel '//ylabel\n",
    "  write(112,*)label\n",
    "  write(112,*)'set yrange [-1.2:1.2]'\n",
    "  label='plot \"03_dataxy\" using 1:2 title '//title\n",
    "  label=trim(label)//' with lines lt rgb \"red\"'\n",
    "  write(112,*) label\n",
    "  write (112,*) 'pause -1'\n",
    "  close(112)\n",
    "  !\n",
    "  !   Generate x-y pairs for the graph\n",
    "  !\n",
    "  open (112,file='03_dataxy')\n",
    "  do i=0,60\n",
    "    x=.1*i\n",
    "    fx=sin(x)\n",
    "    write(112,*) x,fx\n",
    "  enddo\n",
    "  close(112)\n",
    "  !\n",
    "end program"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "059d5e2a",
   "metadata": {},
   "source": [
    "This code is going to create 2 files: \"03_dataxy\" and \"03_gnuxy\".\n",
    "\n",
    "The idea is to use a linux plotting tool called \"GNUplot\" to make a graph: the first file is the data for the graph, the second one is the gnuplot script using these data.\n",
    "\n",
    "```bash\n",
    "gnuplot 03_gnuxy\n",
    "```\n",
    "\n",
    "<img src=\"https://gogs.elic.ucl.ac.be/pbarriat/learning-fortran/raw/master/assets/sin.png\">\n",
    "\n",
    "#### Format controlled IO"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a26b3cc5",
   "metadata": {},
   "outputs": [],
   "source": [
    "program format\n",
    "\n",
    "  implicit none\n",
    "  \n",
    "  real(4) A\n",
    "  real(8) B\n",
    "  integer I, KEY\n",
    "\n",
    "  A= 1500.*acos(0.)\n",
    "  B= 4e3*dcos(16.5d0)\n",
    "  KEY= 884\n",
    "  \n",
    "  write(*,*) A,B,KEY\n",
    "  write(*,*)\n",
    "  \n",
    "  write(*,1000) A,B,KEY\n",
    "  write(*,1001) (\"-\",I=1,38)\n",
    "  \n",
    "  1000 FORMAT(F18.10,E14.5,I6)\n",
    "  1001 FORMAT(38A1)\n",
    "      \n",
    "end program format  "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "31f27416",
   "metadata": {},
   "source": [
    "### Hands on learning: numerical analysis\n",
    "\n",
    "Apply the Newton's method to find the root(s) of a polynomial function.\n",
    "\n",
    "<img src=\"https://wikimedia.org/api/rest_v1/media/math/render/svg/6929060731e351c465426e37567abe5ee13d65d9\">"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "df362a1a",
   "metadata": {},
   "outputs": [],
   "source": [
    "program newton\n",
    "\n",
    "  implicit none\n",
    "\n",
    "  ! Use a Newton iteration to solve a polynomial equation\n",
    "\n",
    "  integer :: i\n",
    "\n",
    "  write(*,*) 'Try to solve \"x**3+x-10=0\"'  \n",
    "  write(*,*) 'What is your initial guess for the solution?'\n",
    "\n",
    "  do while( .TRUE. )\n",
    "  \n",
    "    write(*,*)\n",
    "    exit\n",
    "\n",
    "  end do\n",
    "\n",
    "end program\n",
    "\n",
    "! ******************************************************************************************\n",
    "\n",
    "subroutine derivate()\n",
    "\n",
    "! Evaluate the function f(x)=x**3+x-10\n",
    "! also return the derivative of the function\n",
    "\n",
    "\n",
    "end subroutine\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "919d1d4f",
   "metadata": {},
   "source": [
    "### COMMON Statement (F77)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4b517d6b",
   "metadata": {},
   "outputs": [],
   "source": [
    "      PROGRAM test_arg\n",
    "\n",
    "        implicit none\n",
    "        integer a,b,c\n",
    "\n",
    "        common /arg/ a,b,c\n",
    "\n",
    "        a = 2\n",
    "        c = 1\n",
    "\n",
    "        print *, 'Before the call:'\n",
    "        print *, 'a = ',a,', b = ',b,', c = ',c\n",
    "\n",
    "        call sub\n",
    "\n",
    "        print *, 'After the call:'\n",
    "        print *, 'a = ',a,', b = ',b,', c = ',c\n",
    "\n",
    "      END PROGRAM\n",
    "\n",
    "      SUBROUTINE sub\n",
    "\n",
    "        implicit none\n",
    "\n",
    "        integer a,b,c\n",
    "        common /arg/ a,b,c\n",
    "\n",
    "        b = a + c\n",
    "        c = c + 1\n",
    "       \n",
    "      END SUBROUTINE"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e457015",
   "metadata": {},
   "source": [
    "### MODULE Statement (F90)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "71f26006",
   "metadata": {},
   "outputs": [],
   "source": [
    "MODULE arg\n",
    " implicit none\n",
    " integer :: a,b,c\n",
    " real(8) :: x\n",
    "END MODULE arg\n",
    "\n",
    "! * * * * * * * \n",
    "\n",
    "PROGRAM test_arg\n",
    " USE arg\n",
    " implicit none\n",
    "\n",
    " a = 2\n",
    " c = 1\n",
    "\n",
    " write(*,*) 'Before the call:'\n",
    " write(*,'(3(A5,I3))') ' a = ',a,', b = ',b,', c = ',c\n",
    "\n",
    " call sub\n",
    "\n",
    " write(*,*) 'After the call:'\n",
    " write(*,'(3(A5,I3))') 'a = ',a,', b = ',b,', c = ',c\n",
    "\n",
    "END PROGRAM test_arg\n",
    "\n",
    "! * * * * * * * \n",
    "\n",
    "SUBROUTINE sub\n",
    " USE arg, only : a,b,c    ! seuls a b et c sont utiles\n",
    " implicit none\n",
    "\n",
    " b = a + c\n",
    " c = c + 1\n",
    "\n",
    "END SUBROUTINE sub"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0900a54",
   "metadata": {},
   "source": [
    "### NAMELIST (F90)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e3791d4f",
   "metadata": {},
   "outputs": [],
   "source": [
    "PROGRAM test_namelist\n",
    "\n",
    "  implicit none\n",
    "\n",
    "  real(8) lon_min, lon_max, lat_min, lat_max\n",
    "\n",
    "  NAMELIST/namlon/ lon_min, lon_max\n",
    "  NAMELIST/namlat/ lat_min, lat_max\n",
    "\n",
    "  write(*,*) 'Before:'\n",
    "  call print_res(lon_min, lon_max, lat_min, lat_max)\n",
    "\n",
    "  open(161,file='../src/07_namelist.def',status='old',form='formatted')\n",
    "  read(161,NML=namlon)\n",
    "\n",
    "  write(*,*) 'Between:'\n",
    "  call print_res(lon_min, lon_max, lat_min, lat_max)\n",
    "\n",
    "  read(161,NML=namlat)\n",
    "  close (161)\n",
    "\n",
    "  write(*,*) 'After:'\n",
    "  call print_res(lon_min, lon_max, lat_min, lat_max)\n",
    "\n",
    "END\n",
    "\n",
    "SUBROUTINE print_res(a,b,c,d)\n",
    "  implicit none\n",
    "  real(8), intent(in) :: a,b,c,d\n",
    "  write(*,'(4(A12,F6.2))') '  lon_min = ',a,', lon_max = ',b, &\n",
    "                          ', lat_min = ',c,', lat_max = ',d\n",
    "  RETURN\n",
    "END"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c0b0a801",
   "metadata": {},
   "source": [
    "### Hands on learning: structure\n",
    "\n",
    "The aim of this exercise is to work with loops (for or while) in order to draw in a terminal a Christmas tree with its balls.\n",
    "\n",
    "The program must be carried out in Fortran 90. It will take as argument the height of the tree which is a variable of the problem:\n",
    "\n",
    "Height=7\n",
    "```\n",
    "      #\n",
    "     ###\n",
    "    #o###\n",
    "   ##o####\n",
    "  #o#####o#\n",
    " ####o#####o\n",
    "#####o#####o#\n",
    "```\n",
    "This parameter must be supplied at the command line when the program (for example './tree 10'). \n",
    "\n",
    "Balls must be positioned all 6 sharps."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "930eedf9",
   "metadata": {},
   "outputs": [],
   "source": [
    "program ChristmasTree\n",
    "\n",
    "  implicit none\n",
    "\n",
    "\n",
    "\n",
    "end program"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6362d74e",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Fortran",
   "language": "Fortran",
   "name": "fortran_spec"
  },
  "language_info": {
   "file_extension": "f90",
   "mimetype": "text/plain",
   "name": "fortran"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
