fabm_types.F90 138 KB
Newer Older
1
#include "fabm_driver.h"
2 3 4 5 6 7 8 9 10 11 12 13 14

! =============================================================================
! fabm_types --- Derived types and procedures for use by biogeochemical models
! -----------------------------------------------------------------------------
! This module contains the derived types and procedures that are used for
! communication between biogeochemical models and FABM. This module provides
! types for storing model data (e.g., metadata for variables and parameters),
! and logic for registration of model objects (state and diagnostic variables),
! retrieval of model settings (parameter values) and coupling.
! =============================================================================

module fabm_types

15
   use fabm_parameters, rk=>rki
16 17
   use fabm_standard_variables, type_bulk_standard_variable => type_universal_standard_variable, &
      type_universal_standard_variable => type_universal_standard_variable
18
   use fabm_properties
19
   use fabm_driver, only: driver
20

21
   implicit none
22

23
   private
24 25 26 27 28

   ! --------------------------------------------------------------------------
   ! Public members
   ! --------------------------------------------------------------------------

Jorn Bruggeman's avatar
Jorn Bruggeman committed
29
   ! Base data type for biogeochemical models.
Jorn Bruggeman's avatar
Jorn Bruggeman committed
30
   public type_base_model
Jorn Bruggeman's avatar
Jorn Bruggeman committed
31

32
   ! Expose symbols defined in fabm_standard_variables module
33
   public standard_variables
34 35
   public type_interior_standard_variable, type_horizontal_standard_variable, type_global_standard_variable, &
      type_universal_standard_variable, type_bottom_standard_variable, type_surface_standard_variable, &
36
      initialize_standard_variables, type_standard_variable_node, type_base_standard_variable, type_standard_variable_set
37

Jorn Bruggeman's avatar
Jorn Bruggeman committed
38
   ! Variable identifier types used by biogeochemical models
39
   public type_variable_id
40 41 42
   public type_diagnostic_variable_id, type_horizontal_diagnostic_variable_id, &
      type_surface_diagnostic_variable_id, type_bottom_diagnostic_variable_id
   public type_state_variable_id, type_surface_state_variable_id, type_bottom_state_variable_id
43 44
   public type_dependency_id, type_surface_dependency_id, type_bottom_dependency_id, type_horizontal_dependency_id, &
      type_global_dependency_id
45
   public type_add_id, type_horizontal_add_id
Jorn Bruggeman's avatar
Jorn Bruggeman committed
46 47

   ! Data types and procedures for variable management - used by FABM internally only.
48
   public type_link, type_link_list, type_link_pointer, type_variable_node, type_variable_set, type_variable_list
49
   public type_internal_variable
50
   public type_cache, type_interior_cache, type_horizontal_cache, type_vertical_cache
51
   public type_model_list, type_model_list_node
Jorn Bruggeman's avatar
Jorn Bruggeman committed
52 53 54

   public get_free_unit
   public get_safe_name
55
   public source2string
56

Jorn Bruggeman's avatar
Jorn Bruggeman committed
57
   public type_expression, type_interior_expression, type_horizontal_expression
Jorn Bruggeman's avatar
Jorn Bruggeman committed
58

59
   public get_aggregate_variable_access, type_aggregate_variable_access, type_contribution
60

61
   public type_coupling_task
62

63 64 65
   ! For backward compatibility (20200302, pre 1.0)
   public type_bulk_standard_variable

Jorn Bruggeman's avatar
Jorn Bruggeman committed
66
   integer, parameter, public :: attribute_length = 256
67

68
   public rk, rke
Karsten Bolding's avatar
Karsten Bolding committed
69

70 71 72 73 74 75 76 77 78 79 80 81
   integer, parameter, public :: domain_interior   = 4, &
                                 domain_horizontal = 8, &
                                 domain_scalar     = 16, &
                                 domain_bottom     = 9, &
                                 domain_surface    = 10

   integer, parameter, public :: source_unknown                  =  0, &
                                 source_do                       =  1, &
                                 source_do_column                =  2, &
                                 source_do_horizontal            =  3, &
                                 source_do_bottom                =  4, &
                                 source_do_surface               =  5, &
Jorn Bruggeman's avatar
Jorn Bruggeman committed
82
                                 source_constant                 =  6, &
83 84 85 86 87 88 89 90 91 92
                                 source_none                     =  6, &
                                 source_get_vertical_movement    =  7, &
                                 source_initialize_state         =  8, &
                                 source_initialize_surface_state =  9, &
                                 source_initialize_bottom_state  = 10, &
                                 source_check_state              = 11, &
                                 source_check_surface_state      = 12, &
                                 source_check_bottom_state       = 13, &
                                 source_get_light_extinction     = 14, &
                                 source_get_drag                 = 15, &
