LCOV - code coverage report
Current view: top level - common - mo_common_read_config.F90 (source / functions) Hit Total Coverage
Test: mHM coverage Lines: 98 113 86.7 %
Date: 2024-04-15 17:48:09 Functions: 4 4 100.0 %

          Line data    Source code
       1             : !> \file mo_common_read_config.f90
       2             : !> \brief   \copybrief mo_common_read_config
       3             : !> \details \copydetails mo_common_read_config
       4             : 
       5             : !> \brief Reading of main model configurations.
       6             : !> \details This routine reads the configurations of namelists commonly used by mHM, mRM and MPR
       7             : !> \authors Matthias Zink
       8             : !> \date Dec 2012
       9             : !> \copyright Copyright 2005-\today, the mHM Developers, Luis Samaniego, Sabine Attinger: All rights reserved.
      10             : !! mHM is released under the LGPLv3+ license \license_note
      11             : !> \ingroup f_common
      12             : MODULE mo_common_read_config
      13             : 
      14             :   USE mo_kind, ONLY : i4, dp
      15             :   use mo_message, only: error_message
      16             : 
      17             :   IMPLICIT NONE
      18             : 
      19             :   PRIVATE
      20             : 
      21             :   PUBLIC :: common_read_config, set_land_cover_scenes_id
      22             : 
      23             :   ! ------------------------------------------------------------------
      24             : 
      25             : CONTAINS
      26             : 
      27             : 
      28             :   !> \brief Read main configurations commonly used by mHM, mRM and MPR
      29             :   !> \details Read the main configurations commonly used by mHM, mRM and MPR, namely:
      30             :   !! project_description, directories_general, mainconfig, processSelection, LCover
      31             :   !> \changelog
      32             :   !! - Robert Schweppe Dec  2018
      33             :   !!   - refactoring and restructuring
      34             :   !! - Sebastian Müller Mar 2023
      35             :   !!   - added check_L0Domain
      36             :   !> \authors Matthias Zink
      37             :   !> \date Dec 2012
      38          14 :   subroutine common_read_config(file_namelist, unamelist)
      39             : 
      40             :     use mo_common_constants, only : maxNLcovers, maxNoDomains
      41             :     use mo_common_variables, only : Conventions, LC_year_end, LC_year_start, LCfilename, contact, &
      42             :                                     dirCommonFiles, dirConfigOut, dirLCover, dirMorpho, dirOut, &
      43             :                                     mhmFileRestartOut, mrmFileRestartOut, &
      44             :                                     fileLatLon, history, iFlag_cordinate_sys, mHM_details, domainMeta, nLcoverScene, &
      45             :                                     nProcesses, nuniqueL0Domains, processMatrix, project_details, resolutionHydrology, &
      46             :                                     setup_description, simulation_type, write_restart
      47             :     use mo_nml, only : close_nml, open_nml, position_nml
      48             :     use mo_string_utils, only : num2str
      49             : 
      50             :     implicit none
      51             : 
      52             :     !> name of file
      53             :     character(*), intent(in) :: file_namelist
      54             : 
      55             :     !> id of file
      56             :     integer, intent(in) :: unamelist
      57             : 
      58             :     ! Choosen process description number
      59             :     integer(i4), dimension(nProcesses) :: processCase
      60             : 
      61             :     character(256), dimension(maxNoDomains) :: dir_Morpho
      62             : 
      63             :     character(256), dimension(maxNoDomains) :: mhm_file_RestartOut
      64             : 
      65             :     character(256), dimension(maxNoDomains) :: mrm_file_RestartOut
      66             : 
      67             :     character(256), dimension(maxNoDomains) :: dir_LCover
      68             : 
      69             :     character(256), dimension(maxNoDomains) :: dir_Out
      70             : 
      71             :     character(256), dimension(maxNoDomains) :: file_LatLon
      72             : 
      73         714 :     real(dp), dimension(maxNoDomains) :: resolution_Hydrology
      74             : 
      75             :     integer(i4), dimension(maxNoDomains) :: L0Domain
      76             : 
      77             :     integer(i4), dimension(maxNoDomains) :: read_opt_domain_data
      78             : 
      79             :     ! starting year LCover
      80             :     integer(i4), dimension(maxNLCovers) :: LCoverYearStart
      81             : 
      82             :     ! ending year LCover
      83             :     integer(i4), dimension(maxNLCovers) :: LCoverYearEnd
      84             : 
      85             :     ! filename of Lcover file
      86             :     character(256), dimension(maxNLCovers) :: LCoverfName
      87             : 
      88             :     integer(i4) :: i, newDomainID, domainID, iDomain, nDomains
      89             : 
      90             :     ! flag to advance nuniqueL0Domain counter
      91             :     logical :: addCounter
      92             : 
      93             : 
      94             :     ! define namelists
      95             :     ! namelist directories
      96             :     namelist /project_description/ project_details, setup_description, simulation_type, &
      97             :             Conventions, contact, mHM_details, history
      98             :     namelist /directories_general/ dirConfigOut, dirCommonFiles, &
      99             :             dir_Morpho, dir_LCover, &
     100             :             dir_Out, mhm_file_RestartOut, mrm_file_RestartOut, &
     101             :             file_LatLon
     102             :     ! namelist spatial & temporal resolution, optimization information
     103             :     namelist /mainconfig/ iFlag_cordinate_sys, resolution_Hydrology, nDomains, L0Domain, write_restart, &
     104             :             read_opt_domain_data
     105             :     ! namelist process selection
     106             :     namelist /processSelection/ processCase
     107             : 
     108             :     ! namelist for land cover scenes
     109             :     namelist/LCover/nLcoverScene, LCoverYearStart, LCoverYearEnd, LCoverfName
     110             : 
     111             :     !===============================================================
     112             :     !  Read namelist main directories
     113             :     !===============================================================
     114          14 :     call open_nml(file_namelist, unamelist, quiet = .true.)
     115             : 
     116             :     !===============================================================
     117             :     !  Read namelist specifying the project description
     118             :     !===============================================================
     119          14 :     call position_nml('project_description', unamelist)
     120          14 :     read(unamelist, nml = project_description)
     121             : 
     122             :     !===============================================================
     123             :     !  Read namelist specifying the model configuration
     124             :     !===============================================================
     125          14 :     call position_nml('mainconfig', unamelist)
     126          14 :     read(unamelist, nml = mainconfig)
     127             : 
     128          14 :     call init_domain_variable(nDomains, read_opt_domain_data(1:nDomains), domainMeta)
     129             : 
     130          14 :     if (nDomains .GT. maxNoDomains) then
     131           0 :       call error_message('***ERROR: Number of domains is resticted to ', trim(num2str(maxNoDomains)), '!')
     132             :     end if
     133             : 
     134          14 :     call check_L0Domain(L0Domain, nDomains)
     135             : 
     136             :     ! allocate patharray sizes
     137          42 :     allocate(resolutionHydrology(domainMeta%nDomains))
     138          42 :     allocate(dirMorpho(domainMeta%nDomains))
     139          28 :     allocate(mhmFileRestartOut(domainMeta%nDomains))
     140          28 :     allocate(mrmFileRestartOut(domainMeta%nDomains))
     141          28 :     allocate(dirLCover(domainMeta%nDomains))
     142          28 :     allocate(dirOut(domainMeta%nDomains))
     143          28 :     allocate(fileLatLon(domainMeta%nDomains))
     144          42 :     allocate(domainMeta%L0DataFrom(domainMeta%nDomains))
     145          28 :     allocate(domainMeta%optidata(domainMeta%nDomains))
     146          28 :     allocate(domainMeta%doRouting(domainMeta%nDomains))
     147             : 
     148          14 :     nuniqueL0Domains = 0_i4
     149          40 :     do iDomain = 1, domainMeta%nDomains
     150          26 :       domainID = domainMeta%indices(iDomain)
     151          26 :       resolutionHydrology(iDomain) = resolution_Hydrology(domainID)
     152             :       ! if a domain uses the same L0 data as a previous one, write
     153             :       ! the index into domainMeta%L0DataFrom
     154          26 :       newDomainID = L0Domain(domainID)
     155          26 :       domainMeta%L0DataFrom(iDomain) = iDomain
     156             :       !
     157          26 :       addCounter = .True.
     158          59 :       do i = 1, iDomain - 1
     159          59 :         if (newDomainID == domainMeta%indices(i)) then
     160           3 :           domainMeta%L0DataFrom(iDomain) = i
     161           3 :           addCounter = .False.
     162             :         end if
     163             :       end do
     164          40 :       if (addCounter) nuniqueL0Domains = nuniqueL0Domains + 1_i4
     165             :     end do
     166             : 
     167             :     ! check for possible options
     168          14 :     if(.NOT. (iFlag_cordinate_sys == 0 .OR. iFlag_cordinate_sys == 1)) then
     169           0 :       call error_message('***ERROR: coordinate system for the model run should be 0 or 1')
     170             :     end if
     171             : 
     172             :     !===============================================================
     173             :     ! Read land cover
     174             :     !===============================================================
     175          14 :     call position_nml('LCover', unamelist)
     176          14 :     read(unamelist, nml = LCover)
     177             : 
     178             :     ! put land cover scenes to corresponding file name and LuT
     179             :     ! this is done already here for MPR, which does not check for the time periods
     180          42 :     allocate(LCfilename(nLCoverScene))
     181          42 :     allocate(LC_year_start(nLCoverScene))
     182          28 :     allocate(LC_year_end(nLCoverScene))
     183          56 :     LCfilename(:) = LCoverfName(1 : nLCoverScene)
     184          42 :     LC_year_start(:) = LCoverYearStart(1 : nLCoverScene)
     185          42 :     LC_year_end(:) = LCoverYearEnd(1 : nLCoverScene)
     186             : 
     187             :     !===============================================================
     188             :     ! Read namelist for mainpaths
     189             :     !===============================================================
     190          14 :     call position_nml('directories_general', unamelist)
     191          14 :     read(unamelist, nml = directories_general)
     192             : 
     193          40 :     do iDomain = 1, domainMeta%nDomains
     194          26 :       domainID = domainMeta%indices(iDomain)
     195          26 :       domainMeta%optidata(iDomain) = read_opt_domain_data(domainID)
     196          26 :       dirMorpho(iDomain)           = dir_Morpho(domainID)
     197          26 :       mhmFileRestartOut(iDomain)   = mhm_file_RestartOut(domainID)
     198          26 :       mrmFileRestartOut(iDomain)   = mrm_file_RestartOut(domainID)
     199          26 :       dirLCover(iDomain)           = dir_LCover(domainID)
     200          26 :       dirOut(iDomain)              = dir_Out(domainID)
     201          40 :       fileLatLon(iDomain)          = file_LatLon(domainID)
     202             :     end do
     203             : 
     204             :     ! ToDo: add test if opti_function matches at least one domainMeta%optidata
     205             :     ! as soon as common and common_mRM_mHM are merged, if that is the plan
     206             : 
     207             : 
     208             :     !===============================================================
     209             :     ! Read process selection list
     210             :     !===============================================================
     211             :     ! init the processCase matrix to 0 to be backward compatible
     212             :     ! if cases were added later (then there would be no values if not init here)
     213          14 :     processCase = 0_i4
     214          14 :     call position_nml('processselection', unamelist)
     215          14 :     read(unamelist, nml = processSelection)
     216             : 
     217          14 :     processMatrix = 0_i4
     218         168 :     processMatrix(:, 1) = processCase
     219          14 :     if (processMatrix(8, 1) == 0) then
     220           2 :       domainMeta%doRouting(:) = .FALSE.
     221             :     else
     222          38 :       domainMeta%doRouting(:) = .TRUE.
     223             :     end if
     224             : 
     225          14 :     call close_nml(unamelist)
     226             : 
     227          14 :   end subroutine common_read_config
     228             : 
     229             : 
     230             :   !> \brief Set land cover scenes IDs
     231             :   !> \changelog
     232             :   !! - Robert Schweppe Dec  2018
     233             :   !!   - refactoring and restructuring
     234             :   !> \authors Matthias Zink
     235             :   !> \date Dec 2012
     236          14 :   subroutine set_land_cover_scenes_id(sim_Per, LCyear_Id)
     237             : 
     238          14 :     use mo_common_constants, only : nodata_i4
     239             :     use mo_common_types, only: period
     240             :     use mo_common_variables, only : LC_year_end, LC_year_start, domainMeta, nLcoverScene
     241             :     use mo_string_utils, only : num2str
     242             : 
     243             :     implicit none
     244             : 
     245             :     type(period), dimension(:), intent(in) :: sim_Per !< simulation period
     246             :     integer(i4), dimension(:, :), allocatable, intent(inout) :: LCyear_Id !< land cover year ID
     247             : 
     248             :     integer(i4) :: ii, iDomain
     249             : 
     250             : 
     251             :     ! countercheck if land cover covers simulation period
     252          54 :     if (LC_year_start(1) .GT. minval(sim_Per(1 : domainMeta%nDomains)%yStart)) then
     253           0 :       call error_message('***ERROR: Land cover for warming period is missing!', raise=.false.)
     254           0 :       call error_message('   SimStart   : ', trim(num2str(minval(sim_Per(1 : domainMeta%nDomains)%yStart))), raise=.false.)
     255           0 :       call error_message('   LCoverStart: ', trim(num2str(LC_year_start(1))))
     256             :     end if
     257          54 :     if (LC_year_end(nLCoverScene) .LT. maxval(sim_Per(1 : domainMeta%nDomains)%yEnd)) then
     258           0 :       call error_message('***ERROR: Land cover period shorter than modelling period!', raise=.false.)
     259           0 :       call error_message('   SimEnd   : ', trim(num2str(maxval(sim_Per(1 : domainMeta%nDomains)%yEnd))), raise=.false.)
     260           0 :       call error_message('   LCoverEnd: ', trim(num2str(LC_year_end(nLCoverScene))))
     261             :     end if
     262             :     !
     263          14 :     allocate(LCyear_Id(minval(sim_Per(1 : domainMeta%nDomains)%yStart) : maxval(sim_Per(1 : domainMeta%nDomains)%yEnd), &
     264         136 :                    domainMeta%nDomains))
     265         136 :     LCyear_Id = nodata_i4
     266          40 :     do iDomain = 1, domainMeta%nDomains
     267          85 :       do ii = 1, nLCoverScene
     268             :         ! land cover before model period or land cover after model period
     269         100 :         if ((LC_year_end(ii) .LT. sim_Per(iDomain)%yStart) .OR. &
     270          71 :                 (LC_year_start(ii) .GT. sim_Per(iDomain)%yEnd)) then
     271             :           cycle
     272             :           ! land cover period fully covers model period
     273          47 :         else if ((LC_year_start(ii) .LE. sim_Per(iDomain)%yStart) .AND. &
     274             :                 (LC_year_end(ii) .GE. sim_Per(iDomain)%yEnd)) then
     275          13 :           LCyear_Id(sim_Per(iDomain)%yStart : sim_Per(iDomain)%yEnd, iDomain) = ii
     276             :           exit
     277             :           ! land cover period covers beginning of model period
     278          42 :         else if ((LC_year_start(ii) .LE. sim_Per(iDomain)%yStart) .AND. &
     279             :                 (LC_year_end(ii) .LT. sim_Per(iDomain)%yEnd)) then
     280          42 :           LCyear_Id(sim_Per(iDomain)%yStart : LC_year_end(ii), iDomain) = ii
     281             :           ! land cover period covers end of model period
     282          21 :         else if ((LC_year_start(ii) .GT. sim_Per(iDomain)%yStart) .AND. &
     283             :                 (LC_year_end(ii) .GE. sim_Per(iDomain)%yEnd)) then
     284          55 :           LCyear_Id(LC_year_start(ii) : sim_Per(iDomain)%yEnd, iDomain) = ii
     285             :           ! land cover period covers part of model_period
     286             :         else
     287           0 :           LCyear_Id(LC_year_start(ii) : LC_year_end(ii), iDomain) = ii
     288             :         end if
     289             :       end do
     290             :     end do
     291             : 
     292             : 
     293          14 :   end subroutine set_land_cover_scenes_id
     294             : 
     295             : 
     296             :   !> \brief Initialization of the domain variables
     297             :   !> \details Initialization of the domain variable for all domain loops and if activated for parallelization
     298             :   !! In case of MPI parallelization domainMeta%overAllNumberOfDomains is a
     299             :   !! variable where the number of domains from the namelist is stored. By this
     300             :   !! every process knows the total number of domains. Then, in a loop the
     301             :   !! domains are distributed onto the processes. There is a master process
     302             :   !! and several subprocesses. The master process only reads the confings in the
     303             :   !! mHM driver.
     304             :   !!
     305             :   !! The subprocesses get a number of domains. domainMeta%nDomain refers
     306             :   !! to the number of domains assigned to a specific process. It is a local
     307             :   !! variable and therefore has a different value for each process.
     308             :   !!
     309             :   !! In case more domains are there than processes, currently the domains
     310             :   !! are distributed round robin, i.e. like cards in a card game.
     311             :   !!
     312             :   !! In case less domains than processes exist, all remaining processes
     313             :   !! are assigned to the routing domains round robin. In that case the
     314             :   !! local communicator is of interest: It is a group of processes assigned
     315             :   !! to a routing domain again with a master process
     316             :   !! (domainMeta%isMasterInComLocal) and subprocesses. This communicator can
     317             :   !! in future be passed to the routing parallelization.
     318             :   !> \author Maren Kaluza
     319             :   !> \date Sep 2019
     320          14 :   subroutine init_domain_variable(nDomains, optiData, domainMeta)
     321          14 :     use mo_common_types, only: domain_meta
     322             : #ifdef MPI
     323             :     use mo_common_variables, only: comm
     324             :     use mpi_f08
     325             : #endif
     326             :     integer(i4),       intent(in)    :: nDomains !< number of domains
     327             :     integer(i4), dimension(:), intent(in) :: optiData !< optimization data
     328             :     type(domain_meta), intent(inout) :: domainMeta !< domain meta info
     329             : 
     330             :     integer             :: ierror
     331             :     integer(i4)         :: nproc
     332             :     integer(i4)         :: rank
     333             :     integer(i4)         :: iDomain
     334             :     integer(i4)         :: colDomain, colMasters
     335             : 
     336          14 :     domainMeta%overallNumberOfDomains = nDomains
     337             : #ifdef MPI
     338             :     ! find number of processes nproc
     339             :     call MPI_Comm_size(comm, nproc, ierror)
     340             :     ! find the number the process is referred to, called rank
     341             :     call MPI_Comm_rank(comm, rank, ierror)
     342             :     if (nproc < 2) then
     343             :       call error_message('at least 2 processes are required')
     344             :     end if
     345             :     ! if there are more processes than domains
     346             :     if (nproc > domainMeta%overallNumberOfDomains + 1) then
     347             :       domainMeta%nDomains = 0
     348             :       ! master reads only metadata of all domains
     349             :       if (rank == 0) then
     350             :         call init_domain_variable_for_master(domainMeta, colMasters, colDomain)
     351             :       ! all other nodes read metadata but also data of assigned domains
     352             :       else
     353             :         ! currently each domain gets one process except it is a routing domain.
     354             :         ! in that case the remaining processes are distributed round robin to
     355             :         ! the routing domains.
     356             :         call distribute_processes_to_domains_according_to_role(optiData, rank, &
     357             :                                                domainMeta, colMasters, colDomain)
     358             :       end if
     359             :       ! two communicators are created, i.e. groups of processes that talk about
     360             :       ! a certain topic:
     361             :       ! comMaster is the communicator of all processes that need to read all
     362             :       ! data. These are the processes that are masters in the comLocal plus the
     363             :       ! master over all processes. comLocal is a communicator for a group of
     364             :       ! processes assigned to the same domain.
     365             :       call MPI_Comm_split(comm, colMasters, rank, domainMeta%comMaster, ierror)
     366             :       call MPI_Comm_split(comm, colDomain, rank, domainMeta%comLocal, ierror)
     367             :       call MPI_Comm_size(domainMeta%comMaster, nproc, ierror)
     368             :     else
     369             :       ! in case of more domains than processes, distribute domains round robin
     370             :       ! onto the processes
     371             :       call MPI_Comm_dup(comm, domainMeta%comMaster, ierror)
     372             :       domainMeta%isMasterInComLocal = .true.
     373             :       domainMeta%nDomains = 0
     374             :       ! master reads only metadata of all domains
     375             :       if (rank == 0) then
     376             :         domainMeta%nDomains = domainMeta%overallNumberOfDomains
     377             :         allocate(domainMeta%indices(domainMeta%nDomains))
     378             :         do iDomain = 1, domainMeta%nDomains
     379             :           domainMeta%indices(iDomain) = iDomain
     380             :         end do
     381             :       ! all other nodes read metadata but also data of assigned domains
     382             :       else
     383             :         call distributeDomainsRoundRobin(nproc, rank, domainMeta)
     384             :       end if
     385             :     end if ! round robin
     386             : #else
     387          14 :     domainMeta%nDomains = nDomains
     388          42 :     allocate(domainMeta%indices(domainMeta%nDomains))
     389          40 :     do iDomain = 1, domainMeta%nDomains
     390          40 :       domainMeta%indices(iDomain) = iDomain
     391             :     end do
     392             : #endif
     393             : 
     394          14 :   end subroutine init_domain_variable
     395             : 
     396             : #ifdef MPI
     397             :   subroutine init_domain_variable_for_master(domainMeta, colMasters, colDomain)
     398             :     use mo_common_types, only: domain_meta
     399             :     type(domain_meta), intent(inout) :: domainMeta
     400             :     integer(i4),       intent(out)   :: colMasters
     401             :     integer(i4),       intent(out)   :: colDomain
     402             :     !local
     403             :     integer(i4) :: iDomain
     404             : 
     405             :     domainMeta%nDomains = domainMeta%overallNumberOfDomains
     406             :     allocate(domainMeta%indices(domainMeta%nDomains))
     407             :     do iDomain = 1, domainMeta%nDomains
     408             :       domainMeta%indices(iDomain) = iDomain
     409             :     end do
     410             :     colMasters = 1
     411             :     colDomain = 0
     412             :     domainMeta%isMasterInComLocal = .true.
     413             : 
     414             :   end subroutine init_domain_variable_for_master
     415             : 
     416             :   subroutine distributeDomainsRoundRobin(nproc, rank, domainMeta)
     417             :     use mo_common_types, only: domain_meta
     418             :     integer(i4),       intent(in)    :: nproc
     419             :     integer(i4),       intent(in)    :: rank
     420             :     type(domain_meta), intent(inout) :: domainMeta
     421             : 
     422             :     integer(i4) :: iDomain, iProcDomain
     423             : 
     424             :     do iDomain = 1 , domainMeta%overallNumberOfDomains
     425             :       if (rank == (modulo(iDomain + nproc - 2, (nproc - 1)) + 1)) then
     426             :         domainMeta%nDomains = domainMeta%nDomains + 1
     427             :       end if
     428             :     end do
     429             :     allocate(domainMeta%indices(domainMeta%nDomains))
     430             :     iProcDomain = 0
     431             :     do iDomain = 1 , domainMeta%overallNumberOfDomains
     432             :       if (rank == (modulo(iDomain + nproc - 2, (nproc - 1)) + 1)) then
     433             :         iProcDomain = iProcDomain + 1
     434             :         domainMeta%indices(iProcDomain) = iDomain
     435             :       end if
     436             :     end do
     437             :   end subroutine distributeDomainsRoundRobin
     438             : 
     439             :   subroutine distribute_processes_to_domains_according_to_role(optiData, rank, &
     440             :                                                domainMeta, colMasters, colDomain)
     441             :     use mo_common_types, only: domain_meta
     442             :     integer(i4), dimension(:), intent(in)    :: optiData
     443             :     integer(i4),               intent(in)    :: rank
     444             :     type(domain_meta),         intent(inout) :: domainMeta
     445             :     integer(i4),               intent(out)   :: colMasters
     446             :     integer(i4),               intent(out)   :: colDomain
     447             : 
     448             :     ! local
     449             :     integer(i4) :: nDomainsAll, nTreeDomains, i, iDomain
     450             :     integer(i4), dimension(:), allocatable :: treeDomainList
     451             : 
     452             :     nDomainsAll = domainMeta%overallNumberOfDomains
     453             :     nTreeDomains = 0
     454             :     do iDomain = 1, nDomainsAll
     455             :       !ToDo: should also routing but not opti domains be counted?
     456             :       if (optiData(iDomain) == 1) then
     457             :         nTreeDomains = nTreeDomains + 1
     458             :       end if
     459             :     end do
     460             :     allocate(treeDomainList(nTreeDomains))
     461             :     i = 0
     462             :     do iDomain = 1, nDomainsAll
     463             :       if (optiData(iDomain) == 1) then
     464             :         i = i + 1
     465             :         treeDomainList(i) = iDomain
     466             :       end if
     467             :     end do
     468             :     if (rank < nDomainsAll + 1) then
     469             :       colMasters = 1
     470             :       colDomain = rank
     471             :       domainMeta%isMasterInComLocal = .true.
     472             :       domainMeta%nDomains = 1
     473             :       allocate(domainMeta%indices(domainMeta%nDomains))
     474             :       domainMeta%indices(1) = rank
     475             :     else
     476             :       colMasters = 0
     477             :       if (nTreeDomains > 0) then
     478             :         colDomain = treeDomainList(mod(rank, nTreeDomains) + 1)
     479             :       else
     480             :         colDomain = 1
     481             :       end if
     482             :       domainMeta%isMasterInComLocal = .false.
     483             :       domainMeta%nDomains = 1
     484             :       allocate(domainMeta%indices(domainMeta%nDomains))
     485             :       ! ToDo : temporary solution, this should either not read data at all
     486             :       ! or data corresponding to the master process
     487             :       domainMeta%indices(1) = 1
     488             :     end if
     489             :     deallocate(treeDomainList)
     490             :   end subroutine
     491             : #endif
     492             : 
     493             :   ! \brief check the L0Domain variable from the namelist
     494             :   !> \authors Sebastian Müller
     495             :   !> \date Mar 2023
     496          14 :   subroutine check_L0Domain(L0Domain, nDomains)
     497          14 :     use mo_common_constants, only : maxNoDomains
     498             :     use mo_string_utils, only : num2str
     499             : 
     500             :     integer(i4), dimension(maxNoDomains), intent(in) ::L0Domain !< given L0Domain variable
     501             :     integer(i4), intent(in) :: nDomains !< number of domains
     502             : 
     503             :     integer(i4) :: i
     504             : 
     505          40 :     do i = 1, nDomains
     506          26 :       if (L0Domain(i) < 0) call error_message( &
     507             :         "L0Domain values need to be positive: ", &
     508           0 :         "L0Domain(", trim(adjustl(num2str(i))), ") = ", trim(adjustl(num2str(L0Domain(i)))))
     509          26 :       if (L0Domain(i) > i) call error_message( &
     510             :         "L0Domain values need to be less or equal to the domain index: ", &
     511           0 :         "L0Domain(", trim(adjustl(num2str(i))), ") = ", trim(adjustl(num2str(L0Domain(i)))))
     512             :       ! check for increasing values
     513          26 :       if (i > 1) then
     514          12 :         if (L0Domain(i) < L0Domain(i-1)) call error_message( &
     515             :           "L0Domain values need to be increasing: ", &
     516           0 :           "L0Domain(", trim(adjustl(num2str(i-1))), ") = ", trim(adjustl(num2str(L0Domain(i-1)))), &
     517           0 :           ", L0Domain(", trim(adjustl(num2str(i))), ") = ", trim(adjustl(num2str(L0Domain(i)))))
     518             :       end if
     519             :       ! if lower, check that the reference domain uses its own L0Data
     520          40 :       if (L0Domain(i) < i) then
     521           3 :         if (L0Domain(L0Domain(i)) /= L0Domain(i)) call error_message( &
     522             :           "L0Domain values should be taken from a domain with its own L0 data: ", &
     523           0 :           "L0Domain(", trim(adjustl(num2str(i))), ") = ", trim(adjustl(num2str(L0Domain(i)))), &
     524           0 :           ", L0Domain(", trim(adjustl(num2str(L0Domain(i)))), ") = ", trim(adjustl(num2str(L0Domain(L0Domain(i))))))
     525             :       end if
     526             :     end do
     527             : 
     528          14 :   end subroutine check_L0Domain
     529             : 
     530             : END MODULE mo_common_read_config

Generated by: LCOV version 1.16