Fortran

Guide To Learn

Instantiating a derived type

Defining a derived type was the first necessary step, but to actually use it, we need to instantiate one. Instantiating means nothing more than creating a new instance. It’s kind of an unwieldy word, but the more you use it, the more natural it becomes. In listing 8.2, I used a shortcut to declare and initialize a derived type instance in a single statement:

type(Person) :: some_person = Person('Jill')

This is equivalent to a more explicit, two-step process:

type(Person) :: some_person       ❶
some_person = Person('Jill')      ❷

❶ Declares an instance of the Person type

❷ Initializes the new instance

Now we get to our second new syntax element for this chapter–initializing a derived type instance by invoking the name of the type, and passing the values of its components in parentheses: Person('Jill'). This is the default way to initialize a derived type, which requires all components to be passed to the type constructor as arguments, much like we did in procedure calls. For a refresher on invoking Fortran procedures, see section 3.2.1.

Take, for example, a slightly richer type with three components, as shown in the following listing.

Listing 8.3 Attempting to initialize a derived type instance

type :: Person
  character(len=20) :: name         ❶
  integer :: age                    ❶
  character(len=20) :: occupation   ❶
end type Person
 
type(Person) :: some_person         ❷
 
some_person = Person('Bob')         ❸

❶ This type has three components.

❷ Declares a new Person instance

❸ Tries to initialize with just the name argument

If you try to initialize this type with just the name, like in listing 8.3, the compiler will yell back at you:

$ gfortran derived_type_init.f90
derived_type_init.f90:20:16:
 
   some_person = Person('Bob')
                1
Error: No initializer for component ‘age’ given in the structure constructor at (1)

Here, the compiler expected to receive parameters for all three type components, not just the name. This means that the code won’t compile until we provide all input parameters to match all derived type components:

some_person = Person('Bob', 32, 'Engineer')

Back in the tsunami app, our Field type could be initialized as

integer(int32), parameter :: im = 101, jm = 101    ❶
type(Field) :: h                                   ❷
h = Field('Water height', [im, jm])                ❸

❶ Grid size in x and y directions

❷ Declares a field instance

❸ Instantiates using default constructor

Currently, our new Field type still doesn’t do anything interesting, nor does it contain much useful data. We just gave it a name and assigned it a size in each of the two dimensions. However, we’ll be able to use this information for all the setup work, such as decomposition of the domain into parallel tiles, determining start and end indices of data arrays, and allocating the arrays.

Now that we’ve created new instances of the Person and Field types, let’s see how we can access their components.

Instantiating a derived type

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top