93
                                 source_get_albedo               = 16, &
Jorn Bruggeman's avatar
Jorn Bruggeman committed
94 95
                                 source_external                 = 17, &
                                 source_state                    = 18
96 97 98 99 100 101

   integer, parameter, public :: presence_internal          = 1, &
                                 presence_external_required = 2, &
                                 presence_external_optional = 6

   integer, parameter, public :: prefill_none           = 0, &
102 103
                                 prefill_constant       = -1, &
                                 prefill_previous_value = -2
104 105 106 107 108

   integer, parameter, public :: access_none       = 0, &
                                 access_read       = 1, &
                                 access_set_source = 2, &
                                 access_state      = ior(access_read,access_set_source)
109

110
   integer, parameter, public :: store_index_none = -1
111

Jorn Bruggeman's avatar
Jorn Bruggeman committed
112
   integer, parameter, public :: operator_assign = 0, &
113 114
                                 operator_add    = 1, &
                                 operator_merge_forbidden = 256
115

116 117 118 119 120 121
   integer, parameter, public :: output_none                 = 0, &
                                 output_instantaneous        = 1, &
                                 output_time_integrated      = 2, &
                                 output_time_step_averaged   = 4, &
                                 output_time_step_integrated = 8

122
   ! --------------------------------------------------------------------------
123
   ! Data types for pointers to variable values
124
   ! --------------------------------------------------------------------------
Jorn Bruggeman's avatar
Jorn Bruggeman committed
125 126

   type type_integer_pointer
127
      integer, pointer :: p => null()
Jorn Bruggeman's avatar
Jorn Bruggeman committed
128
   end type
129

130
   type type_real_pointer
131
      real(rk), pointer :: p => null()
132 133 134
   end type

   type type_real_pointer_set
135
      type (type_real_pointer), allocatable :: pointers(:)
136 137 138 139 140 141 142
   contains
      procedure :: append    => real_pointer_set_append
      procedure :: extend    => real_pointer_set_extend
      procedure :: set_value => real_pointer_set_set_value
   end type

   type type_integer_pointer_set
143 144
      type (type_integer_pointer), allocatable :: pointers(:)
      integer                                  :: value = -1
145
   contains
146 147 148 149
      procedure :: append      => integer_pointer_set_append
      procedure :: extend      => integer_pointer_set_extend
      procedure :: set_value   => integer_pointer_set_set_value
      procedure :: is_empty    => integer_pointer_set_is_empty
150
      procedure :: finalize    => integer_pointer_set_finalize
151 152
   end type

153 154 155 156
   ! --------------------------------------------------------------------------
   ! Data types for coupling tasks
   ! --------------------------------------------------------------------------

157
   type type_coupling_task
158 159
      type (type_link), pointer                    :: slave       => null()
      character(len=attribute_length)              :: master_name = ''
160
      class (type_domain_specific_standard_variable), pointer :: master_standard_variable => null()
161 162 163
      logical                                      :: user_specified = .false.
      class (type_coupling_task), pointer          :: previous    => null()
      class (type_coupling_task), pointer          :: next        => null()
164 165 166
   end type

   type type_coupling_task_list
167 168
      class (type_coupling_task), pointer :: first => null()
      logical                             :: includes_custom = .false.
169
   contains
170 171
      procedure :: remove     => coupling_task_list_remove
      procedure :: add        => coupling_task_list_add
172
      procedure :: add_object => coupling_task_list_add_object
173 174
   end type

175
   ! --------------------------------------------------------------------------
176
   ! Data types for variable identifiers used by biogeochemical models
177
   ! --------------------------------------------------------------------------
Jorn Bruggeman's avatar
Jorn Bruggeman committed
178

179
   type, abstract :: type_variable_id
Jorn Bruggeman's avatar
Jorn Bruggeman committed
180 181 182
      type (type_link), pointer :: link => null()
   end type

183 184
   type, extends(type_variable_id) :: type_add_id
      integer :: sum_index = -1
185 186
   end type

187 188
   type, extends(type_variable_id) :: type_horizontal_add_id
      integer :: horizontal_sum_index = -1
189 190
   end type

191 192 193
   type, extends(type_variable_id) :: type_dependency_id
      integer  :: index      = -1
      real(rk) :: background = 0.0_rk
Jorn Bruggeman's avatar
Jorn Bruggeman committed
194 195
   end type

196 197 198
   type, extends(type_variable_id) :: type_horizontal_dependency_id
      integer  :: horizontal_index = -1
      real(rk) :: background       = 0.0_rk
