How do you USE Fortran 90 module data

48,490

Solution 1

It's a matter of balance.

If you use only a few stuff from the module, it makes sense if you add ONLY, to clearly specify what you are using.

If you use a lot of stuff from the module, specifying ONLY will be followed by a lot of stuff, so it makes less sense. You are basically cherry-picking what you use, but the true fact is that you are dependent on that module as a whole.

However, in the end the best philosophy is this one: if you are concerned about namespace pollution, and you have a module so large that you feel compelled to add ONLY, it means that your module is too big. Split it.

Update: Fortran? just recode it in python ;)

Solution 2

I used to just do use modulename - then, as my application grew, I found it more and more difficult to find the source to functions (without turning to grep) - some of the other code floating around the office still uses a one-subroutine-per-file, which has its own set of problems, but it makes it much easier to use a text editor to move through the code and quickly track down what you need.

After experiencing this, I've become a convert to using use...only whenever possible. I've also started picking up Python, and view it the same way as from modulename import *. There's a lot of great things that modules give you, but I prefer to keep my global namespace tightly controlled.

Solution 3

Not exactly answering the question here, just throwing in another solution that I have found useful in some circumstances, if for whatever reason you don't want to split your module and start to get namespace clashes. You can use derived types to store several namespaces in one module.

If there is some logical grouping of the variables, you can create your own derived type for each group, store an instance of this type in the module and then you can import just the group that you happen to need.

Small example: We have a lot of data some of which is user input and some that is the result of miscellaneous initializations.

module basicdata
   implicit none
   ! First the data types...
   type input_data
      integer :: a, b
   end type input_data
   type init_data
      integer :: b, c
   end type init_data

   ! ... then declare the data
   type(input_data) :: input
   type(init_data) :: init
end module basicdata

Now if a subroutine only uses data from init, you import just that:

subroutine doesstuff
   use basicdata, only : init
   ...
   q = init%b
end subroutine doesstuff

This is definitely not a universally applicable solution, you get some extra verbosity from the derived type syntax and then it will of course barely help if your module is not the basicdata sort above, but instead more of a allthestuffivebeenmeaningtosortoutvariety. Anyway, I have had some luck in getting code that fits easier into the brain this way.

Solution 4

The main advantage of USE, ONLY for me is that it avoids polluting my global namespace with stuff I don't need.

Solution 5

Agreed with most answers previously given, use ..., only: ... is the way to go, use types when it makes sense, apply python thinking as much as possible. Another suggestion is to use appropriate naming conventions in your imported module, along with private / public statements.

For instance, the netcdf library uses nf90_<some name>, which limits the namespace pollution on the importer side.

use netcdf  ! imported names are prefixed with "nf90_"

nf90_open(...)
nf90_create(...)
nf90_get_var(...)
nf90_close(...)

similarly, the ncio wrapper to this library uses nc_<some name> (nc_read, nc_write...).

Importantly, with such designs where use: ..., only: ... is made less relevant, you'd better control the namespace of the imported module by setting appropriate private / public attributes in the header, so that a quick look at it will be sufficient for readers to assess which level of "pollution" they are facing. This is basically the same as use ..., only: ..., but on the imported module side - thus to be written only once, not at each import).

One more thing: as far as object-orientation and python are concerned, a difference in my view is that fortran does not really encourage type-bound procedures, in part because it is a relatively new standard (e.g. not compatible with a number of tools, and less rationally, it is just unusual) and because it breaks handy behavior such as procedure-free derived type copy (type(mytype) :: t1, t2 and t2 = t1). That means you often have to import the type and all would-be type-bound procedures, instead of just the class. This alone makes fortran code more verbose compared to python, and practical solutions like a prefix naming convention may come in handy.

IMO, the bottom line is: choose your coding style for people who will read it (this includes your later self), as taught by python. The best is the more verbose use ..., only: ... at each import, but in some cases a simple naming convention will do it (if you are disciplined enough...).

Share:
48,490
Pete
Author by

Pete

Mostly working with AWS, Docker, Python, Rails, OpenLayers-3 &amp; Postgis these days.

Updated on May 13, 2020

Comments

  • Pete
    Pete almost 4 years

    Let's say you have a Fortran 90 module containing lots of variables, functions and subroutines. In your USE statement, which convention do you follow:

    1. explicitly declare which variables/functions/subroutines you're using with the , only : syntax, such as USE [module_name], only : variable1, variable2, ...?
    2. Insert a blanket USE [module_name]?

    On the one hand, the only clause makes the code a bit more verbose. However, it forces you to repeat yourself in the code and if your module contains lots of variables/functions/subroutines, things begin to look unruly.

    Here's an example:

    module constants
      implicit none
      real, parameter :: PI=3.14
      real, parameter :: E=2.71828183
      integer, parameter :: answer=42
      real, parameter :: earthRadiusMeters=6.38e6
    end module constants
    
    program test
    ! Option #1:  blanket "use constants"
    !  use constants
    ! Option #2:  Specify EACH variable you wish to use.
      use constants, only : PI,E,answer,earthRadiusMeters
      implicit none
    
      write(6,*) "Hello world.  Here are some constants:"
      write(6,*) PI, &
           E, &
           answer, &
           earthRadiusInMeters
    end program test
    

    Update Hopefully someone says something like "Fortran? Just recode it in C#!" so I can down vote you.


    Update

    I like Tim Whitcomb's answer, which compares Fortran's USE modulename with Python's from modulename import *. A topic which has been on Stack Overflow before:

    • ‘import module’ or ‘from module import’

      • In an answer, Mark Roddy mentioned:

        don't use 'from module import *'. For any reasonable large set of code, if you 'import *' your will likely be cementing it into the module, unable to be removed. This is because it is difficult to determine what items used in the code are coming from 'module', making it east to get to the point where you think you don't use the import anymore but its extremely difficult to be sure.

    • What are good rules of thumb for python imports?

      • dbr's answer contains

        don't do from x import * - it makes your code very hard to understand, as you cannot easily see where a method came from (from x import *; from y import *; my_func() - where is my_func defined?)

    So, I'm leaning towards a consensus of explicitly stating all the items I'm using in a module via

    USE modulename, only : var1, var2, ...
    

    And as Stefano Borini mentions,

    [if] you have a module so large that you feel compelled to add ONLY, it means that your module is too big. Split it.