Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Spanky Deluxe

macrumors demi-god
Original poster
Mar 17, 2005
5,285
1,789
London, UK
Hi everyone again,

I've coded some test programs that I now want to merge into one program. I'm reading up on how to use the SUBROUTINE definitions and how to pass variables between subroutines, however there's one thing in particular that I don't know how to deal with.

Where do I put the include statements? All my subroutines need to use an include .h file. I've read that when compiling, you need to put the subroutine files first with your main handler program last.

I'm using iFort to compile and my command to compile is as follows, is this correct:

ifort test_subroutine.f90 test_main.f90 -o test.e

Any help would be really appreciated!! :)
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
What I'd say is most analogous to #include is the use keyword. You can "include" modules with:
use modulename

Otherwise the convention I've seen for actual includes is using a file called .i.f/F/F90/F95. Then you can actually use the keyword include. This isn't too common, but you can declare types of functions if needed in a file like this, or just use it as a sort of "inline" method that you can stick into your code.

I'm using G95, but I'll show you my example to see if it helps:
testSub.F95:
Code:
program testSub
  implicit none
  call subA()
end program

testSubA.F95
Code:
subroutine subA()
  implicit none
  write(7,'("In sub!")')
end subroutine

Build object file for testSubA:
Code:
g95 -c testSubA.F95

Build and link executable for testSub:
Code:
g95 testSubA.o -o testSub testSub.F95

I'm sure ifort is a bit different in its syntax, but that's the general idea for most compilers. You need to build all of your objects first, then build/link your executable. Using a makefile can greatly simplify this process.

-Lee
 

Spanky Deluxe

macrumors demi-god
Original poster
Mar 17, 2005
5,285
1,789
London, UK
Thanks for that, I'll start using makefiles soon but I want to understand how to do it manually first.

Can you suggest how to use the use command? I.e. where do I put it.

My code is basically of the format:

test_main.f90:
Code:
program testSub
  include mpif.h
  implicit none
  call subA()
end program

and then test_subroutine.f90:

Code:
subroutine subA()
  include mpif.h
  implicit none
  write(7,'("In sub!")')
end subroutine

I don't know where to put the include line for the mpif.h file. :confused:
 

ChrisA

macrumors G5
Jan 5, 2006
12,918
2,169
Redondo Beach, California
I don't know where to put the include line for the mpif.h file. :confused:

The compilers will have a search path, that is a list of directories it will look it. Normally this path includes the current working directory, the same place that holds your other source code. The gcc compiler excepts a -I switch where you can add directories to the search path.

BTW "include files" must be some recent addition to FORTRAN. You will not see it used in most FORTRAN programs you come across
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
What is in your .h file that you need access to in both programs? Are you trying to use a common block?

Chances are your .h file contains C, so this may not be the right solution.

-Lee
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
You had asked about "use", so I wrote something else up:

testSub.F95:
Code:
program testSub
  use module_test
  implicit none
  type(testType) :: myTest
  myTest%key=5
  myTest%next=2
  myTest%value=int(33432,4)
  call print_testType(myTest)
end program

module_test.F95:
Code:
module testType_mod
  type testType
    sequence
    integer(4) :: key
    integer(2) :: next
    integer(4) :: value
  end type
end module

module module_test
  use testType_mod
  implicit none
  contains
    subroutine print_testType(toPrint)
      implicit none
      type(testType), intent(in) :: toPrint
      write(6,'("Key: ",i12," next: ",i5," value: ",i12)') &
         & toPrint%key,toPrint%next,toPrint%value
    end subroutine
end module

build module:
Code:
g95 -c module_test.F95

build/link executable:
Code:
g95 module_test.o -o testSub testSub.F95

By "use"ing the module_test module, this also "use"s the testType_mod module. Then whenever you "use module_test" you can use the testType type, and you can call the function print_testType.

-Lee
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
The compilers will have a search path, that is a list of directories it will look it. Normally this path includes the current working directory, the same place that holds your other source code. The gcc compiler excepts a -I switch where you can add directories to the search path.

BTW "include files" must be some recent addition to FORTRAN. You will not see it used in most FORTRAN programs you come across

include has been in the language since at least F77, use was introduced with Fortran 90.

-Lee
 

Spanky Deluxe