Jorn Bruggeman's avatar
Jorn Bruggeman committed
199 200
   end type

201 202 203 204 205 206
   type, extends(type_horizontal_dependency_id) :: type_bottom_dependency_id
   end type

   type, extends(type_horizontal_dependency_id) :: type_surface_dependency_id
   end type

207 208 209
   type, extends(type_variable_id) :: type_global_dependency_id
      integer  :: global_index = -1
      real(rk) :: background   = 0.0_rk
Jorn Bruggeman's avatar
Jorn Bruggeman committed
210 211
   end type

212 213 214 215 216 217
   type, extends(type_dependency_id) :: type_state_variable_id
      integer :: state_index = -1
      type (type_add_id)            :: sms
      type (type_add_id)            :: movement
      type (type_horizontal_add_id) :: surface_flux
      type (type_horizontal_add_id) :: bottom_flux
Jorn Bruggeman's avatar
Jorn Bruggeman committed
218 219
   end type

220
   type, extends(type_bottom_dependency_id) :: type_bottom_state_variable_id
221 222
      integer :: bottom_state_index = -1
      type (type_horizontal_add_id) :: bottom_sms
Jorn Bruggeman's avatar
Jorn Bruggeman committed
223 224
   end type

225
   type, extends(type_surface_dependency_id) :: type_surface_state_variable_id
226 227
      integer :: surface_state_index = -1
      type (type_horizontal_add_id) :: surface_sms
Jorn Bruggeman's avatar
Jorn Bruggeman committed
228 229
   end type

230 231
   type, extends(type_variable_id) :: type_diagnostic_variable_id
      integer :: write_index = -1
Jorn Bruggeman's avatar
Jorn Bruggeman committed
232 233
   end type

234 235 236 237 238 239 240 241
   type, extends(type_variable_id) :: type_surface_diagnostic_variable_id
      integer :: surface_write_index = -1
   end type

   type, extends(type_variable_id) :: type_bottom_diagnostic_variable_id
      integer :: bottom_write_index = -1
   end type

242 243
   type, extends(type_variable_id) :: type_horizontal_diagnostic_variable_id
      integer :: horizontal_write_index = -1
Jorn Bruggeman's avatar
Jorn Bruggeman committed
244 245
   end type

246
   ! --------------------------------------------------------------------------
247
   ! Data types for contributions to aggregate variables.
248
   ! --------------------------------------------------------------------------
Jorn Bruggeman's avatar
Jorn Bruggeman committed
249

Jorn Bruggeman's avatar
Jorn Bruggeman committed
250
   type type_contribution
251 252 253 254
      class (type_domain_specific_standard_variable), pointer :: target => null()
      real(rk)                                     :: scale_factor = 1.0_rk
      logical                                      :: include_background = .false.
      type (type_contribution),            pointer :: next => null()
255 256
   end type

Jorn Bruggeman's avatar
Jorn Bruggeman committed
257
   type type_contribution_list
258
      type (type_contribution), pointer :: first => null()
Jorn Bruggeman's avatar
Jorn Bruggeman committed
259 260
   contains
      procedure :: add => contribution_list_add
261 262
   end type

263
   type type_aggregate_variable_access
264 265 266
      class (type_domain_specific_standard_variable), pointer :: standard_variable => null()
      integer                                                 :: access            = access_none
      type (type_aggregate_variable_access),          pointer :: next              => null()
Jorn Bruggeman's avatar
Jorn Bruggeman committed
267 268
   end type

269 270 271 272
   ! --------------------------------------------------------------------------
   ! Data types for collections of variables
   ! --------------------------------------------------------------------------

273
   type type_link_list
274 275
      type (type_link), pointer :: first => null()
      type (type_link), pointer :: last  => null()
276 277 278 279 280 281 282 283
   contains
      procedure :: append   => link_list_append
      procedure :: find     => link_list_find
      procedure :: count    => link_list_count
      procedure :: finalize => link_list_finalize
      procedure :: extend   => link_list_extend
   end type

284
   type type_link_pointer
285 286
      type (type_link),         pointer :: p    => null()
      type (type_link_pointer), pointer :: next => null()
287 288
   end type

289 290 291
   type type_variable_node
      type (type_internal_variable), pointer :: target => null()
      type (type_variable_node),     pointer :: next   => null()
Jorn Bruggeman's avatar
Jorn Bruggeman committed
292 293 294
   end type

   type type_variable_set
295
      type (type_variable_node), pointer :: first => null()
Jorn Bruggeman's avatar
Jorn Bruggeman committed
296 297 298 299 300 301 302 303 304
   contains
      procedure :: add      => variable_set_add
      procedure :: update   => variable_set_update
      procedure :: remove   => variable_set_remove
      procedure :: contains => variable_set_contains
      procedure :: finalize => variable_set_finalize
   end type

   type type_variable_list
