Module and Data Sharing 
Programming in the Large
•	Software, in general, is large having multiple units
•	Multiple units designed and developed independently
•	But these units executed together to achieve some common goal
•	Units share data and need to communicate with one another
•	Large software require mechanisms for designing and developing multiple units
•	Flexible and powerful mechanism for Communication or sharing of data essential 
Parameters and Global Variables
•	Fortran provides two means of communication
•	Parameters: Subroutines and main programs can share data via parameters
•	Global Variables: Internal routines and functions can share the variable in the main program
•	Both are restrictive
–	Too many parameters
–	All routines in the same file
•	A more general mechanism desirable for programming in the large
•	Modules is the Fortran Solution for this
Module definition
•	Here is an example module definition

    module example
      implicit none
  save   ! guarantees saving all data values declared

  integer, parameter:: pi = 3.141592
  real:: x, y, z

  real, dimension(100,100):: satellite_data

end module example
Module use
Program using_example

use example   ! appears before all other statement
implicit none

integer:: i, j

do i = 1, 100
   do j = 1, 100
      satellite_data(i, j) = pi * i + j
   end do
end do

call test_routine

end program
Module use in procedures
subroutine test_routine

use example ! like in the program
implicit none

..
satellite_data(i, j) = ...

...

end subroutine
Data Sharing using modules
•	Data declared in different modules can be shared among main program and subroutines and functions
•	Variables can be assigned and updated by all the units
•	Values are retained with SAVE attribute
•	a simple and efficient mechanism for sharing large amount of data
•	No need for passing large amount of data via parameters
•	Modules can be separately compiled and linked later
Procedures can be shared too
   Module example1
      implicit none

      -- shared data ---
   
      contains
         subroutine ex1(x, y, z)
            implicit none 
     
             -- parameter and local variable declarations

            -- body 
         end subroutine

      -- other procedure or function definition

 end module example1
Using the procedures
•	Main program and any procedure that uses the above module can call ex1 and other routines declared
•	Advantage over conventional method
–	increased safety
•	Modules with procedures create (when compiled) EXPLICIT INTERFACES
•	compile with -c option creates .vo file containing the interface
•	Explicit interface for a procedure contains
		no. , type, intent of each argument
•	When the calling program compiled, the compiler checks whether the calls match the interfaces and flag errors, if any
•	When procedures not in a module compiled only an implicit interface is created
–	No details about the procedures
–	compiler can then miss errors leading to strange errors at run-time
High Level Data Types
•	Another use of including procedures in modules is extensibility
•	New data types can be created by the users
•	Suppose we want to create a new data type Polynomails
–	Data Values: all possible ploynomials of, say degree 4
–	Operations:	Addition, Subtraction, multiplication			            by a constant, creation, coefficient 			            extraction
•	Modules useful for defining such a data type
Polynomial data type
Module polynomial
implicit none

type:: poly
  real:: x
  real:: y
  real:: z
  real:: w
end type

contains
  subroutine create(poly_result, x1, y1, z1, w1)
    implicit none
    type (poly), intent(out):: poly_result
    real:: x1, y1, z1, w1
    poly_result%x = x1
    poly_result%y = y1
    poly_result%z = z1
    poly_result%w = w1
  end subroutine
Polynomial Module continued
subroutine add(poly_result, poly1, poly2)
    implicit none
    type (poly), intent(out):: poly_result
    type (poly), intent(in):: poly1, poly2 
    poly_result%x = poly1%x + poly2%x
    poly_result%y = poly1%y + poly2%y
    poly_result%z = poly1%z + poly2%z
    poly_result%w = poly1%w + poly2%w
end subroutine

 subroutine multiply(poly_result, poly1, a)
    implicit none
    type (poly), intent(out):: poly_result
    type (poly), intent(in):: poly1
    real, intent(in):: a
    poly_result%x = a* poly1%x 
    poly_result%y = a* poly1%y
    poly_result%z = a* poly1%z
    poly_result%w = a* poly1%w
end subroutine
The main program
Program poly_main
use polynomial
implicit none

type(poly):: a, b, c, d, e
real:: a1, a2, a3, a4
real:: b1, b2, b3, b4

print *, "type the coefficients of a"
read *, a1, a2, a3, a4

print *, "type the coefficients of b"
read *, b1, b2, b3, b4

call create(a, a1, a2, a3, a4)
call create(b, b1, b2, b3, b4)

call add(c, a, b)
call multiply(d, a, a1)
call multiply(e, b, b1)

print *, c%x, c%y, c%z, c%w
print *, d%x, d%y, d%z, d%w

end program
A Problem
•	Units using a module can access any entities declared in the module
•	For example, the main program above accesses the x,y,z,w components to print the polynomial coefficients
•	But this is undesirable
•	Loss of Abstraction:
–	Polynomial module provides an abstract data type of polynomails
–	The operation like c%x is meaningless at the level of polynomials
–	It is like accessing 5th bit of an integer variable

•	Not robust under change of representation
–	Structures are internal data structures to represent polynomials
–	Suppose tomorrow we choose to use arrays for representing polynomials
–	then the main program would not work
The solution
•	There is a need for an abstract routine that returns any coefficient of a polynomial 
•	But that is not enough - main program can even then access the internal representation
•	There is a need for a mechanism to restrict the access of module components
•	Components can be declared to be public or private
•	For example, the above problem disappears if we declare
        type:: poly
       private
       real:: x
       real:: y
       real:: z
       real:: w
    end type
•	Then any reference to the components like c%x, d%z is illegal
•	Separate routines needed for printing coefficients
Public and Private Components
•	In general, any component, data or routines can be declared public or private
•	The declarations are:
		private:: list of private items
		public:: list of public items
•	A declaration  private inside a module (after implicit none)
–	declares all items to be private
•	Default: all items are public
•	Alternate declarations is:
		integer, public:: x, y, z
		real, private:: a, b, c
Assumed Shape arrays
•	Array parameters in procedures
–	usually the shape of array is explicitly given
–	Example:    real, dimension(n,m):: arr1
			where n,m are also arguments
•	If procedures are declared in a module then no need for specifying n, m
•	They can be automatically found using intrinsic functions
–	LBOUND(arr1,i): lower bound in ith dimesion
                                        (this will be 1)
–	UBOUND(arr1,j): upper bound in the jth dimension
•	Shape and size can be inferred using these functions in called program
•	Actual bounds can not however be inferred
–	use explicit shape array if required