[For discussion] Initialization levels

Open
#26 · Created  · Last updated

Description

Original Initialization Method

The original way for initialization to be handled in gs2 is for each module to have its own init function. This does the initialization for a module, and makes sure that dependencies are also initialized. Generically, it’s something like:

module my_mod private logical :: initialized = .false. subroutine init_my_mod use dependency, only: init_dependency ! Return if already initialized if (initialized) return initialized = .true. ! Initialize dependencies call init_dependency ! Now initialize my_mod, read namelists, allocate arrays, etc end subroutine init_my_mod subroutine finish_my_mod ! Try to undo everything that happened in init_my_mod end subroutine finish_my_mod end module my_mod

This is usually fine, but it is also limited:

  • It obscures the dependencies between modules. It's common for init_dependency to be called from lots of other init routines. All but one of these calls will do nothing (and so should be deleted) -- without digging, it's hard to see where init_dependency is actually doing the initialization.

  • For testing, or coupling gs2 to other codes, or running multiple instances of gs2 in a single execution, it's important to be able to cleanly initialize and uninitialize modules. For example, one might want to run gs2 with some run_parameters, and then run gs2 again on the same grids, but with some parameters changed. This approach doesn’t support that without uninitializing everything, and starting again.

  • This approach isn't object oriented - it uses global variables. If my_mod really needs dependency, I want to be working with an instance of that dependency.

New Initialization Method

To address these, Edmund introduced initialization levels, copying the approach used in initializing Linux. The idea is that each module is assigned a unique level number, and you can initialize or uninitialize code by calling init(current_level, desired_level). After this call, it is guaranteed that all modules with levels up to desired_level are initialized, and all modules above this are not initialized.

For example, if the current_level=11, and the initialization levels of le_grids and collisions are 12 and 13 respectively, I would initialize collisions by calling init(current_level,collisions_level). What this would actually do is call init_le_grids followed by init_collisions (and then set current_level=13). If I then called init(current_level,le_grids_level), it would uninitialize collisions by calling finish_collisions, but leave le_grids initialized.

The levels are determined from information in the ruby script gs2_init.rb. This script lists modules and their dependencies in the form:

DEPENDENCIES = [ ['module_1', ['dendency_1','dependency_2']], ['module_2', ['dendency_3','dependency_4']], ['collisions', ['le_grids', 'other_stuff']], ['le_grids', ['stuff_not_including_collisions']], ... ]

and from this, auto-generates gs2_init.f90.

So what’s this PR?

The code in gs2 is actually currently a hybrid of these two approaches - the initialization levels approach is used, but init functions also still call their dependencies. That is, in the example above, the subroutine init_collisions calls init_le_grids inside itself, even though the levels method guarantees that le_grids is already initialized.

This PR removes redundant calls to init functions, so that everything is initialized only through the levels approach in gs2_init.f90. This PR also tries to correct/update the dependencies generated in gs2_init.rb. It may seem obscure, but it’s necessary to get proper unit tests working, and to make the code more object oriented.

This branch passes all tests*, but these changes are most likely to affect cases not covered by the tests: Trinity or Gryfx users, people who use flags like LOWFLOW, etc. So this PR is here to

  1. advertise that initialization levels is a thing; and

  2. see if I can tempt people to use this branch instead of `next`, to see what breaks…

*on my laptop, we’ll see what happens in the pipeline…

0 attachments

0 comments

Loading commits...