macrumors demi-god
Original poster
Mar 17, 2005
5,285
1,789
London, UK
What is in your .h file that you need access to in both programs? Are you trying to use a common block?

Chances are your .h file contains C, so this may not be the right solution.

-Lee

I've got no idea what's in there but its necessary to use MPI. Thanks for the code snippets - it makes a bit more sense now!! :)
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
I've got no idea what's in there but its necessary to use MPI. Thanks for the code snippets - it makes a bit more sense now!! :)

Did a search and found this, it is indeed Fortran in that file. If it's in the same directory as the rest of your source, you should be able to just:
Code:
include 'mpif.h'

-Lee
 

Spanky Deluxe

macrumors demi-god
Original poster
Mar 17, 2005
5,285
1,789
London, UK
Did a search and found this, it is indeed Fortran in that file. If it's in the same directory as the rest of your source, you should be able to just:
Code:
include 'mpif.h'

-Lee

Ok, but do you know which file should I put it in? The main program file, the subroutine file or both?
 

crackpip

macrumors regular
Jul 23, 2002
210
0
I use iFort but not on my Mac, let me give you a few pointers.

Employ MODULES. This allows you to more closely approximate object oriented programming, and can significantly improve organization. For example, I abstracted all of my MPI routines into a single module. I did the samething for output using HDF5. It's also very easy to overload procedures and operations in modules.

I love using the preprocessor (-fpp option) for conditional compilation and organization. It's great for debugging. Until submodules are implemented with Fortran 2003, I use a #include directive, which is basically the same as the standard include. for dividing my larger modules into subfiles.

Compilation will go something like this:

For the compilation I do:
mpif90 -fpp <preprocesor definitions> -c module.f90
mpif90 -fpp <preprocesor definitions> -c subroutine.f90
mpif90 -fpp <preprocesor definitions> -c main.f90

Then the linking is
mpif90 -o executable dependencies(.o files) libraries

By the way, which MPI implementation are you using? Your MPI implementation should have a Fortran 90 module. So instead of 'include "mpif.h"', you can 'use mpi' in any module or procedure that has MPI calls in it.

crackpip
 

Spanky Deluxe

macrumors demi-god
Original poster
Mar 17, 2005
5,285
1,789
London, UK
I'm using MPICH2. So can you use the preprocessor to get it to include the mpif.h file? I'm still a real amateur with mpi and Fortran and am learning my way around gradually. When I replace my include line with "use mpi" I get the error "This USE statement is not positioned correctly within the scoping unit." when compiling. I'm a step closer now with compiling by leaving the include line in both the main program and the subrouting but it still feels messy.

Some of this stuff has such a steep learning curve!! Its taken me months to get to where I am now and the depressing this is, I could recreate all of it from scratch now in a mere matter of hours.
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
the use line needs to be between program, function, subroutines lines and implicit none.

The .mod must be compiled when you compile anything that uses it.

-Lee
 

crackpip

macrumors regular
Jul 23, 2002
210
0
I'm using MPICH2. So can you use the preprocessor to get it to include the mpif.h file? I'm still a real amateur with mpi and Fortran and am learning my way around gradually. When I replace my include line with "use mpi" I get the error "This USE statement is not positioned correctly within the scoping unit." when compiling. I'm a step closer now with compiling by leaving the include line in both the main program and the subrouting but it still feels messy.

Some of this stuff has such a steep learning curve!! Its taken me months to get to where I am now and the depressing this is, I could recreate all of it from scratch now in a mere matter of hours.

Yeah, I know how it goes. I had to learn a lot of this stuff on the fly too. The USE statement needs to be the first statement after the PROGRAM statement before the implicit none. When you compile you should use the premade aliases, for example mpif90, this will add in the proper libraries. As an organizational technique, I put at most one program unit in a file. So one module, one major subroutine not associated with a module, or the main program. Sometimes if a module is too large, I'll divide it into subfiles, put them into a subfolder and use the #include directive.

If you're using allocatable arrays, I found that I ran into problems with the MPI packing routines when only exchanging part of an array. I actually get better communication performance if I use the PACK and UNPACK intrinsic functions to pack the subarray into a 1-D array which is sent to the intended process, and unpacked.

The .mod files will be generated when you call 'mpif90 -c module.f90'

crackpip
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.