305 306
      type (type_variable_node), pointer :: first => null()
      integer                            :: count = 0
Jorn Bruggeman's avatar
Jorn Bruggeman committed
307 308 309 310
   contains
      procedure :: append => variable_list_append
   end type

311
   ! --------------------------------------------------------------------------
312
   ! Data types for information on model variables and model references
313
   ! --------------------------------------------------------------------------
314

315
   type type_internal_variable
Jorn Bruggeman's avatar
Jorn Bruggeman committed
316 317 318
      character(len=attribute_length) :: name      = ''
      character(len=attribute_length) :: long_name = ''
      type (type_property_dictionary) :: properties
319 320 321 322
      character(len=attribute_length) :: units          = ''
      real(rk)                        :: minimum        = -1.e20_rk
      real(rk)                        :: maximum        =  1.e20_rk
      real(rk)                        :: missing_value  = -2.e20_rk
323
      real(rk)                        :: prefill_value  = -2.e20_rk
324 325 326
      real(rk)                        :: initial_value  = 0.0_rk
      integer                         :: output         = output_instantaneous
      integer                         :: presence       = presence_internal
327
      integer                         :: domain         = domain_interior
328
      integer                         :: source         = source_unknown
329
      integer                         :: prefill        = prefill_none
Jorn Bruggeman's avatar
Jorn Bruggeman committed
330
      integer                         :: write_operator = operator_assign
331
      class (type_base_model),pointer :: owner          => null()
Jorn Bruggeman's avatar
Jorn Bruggeman committed
332 333
      type (type_contribution_list)   :: contributions

334
      type (type_standard_variable_set) :: standard_variables
335

336 337
      logical :: fake_state_variable = .false.

338
      ! Only used for interior state variables:
339 340
      logical :: no_precipitation_dilution = .false.
      logical :: no_river_dilution         = .false.
341

342 343 344 345 346
      integer, pointer :: read_index  => null()
      integer, pointer :: write_index => null()
      integer          :: store_index = store_index_none
      integer          :: catalog_index = -1
      logical          :: has_data = .false.
347 348

      ! Collections to collect information from all coupled variables.
349
      type (type_integer_pointer_set)  :: read_indices, state_indices, write_indices
350
      type (type_real_pointer_set)     :: background_values
351
      type (type_link_list)            :: sms_list, surface_flux_list, bottom_flux_list, movement_list
352 353 354 355 356 357 358 359 360
      type (type_link), pointer        :: sms_sum             => null()
      type (type_link), pointer        :: surface_flux_sum    => null()
      type (type_link), pointer        :: bottom_flux_sum     => null()
      type (type_link), pointer        :: movement_sum        => null()
      type (type_link), pointer        :: sms                 => null()
      type (type_link), pointer        :: surface_flux        => null()
      type (type_link), pointer        :: bottom_flux         => null()

      type (type_internal_variable), pointer :: write_owner => null()
361
      type (type_variable_set),      pointer :: cowriters   => null()
362
      type (type_link_pointer),      pointer :: first_link  => null()
363
   end type
Jorn Bruggeman's avatar
Jorn Bruggeman committed
364

Jorn Bruggeman's avatar
Jorn Bruggeman committed
365
   type type_link
366 367 368 369
      character(len=attribute_length)        :: name     = ''
      type (type_internal_variable), pointer :: target   => null()
      type (type_internal_variable), pointer :: original => null()
      type (type_link), pointer              :: next     => null()
370 371
   end type

372
   ! --------------------------------------------------------------------------
373
   ! Data type for custom expressions (arbitrary functions of one or more
374 375
   ! variables).
   ! --------------------------------------------------------------------------
Jorn Bruggeman's avatar
Jorn Bruggeman committed
376

377
   type, abstract :: type_expression
378 379
      class (type_expression), pointer :: next        => null()
      character(len=attribute_length)  :: output_name = ''
380
      integer, pointer :: out => null()
381 382
   end type

Jorn Bruggeman's avatar
Jorn Bruggeman committed
383
   type, abstract, extends(type_expression) :: type_interior_expression
384
      !type (type_interior_data_pointer), pointer :: out => null()
385 386
   end type

387 388
   type, abstract, extends(type_expression) :: type_horizontal_expression
      !type (type_horizontal_data_pointer), pointer :: out => null()
389 390
   end type

391
   ! --------------------------------------------------------------------------
392
   ! Data type for collection of models
393
   ! --------------------------------------------------------------------------
394

Jorn Bruggeman's avatar
Jorn Bruggeman committed
395
   type type_model_list_node
396 397
      class (type_base_model),     pointer :: model => null()
      type (type_model_list_node), pointer :: next  => null()
Jorn Bruggeman's avatar
Jorn Bruggeman committed
398 399 400
   end type

   type type_model_list
401
      type (type_model_list_node), pointer :: first => null()
Jorn Bruggeman's avatar
Jorn Bruggeman committed
402
   contains
403 404 405 406 407 408 409 410
      procedure :: append     => model_list_append
      procedure :: extend     => model_list_extend
      procedure :: find_name  => model_list_find_name
      procedure :: find_model => model_list_find_model
      procedure :: count      => model_list_count
      procedure :: finalize   => model_list_finalize
      procedure :: print      => model_list_print
      generic   :: find       => find_name, find_model
Jorn Bruggeman's avatar
Jorn Bruggeman committed
411 412
   end type

413 414 415 416 417
   ! --------------------------------------------------------------------------
   ! Base model type, used by biogeochemical models to inherit from, and by
   ! external host to get variable lists and metadata.
   ! --------------------------------------------------------------------------

Jorn Bruggeman's avatar
Jorn Bruggeman committed
418
   type type_base_model
419
      ! Flag determining whether the contents of the type are "frozen", i.e., they will not change anymore.
Jorn Bruggeman's avatar
Jorn Bruggeman committed
420
      logical :: frozen = .false.
421

422
      ! Flag determining whether this model was explicitly created by the user (by it appearing as instance in fabm.yaml)
423 424
      logical :: user_created = .false.

425
      ! Pointers to linked models in the model tree.
426 427
      class (type_base_model), pointer :: parent => null()
      type (type_model_list)           :: children
428

429
      ! Model name and variable prefixes.
430 431 432
      character(len=attribute_length) :: name      = ''
      character(len=attribute_length) :: long_name = ''
      character(len=attribute_length) :: type_name = ''
433

Jorn Bruggeman's avatar
Jorn Bruggeman committed
434
      ! Models constituents: links to variables, coupling requests, parameters, expressions
435
      type (type_link_list) :: links
436
      type (type_aggregate_variable_access), pointer :: first_aggregate_variable_access => null()
437

438
      type (type_hierarchical_dictionary) :: couplings
439
      type (type_hierarchical_dictionary) :: parameters
440

441 442
      class (type_expression), pointer :: first_expression => null()

443
      type (type_coupling_task_list) :: coupling_task_list
444

Jorn Bruggeman's avatar
Jorn Bruggeman committed
445
      real(rk) :: dt = 1.0_rk
Jorn Bruggeman's avatar
Jorn Bruggeman committed
446
      real(rk) :: rdt__ = 1.0_rk
Jorn Bruggeman's avatar
Jorn Bruggeman committed
447 448

      logical :: check_conservation = .false.
449

450 451 452
      type (type_add_id)            :: extinction_id
      type (type_horizontal_add_id) :: albedo_id
      type (type_horizontal_add_id) :: surface_drag_id
453 454

      integer, allocatable :: implemented(:)
455 456
   contains

457
      ! Procedure for adding child models [during initialization only]
Jorn Bruggeman's avatar
Jorn Bruggeman committed
458 459
      procedure :: add_child

460
      ! Procedures for adding variables [during initialization only]
461
      procedure :: add_interior_variable
462 463 464 465 466 467 468 469 470 471
      procedure :: add_horizontal_variable
      procedure :: add_scalar_variable
      procedure :: add_object

      ! Procedures for locating links, objects, models.
      procedure :: find_link
      procedure :: find_object
      procedure :: find_model

      ! Procedures for requesting coupling between variables
Jorn Bruggeman's avatar
Jorn Bruggeman committed
472 473 474
      procedure :: request_coupling_for_link
      procedure :: request_coupling_for_name
      procedure :: request_coupling_for_id
475 476
      procedure :: request_standard_coupling_for_link
      procedure :: request_standard_coupling_for_id
477 478
      generic   :: request_coupling => request_coupling_for_link, request_coupling_for_name, request_coupling_for_id, &
                                       request_standard_coupling_for_link, request_standard_coupling_for_id
479

480 481 482 483 484 485 486 487 488 489 490 491
      ! Procedures that may be used to query parameter values during initialization.
      procedure :: get_real_parameter
      procedure :: get_integer_parameter
      procedure :: get_logical_parameter
      procedure :: get_string_parameter
      generic :: get_parameter => get_real_parameter,get_integer_parameter,get_logical_parameter,get_string_parameter

      procedure :: set_variable_property_real
      procedure :: set_variable_property_integer
      procedure :: set_variable_property_logical
      generic   :: set_variable_property => set_variable_property_real,set_variable_property_integer,set_variable_property_logical

492
      procedure :: add_variable_to_aggregate_variable
493
      procedure :: add_constant_to_aggregate_variable
494
      generic :: add_to_aggregate_variable => add_variable_to_aggregate_variable, &
495
                                              add_constant_to_aggregate_variable
496

497
      ! Procedures that may be used to register model variables and dependencies during initialization.
498 499 500
      procedure :: register_source
      procedure :: register_surface_flux
      procedure :: register_bottom_flux
Jorn Bruggeman's avatar
Jorn Bruggeman committed
501 502
      procedure :: register_surface_source
      procedure :: register_bottom_source
503

504
      procedure :: register_interior_state_variable
505 506
      procedure :: register_bottom_state_variable
      procedure :: register_surface_state_variable
507

508
      procedure :: register_interior_diagnostic_variable
509 510
      procedure :: register_surface_diagnostic_variable
      procedure :: register_bottom_diagnostic_variable
511
      procedure :: register_horizontal_diagnostic_variable
512

513 514
      procedure :: register_named_interior_dependency
      procedure :: register_standard_interior_dependency
515
      procedure :: register_universal_interior_dependency
516 517
      procedure :: register_named_horizontal_dependency
      procedure :: register_standard_horizontal_dependency
518
      procedure :: register_universal_horizontal_dependency
519 520 521 522 523 524
      procedure :: register_named_surface_dependency
      procedure :: register_standard_surface_dependency
      procedure :: register_universal_surface_dependency
      procedure :: register_named_bottom_dependency
      procedure :: register_standard_bottom_dependency
      procedure :: register_universal_bottom_dependency
525 526 527
      procedure :: register_named_global_dependency
      procedure :: register_standard_global_dependency

528
      generic :: register_interior_dependency   => register_named_interior_dependency, register_standard_interior_dependency, &
529
                                                   register_universal_interior_dependency
530
      generic :: register_horizontal_dependency => register_named_horizontal_dependency, register_standard_horizontal_dependency, &
531
                                                   register_universal_horizontal_dependency
532 533 534 535
      generic :: register_surface_dependency    => register_named_surface_dependency, register_standard_surface_dependency, &
                                                   register_universal_surface_dependency
      generic :: register_bottom_dependency     => register_named_bottom_dependency, register_standard_bottom_dependency, &
                                                   register_universal_bottom_dependency
536
      generic :: register_global_dependency     => register_named_global_dependency, register_standard_global_dependency
537

538 539 540
      procedure :: register_interior_state_dependency
      procedure :: register_bottom_state_dependency
      procedure :: register_surface_state_dependency
541
      procedure :: register_standard_interior_state_dependency
542 543
      procedure :: register_standard_bottom_state_dependency
      procedure :: register_standard_surface_state_dependency
544

545
      procedure :: register_interior_expression_dependency
546
      procedure :: register_horizontal_expression_dependency
547
      generic :: register_expression_dependency => register_interior_expression_dependency, register_horizontal_expression_dependency
548

549
      generic :: register_state_variable      => register_interior_state_variable, register_bottom_state_variable, &
Jorn Bruggeman's avatar
Jorn Bruggeman committed
550
                                                 register_surface_state_variable
551 552
      generic :: register_diagnostic_variable => register_interior_diagnostic_variable, register_horizontal_diagnostic_variable, &
                                                 register_surface_diagnostic_variable, register_bottom_diagnostic_variable
553
      generic :: register_dependency          => register_named_interior_dependency, register_standard_interior_dependency, &
554
                                                 register_universal_interior_dependency, &
555
                                                 register_named_horizontal_dependency, register_standard_horizontal_dependency, &
556
                                                 register_universal_horizontal_dependency, &
557 558 559 560
                                                 register_named_surface_dependency, register_standard_surface_dependency, &
                                                 register_universal_surface_dependency, &
                                                 register_named_bottom_dependency, register_standard_bottom_dependency, &
                                                 register_universal_bottom_dependency, &
561
                                                 register_named_global_dependency, register_standard_global_dependency, &
562 563 564
                                                 register_interior_expression_dependency, register_horizontal_expression_dependency
      generic :: register_state_dependency    => register_interior_state_dependency, register_bottom_state_dependency, &
                                                 register_surface_state_dependency, &
565 566
                                                 register_standard_interior_state_dependency, &
                                                 register_standard_bottom_state_dependency, &
567
                                                 register_standard_surface_state_dependency
568

569 570 571 572 573
      ! ----------------------------------------------------------------------------------------------------
      ! Procedures below may be overridden by biogeochemical models to provide custom data or functionality.
      ! ----------------------------------------------------------------------------------------------------

      ! Model initialization.
574 575 576 577
      procedure :: initialize               => base_initialize
      procedure :: initialize_state         => base_initialize_state
      procedure :: initialize_surface_state => base_initialize_horizontal_state
      procedure :: initialize_bottom_state  => base_initialize_horizontal_state
578 579

      ! Providing process rates and diagnostics in pelagic, at surface, and at bottom.
580
      procedure :: do                       => base_do
581 582
      procedure :: do_bottom                => base_do_bottom
      procedure :: do_surface               => base_do_surface
Jorn Bruggeman's avatar
Jorn Bruggeman committed
583
      procedure :: do_horizontal            => base_do_horizontal
584
      procedure :: do_ppdd                  => base_do_ppdd
585
      procedure :: do_bottom_ppdd           => base_do_bottom_ppdd
Jorn Bruggeman's avatar
Jorn Bruggeman committed
586
      procedure :: do_column                => base_do_column
587 588 589
      procedure :: get_vertical_movement    => base_get_vertical_movement

      ! Bookkeeping: calculate total of conserved quantities, check and repair model state.
590
      procedure :: check_state              => base_check_state
591 592
      procedure :: check_surface_state      => base_check_surface_state
      procedure :: check_bottom_state       => base_check_bottom_state
Jorn Bruggeman's avatar
Jorn Bruggeman committed
593
      procedure :: fatal_error              => base_fatal_error
594
      procedure :: log_message              => base_log_message
595
      procedure :: get_path                 => base_get_path
596

597 598 599
      ! Hooks called by FABM - usable by inheriting models
      procedure :: before_coupling => base_before_coupling
      procedure :: after_coupling  => base_after_coupling
600

601 602
      procedure :: implements
      procedure :: register_implemented_routines
Jorn Bruggeman's avatar
Jorn Bruggeman committed
603 604 605 606 607 608

      ! Deprecated as of FABM 1.0
      procedure :: get_light                => base_get_light
      procedure :: get_light_extinction     => base_get_light_extinction
      procedure :: get_drag                 => base_get_drag
      procedure :: get_albedo               => base_get_albedo
Jorn Bruggeman's avatar
Jorn Bruggeman committed
609
   end type type_base_model
610

Jorn Bruggeman's avatar
Jorn Bruggeman committed
611
   ! ====================================================================================================
612
   ! Derived type for cache for all input/output during model calls.
Jorn Bruggeman's avatar
Jorn Bruggeman committed
613
   ! ====================================================================================================
614

615
   type type_cache
616
      ! Number of active items in a single cache line [first dimension of any spatially explicit caches below]
617 618
      integer :: n = 1

619
      ! Read cache (separate interior, horizontal, scalar fields).
Jorn Bruggeman's avatar
Jorn Bruggeman committed
620 621 622
      real(rk), allocatable _DIMENSION_SLICE_PLUS_1_            :: read
      real(rk), allocatable _DIMENSION_HORIZONTAL_SLICE_PLUS_1_ :: read_hz
      real(rk), allocatable, dimension(:)                       :: read_scalar
623

624
#ifdef _FABM_MASK_TYPE_
625
      ! Index mapping between source arrays and packed data
Jorn Bruggeman's avatar
Jorn Bruggeman committed
626
      integer, allocatable _DIMENSION_SLICE_ :: ipack
627
      integer, allocatable _DIMENSION_SLICE_ :: iunpack
628
#endif
629 630 631 632 633

      logical :: repair
      logical :: valid
      logical :: set_interior
      logical :: set_horizontal
634 635 636 637
   end type

   type, extends(type_cache) :: type_interior_cache
      ! Write cache (separate interior, horizontal fields).
638
      real(rk), allocatable _DIMENSION_SLICE_PLUS_1_  :: write
639 640 641 642
   end type

   type, extends(type_cache) :: type_horizontal_cache
      ! Write cache (separate interior, horizontal fields).
643
      real(rk), allocatable _DIMENSION_HORIZONTAL_SLICE_PLUS_1_ :: write_hz
644 645 646 647
   end type

   type, extends(type_cache) :: type_vertical_cache
      ! Write cache (separate interior, horizontal fields).
648 649
      real(rk), allocatable _DIMENSION_SLICE_PLUS_1_            :: write
      real(rk), allocatable _DIMENSION_HORIZONTAL_SLICE_PLUS_1_ :: write_hz
650
   end type
651

652
   ! ====================================================================================================
Jorn Bruggeman's avatar
Jorn Bruggeman committed
653 654 655 656 657 658
   ! Base type for a model object factory (generates a model object from a model name)
   ! An implementation of this type is provided in fabm_library.F90.
   ! Institutes or groups can create inherit from this type to create their own model factories,
   ! which then need to be added to the root factory in fabm_library.F90.
   ! This makes it possible to introduce a large number of new models with only two lines added
   ! in the FABM core.
659 660
   ! ====================================================================================================

661
   type, public :: type_version
662 663 664 665
      character(len=attribute_length) :: module_name    = ''
      character(len=attribute_length) :: version_string = ''
      type (type_version), pointer    :: next           => null()
   end type
666
   type (type_version), pointer, save, public :: first_module_version => null()
667

668
   type type_base_model_factory_node
669 670 671
      character(len=attribute_length)              :: prefix  = ''
      class (type_base_model_factory),     pointer :: factory => null()
      type (type_base_model_factory_node), pointer :: next    => null()
672 673
   end type

674 675 676
   type, public :: type_base_model_factory
      type (type_base_model_factory_node), pointer :: first_child => null()
      logical                                      :: initialized = .false.
Jorn Bruggeman's avatar
Jorn Bruggeman committed
677
   contains
678 679 680 681
      procedure :: initialize       => abstract_model_factory_initialize
      procedure :: add              => abstract_model_factory_add
      procedure :: create           => abstract_model_factory_create
      procedure :: register_version => abstract_model_factory_register_version
Jorn Bruggeman's avatar
Jorn Bruggeman committed
682 683
   end type

684
   class (type_base_model_factory), pointer, save, public :: factory => null()
Jorn Bruggeman's avatar
Jorn Bruggeman committed
685

686
contains
687

688 689 690
   subroutine base_initialize(self, configunit)
      class (type_base_model), intent(inout), target :: self
      integer,                 intent(in)            :: configunit
Jorn Bruggeman's avatar
Jorn Bruggeman committed
691 692
   end subroutine

693
   subroutine base_initialize_state(self, _ARGUMENTS_INITIALIZE_STATE_)
Jorn Bruggeman's avatar
Jorn Bruggeman committed
694
      class (type_base_model), intent(in) :: self
695
      _DECLARE_ARGUMENTS_INITIALIZE_STATE_
Jorn Bruggeman's avatar
Jorn Bruggeman committed
696 697
   end subroutine

698
   subroutine base_initialize_horizontal_state(self, _ARGUMENTS_INITIALIZE_HORIZONTAL_STATE_)
Jorn Bruggeman's avatar
Jorn Bruggeman committed
699
      class (type_base_model), intent(in) :: self
700
      _DECLARE_ARGUMENTS_INITIALIZE_HORIZONTAL_STATE_
Jorn Bruggeman's avatar
Jorn Bruggeman committed
701
   end subroutine
702 703

   ! Providing process rates and diagnostics
704 705
   subroutine base_do(self, _ARGUMENTS_DO_)
      class (type_base_model), intent(in) :: self
706
      _DECLARE_ARGUMENTS_DO_
Jorn Bruggeman's avatar
Jorn Bruggeman committed
707 708
   end subroutine

709 710
   subroutine base_do_ppdd(self, _ARGUMENTS_DO_PPDD_)
      class (type_base_model), intent(in) :: self
711
      _DECLARE_ARGUMENTS_DO_PPDD_
712
      call self%do(_ARGUMENTS_DO_)
Jorn Bruggeman's avatar
Jorn Bruggeman committed
713 714
   end subroutine

715 716
   subroutine base_do_bottom(self, _ARGUMENTS_DO_BOTTOM_)
      class (type_base_model), intent(in) :: self
717
      _DECLARE_ARGUMENTS_DO_BOTTOM_
Jorn Bruggeman's avatar
Jorn Bruggeman committed
718 719
   end subroutine

720 721
   subroutine base_do_bottom_ppdd(self, _ARGUMENTS_DO_BOTTOM_PPDD_)
      class (type_base_model), intent(in) :: self
722
      _DECLARE_ARGUMENTS_DO_BOTTOM_PPDD_
Jorn Bruggeman's avatar
Jorn Bruggeman committed
723 724
   end subroutine

725
   subroutine base_do_surface(self, _ARGUMENTS_DO_SURFACE_)
Jorn Bruggeman's avatar
Jorn Bruggeman committed
726
      class (type_base_model), intent(in) :: self
727
      _DECLARE_ARGUMENTS_DO_SURFACE_
Jorn Bruggeman's avatar
Jorn Bruggeman committed
728
   end subroutine
729

730 731
   subroutine base_do_horizontal(self, _ARGUMENTS_HORIZONTAL_)
      class (type_base_model), intent(in) :: self
Jorn Bruggeman's avatar
Jorn Bruggeman committed
732 733