LCOV - code coverage report
Current view: top level - src - nnp_environment.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 356 406 87.7 %
Date: 2024-12-21 06:28:57 Functions: 3 3 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief  Methods dealing with Neural Network potentials
      10             : !> \author Christoph Schran (christoph.schran@rub.de)
      11             : !> \date   2020-10-10
      12             : ! **************************************************************************************************
      13             : MODULE nnp_environment
      14             : 
      15             :    USE atomic_kind_types,               ONLY: atomic_kind_type
      16             :    USE bibliography,                    ONLY: Behler2007,&
      17             :                                               Behler2011,&
      18             :                                               Schran2020a,&
      19             :                                               Schran2020b,&
      20             :                                               cite_reference
      21             :    USE cell_methods,                    ONLY: read_cell,&
      22             :                                               write_cell
      23             :    USE cell_types,                      ONLY: cell_release,&
      24             :                                               cell_type,&
      25             :                                               get_cell
      26             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      27             :                                               cp_logger_get_default_unit_nr,&
      28             :                                               cp_logger_type
      29             :    USE cp_parser_methods,               ONLY: parser_read_line,&
      30             :                                               parser_search_string
      31             :    USE cp_parser_types,                 ONLY: cp_parser_type,&
      32             :                                               parser_create,&
      33             :                                               parser_release,&
      34             :                                               parser_reset
      35             :    USE cp_subsys_methods,               ONLY: cp_subsys_create
      36             :    USE cp_subsys_types,                 ONLY: cp_subsys_set,&
      37             :                                               cp_subsys_type
      38             :    USE distribution_1d_types,           ONLY: distribution_1d_release,&
      39             :                                               distribution_1d_type
      40             :    USE distribution_methods,            ONLY: distribute_molecules_1d
      41             :    USE input_section_types,             ONLY: section_vals_get,&
      42             :                                               section_vals_get_subs_vals,&
      43             :                                               section_vals_type,&
      44             :                                               section_vals_val_get
      45             :    USE kinds,                           ONLY: default_path_length,&
      46             :                                               dp
      47             :    USE message_passing,                 ONLY: mp_para_env_type
      48             :    USE molecule_kind_types,             ONLY: molecule_kind_type,&
      49             :                                               write_molecule_kind_set
      50             :    USE molecule_types,                  ONLY: molecule_type
      51             :    USE nnp_acsf,                        ONLY: nnp_init_acsf_groups,&
      52             :                                               nnp_sort_acsf,&
      53             :                                               nnp_sort_ele,&
      54             :                                               nnp_write_acsf
      55             :    USE nnp_environment_types,           ONLY: &
      56             :         nnp_actfnct_cos, nnp_actfnct_exp, nnp_actfnct_gaus, nnp_actfnct_invsig, nnp_actfnct_lin, &
      57             :         nnp_actfnct_quad, nnp_actfnct_sig, nnp_actfnct_softplus, nnp_actfnct_tanh, nnp_env_set, &
      58             :         nnp_type
      59             :    USE nnp_model,                       ONLY: nnp_write_arc
      60             :    USE particle_methods,                ONLY: write_fist_particle_coordinates,&
      61             :                                               write_particle_distances,&
      62             :                                               write_structure_data
      63             :    USE particle_types,                  ONLY: particle_type
      64             :    USE periodic_table,                  ONLY: get_ptable_info
      65             : #include "./base/base_uses.f90"
      66             : 
      67             :    IMPLICIT NONE
      68             : 
      69             :    PRIVATE
      70             : 
      71             :    LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .TRUE.
      72             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'nnp_environment'
      73             : 
      74             :    PUBLIC :: nnp_init
      75             :    PUBLIC :: nnp_init_model
      76             : 
      77             : CONTAINS
      78             : 
      79             : ! **************************************************************************************************
      80             : !> \brief Read and initialize all the information for neural network potentials
      81             : !> \param nnp_env ...
      82             : !> \param root_section ...
      83             : !> \param para_env ...
      84             : !> \param force_env_section ...
      85             : !> \param subsys_section ...
      86             : !> \param use_motion_section ...
      87             : !> \date   2020-10-10
      88             : !> \author Christoph Schran (christoph.schran@rub.de)
      89             : ! **************************************************************************************************
      90          28 :    SUBROUTINE nnp_init(nnp_env, root_section, para_env, force_env_section, subsys_section, &
      91             :                        use_motion_section)
      92             :       TYPE(nnp_type), INTENT(INOUT), POINTER             :: nnp_env
      93             :       TYPE(section_vals_type), INTENT(IN), POINTER       :: root_section
      94             :       TYPE(mp_para_env_type), INTENT(IN), POINTER        :: para_env
      95             :       TYPE(section_vals_type), INTENT(INOUT), POINTER    :: force_env_section, subsys_section
      96             :       LOGICAL, INTENT(IN)                                :: use_motion_section
      97             : 
      98             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'nnp_init'
      99             : 
     100             :       INTEGER                                            :: handle
     101             :       LOGICAL                                            :: explicit, use_ref_cell
     102             :       REAL(KIND=dp), DIMENSION(3)                        :: abc
     103             :       TYPE(cell_type), POINTER                           :: cell, cell_ref
     104             :       TYPE(cp_subsys_type), POINTER                      :: subsys
     105             :       TYPE(section_vals_type), POINTER                   :: cell_section, nnp_section
     106             : 
     107          14 :       CALL timeset(routineN, handle)
     108          14 :       CALL cite_reference(Behler2007)
     109          14 :       CALL cite_reference(Behler2011)
     110          14 :       CALL cite_reference(Schran2020a)
     111          14 :       CALL cite_reference(Schran2020b)
     112             : 
     113          14 :       CPASSERT(ASSOCIATED(nnp_env))
     114             : 
     115          14 :       NULLIFY (cell_section, nnp_section, cell, cell_ref, subsys)
     116             : 
     117          14 :       IF (.NOT. ASSOCIATED(subsys_section)) THEN
     118           0 :          subsys_section => section_vals_get_subs_vals(force_env_section, "SUBSYS")
     119             :       END IF
     120          14 :       cell_section => section_vals_get_subs_vals(subsys_section, "CELL")
     121          14 :       nnp_section => section_vals_get_subs_vals(force_env_section, "NNP")
     122          14 :       CALL section_vals_get(nnp_section, explicit=explicit)
     123          14 :       IF (.NOT. explicit) THEN
     124           0 :          CPWARN("NNP section not explicitly stated. Using default file names.")
     125             :       END IF
     126             : 
     127             :       CALL nnp_env_set(nnp_env=nnp_env, nnp_input=nnp_section, &
     128          14 :                        force_env_input=force_env_section)
     129             : 
     130             :       CALL read_cell(cell=cell, cell_ref=cell_ref, use_ref_cell=use_ref_cell, cell_section=cell_section, &
     131          14 :                      para_env=para_env)
     132          14 :       CALL get_cell(cell=cell, abc=abc)
     133          14 :       CALL write_cell(cell=cell, subsys_section=subsys_section)
     134             : 
     135             :       CALL cp_subsys_create(subsys, para_env, root_section, &
     136             :                             force_env_section=force_env_section, subsys_section=subsys_section, &
     137          14 :                             use_motion_section=use_motion_section)
     138             : 
     139             :       CALL nnp_init_subsys(nnp_env=nnp_env, subsys=subsys, cell=cell, &
     140             :                            cell_ref=cell_ref, use_ref_cell=use_ref_cell, &
     141          14 :                            subsys_section=subsys_section)
     142             : 
     143          14 :       CALL cell_release(cell)
     144          14 :       CALL cell_release(cell_ref)
     145             : 
     146          14 :       CALL timestop(handle)
     147             : 
     148          14 :    END SUBROUTINE nnp_init
     149             : 
     150             : ! **************************************************************************************************
     151             : !> \brief Read and initialize all the information for neural network potentials
     152             : !> \param nnp_env ...
     153             : !> \param subsys ...
     154             : !> \param cell ...
     155             : !> \param cell_ref ...
     156             : !> \param use_ref_cell ...
     157             : !> \param subsys_section ...
     158             : !> \date   2020-10-10
     159             : !> \author Christoph Schran (christoph.schran@rub.de)
     160             : ! **************************************************************************************************
     161          14 :    SUBROUTINE nnp_init_subsys(nnp_env, subsys, cell, cell_ref, use_ref_cell, subsys_section)
     162             :       TYPE(nnp_type), INTENT(INOUT), POINTER             :: nnp_env
     163             :       TYPE(cp_subsys_type), INTENT(IN), POINTER          :: subsys
     164             :       TYPE(cell_type), INTENT(INOUT), POINTER            :: cell, cell_ref
     165             :       LOGICAL, INTENT(IN)                                :: use_ref_cell
     166             :       TYPE(section_vals_type), INTENT(IN), POINTER       :: subsys_section
     167             : 
     168             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'nnp_init_subsys'
     169             : 
     170             :       INTEGER                                            :: handle, natom
     171          14 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     172             :       TYPE(distribution_1d_type), POINTER                :: local_molecules, local_particles
     173          14 :       TYPE(molecule_kind_type), DIMENSION(:), POINTER    :: molecule_kind_set
     174          14 :       TYPE(molecule_type), DIMENSION(:), POINTER         :: molecule_set
     175          14 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     176             : 
     177          14 :       CALL timeset(routineN, handle)
     178             : 
     179             :       NULLIFY (atomic_kind_set, molecule_kind_set, particle_set, molecule_set, &
     180          14 :                local_molecules, local_particles)
     181             : 
     182          14 :       particle_set => subsys%particles%els
     183          14 :       atomic_kind_set => subsys%atomic_kinds%els
     184          14 :       molecule_kind_set => subsys%molecule_kinds%els
     185          14 :       molecule_set => subsys%molecules%els
     186             : 
     187             :       !Print the molecule kind set
     188          14 :       CALL write_molecule_kind_set(molecule_kind_set, subsys_section)
     189             : 
     190             :       !Print the atomic coordinates
     191          14 :       CALL write_fist_particle_coordinates(particle_set, subsys_section)
     192             :       CALL write_particle_distances(particle_set, cell=cell, &
     193          14 :                                     subsys_section=subsys_section)
     194             :       CALL write_structure_data(particle_set, cell=cell, &
     195          14 :                                 input_section=subsys_section)
     196             : 
     197             :       !Distribute molecules and atoms using the new data structures
     198             :       CALL distribute_molecules_1d(atomic_kind_set=atomic_kind_set, &
     199             :                                    particle_set=particle_set, &
     200             :                                    local_particles=local_particles, &
     201             :                                    molecule_kind_set=molecule_kind_set, &
     202             :                                    molecule_set=molecule_set, &
     203             :                                    local_molecules=local_molecules, &
     204          14 :                                    force_env_section=nnp_env%force_env_input)
     205             : 
     206          14 :       natom = SIZE(particle_set)
     207             : 
     208          42 :       ALLOCATE (nnp_env%nnp_forces(3, natom))
     209             : 
     210        9254 :       nnp_env%nnp_forces(:, :) = 0.0_dp
     211             : 
     212          14 :       nnp_env%nnp_potential_energy = 0.0_dp
     213             : 
     214             :       ! Set up arrays for calculation:
     215          14 :       nnp_env%num_atoms = natom
     216          42 :       ALLOCATE (nnp_env%ele_ind(natom))
     217          42 :       ALLOCATE (nnp_env%nuc_atoms(natom))
     218          42 :       ALLOCATE (nnp_env%coord(3, natom))
     219          42 :       ALLOCATE (nnp_env%atoms(natom))
     220          42 :       ALLOCATE (nnp_env%sort(natom))
     221          42 :       ALLOCATE (nnp_env%sort_inv(natom))
     222             : 
     223          14 :       CALL cp_subsys_set(subsys, cell=cell)
     224             : 
     225             :       CALL nnp_env_set(nnp_env=nnp_env, subsys=subsys, &
     226             :                        cell_ref=cell_ref, use_ref_cell=use_ref_cell, &
     227             :                        local_molecules=local_molecules, &
     228          14 :                        local_particles=local_particles)
     229             : 
     230          14 :       CALL distribution_1d_release(local_particles)
     231          14 :       CALL distribution_1d_release(local_molecules)
     232             : 
     233          14 :       CALL nnp_init_model(nnp_env=nnp_env, printtag="NNP")
     234             : 
     235          14 :       CALL timestop(handle)
     236             : 
     237          14 :    END SUBROUTINE nnp_init_subsys
     238             : 
     239             : ! **************************************************************************************************
     240             : !> \brief Initialize the Neural Network Potential
     241             : !> \param nnp_env ...
     242             : !> \param printtag ...
     243             : !> \date   2020-10-10
     244             : !> \author Christoph Schran (christoph.schran@rub.de)
     245             : ! **************************************************************************************************
     246          15 :    SUBROUTINE nnp_init_model(nnp_env, printtag)
     247             :       TYPE(nnp_type), INTENT(INOUT), POINTER             :: nnp_env
     248             :       CHARACTER(LEN=*), INTENT(IN)                       :: printtag
     249             : 
     250             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'nnp_init_model'
     251             :       INTEGER, PARAMETER                                 :: def_str_len = 256, &
     252             :                                                             default_path_length = 256
     253             : 
     254          15 :       CHARACTER(len=1), ALLOCATABLE, DIMENSION(:)        :: cactfnct
     255             :       CHARACTER(len=2)                                   :: ele
     256             :       CHARACTER(len=def_str_len)                         :: dummy, line
     257             :       CHARACTER(len=default_path_length)                 :: base_name, file_name
     258             :       INTEGER                                            :: handle, i, i_com, io, iweight, j, k, l, &
     259             :                                                             n_weight, nele, nuc_ele, symfnct_type, &
     260             :                                                             unit_nr
     261             :       LOGICAL                                            :: at_end, atom_e_found, explicit, first, &
     262             :                                                             found
     263             :       REAL(KIND=dp)                                      :: energy
     264          15 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: weights
     265             :       REAL(KIND=dp), DIMENSION(7)                        :: test_array
     266          15 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: work
     267             :       TYPE(cp_logger_type), POINTER                      :: logger
     268             :       TYPE(cp_parser_type)                               :: parser
     269             :       TYPE(section_vals_type), POINTER                   :: bias_section, model_section
     270             : 
     271          15 :       CALL timeset(routineN, handle)
     272             : 
     273          15 :       NULLIFY (logger)
     274             : 
     275          15 :       logger => cp_get_default_logger()
     276             : 
     277          15 :       IF (logger%para_env%is_source()) THEN
     278           8 :          unit_nr = cp_logger_get_default_unit_nr(logger)
     279           8 :          WRITE (unit_nr, *) ""
     280           8 :          WRITE (unit_nr, *) TRIM(printtag)//"| Neural Network Potential Force Environment"
     281             :       END IF
     282             : 
     283          15 :       model_section => section_vals_get_subs_vals(nnp_env%nnp_input, "MODEL")
     284          15 :       CALL section_vals_get(model_section, n_repetition=nnp_env%n_committee)
     285          60 :       ALLOCATE (nnp_env%atomic_energy(nnp_env%num_atoms, nnp_env%n_committee))
     286          45 :       ALLOCATE (nnp_env%committee_energy(nnp_env%n_committee))
     287          60 :       ALLOCATE (nnp_env%myforce(3, nnp_env%num_atoms, nnp_env%n_committee))
     288          60 :       ALLOCATE (nnp_env%committee_forces(3, nnp_env%num_atoms, nnp_env%n_committee))
     289          45 :       ALLOCATE (nnp_env%committee_stress(3, 3, nnp_env%n_committee))
     290             : 
     291          15 :       CALL section_vals_val_get(nnp_env%nnp_input, "NNP_INPUT_FILE_NAME", c_val=file_name)
     292          15 :       CALL parser_create(parser, file_name, para_env=logger%para_env)
     293             : 
     294             :       ! read number of elements and cut_type and check for scale and center
     295          15 :       nnp_env%scale_acsf = .FALSE.
     296          15 :       nnp_env%scale_sigma_acsf = .FALSE.
     297             :       ! Defaults for scale min and max:
     298          15 :       nnp_env%scmin = 0.0_dp
     299          15 :       nnp_env%scmax = 1.0_dp
     300          15 :       nnp_env%center_acsf = .FALSE.
     301          15 :       nnp_env%normnodes = .FALSE.
     302          15 :       nnp_env%n_hlayer = 0
     303             : 
     304          15 :       IF (logger%para_env%is_source()) THEN
     305           8 :          unit_nr = cp_logger_get_default_unit_nr(logger)
     306           8 :          WRITE (unit_nr, *) TRIM(printtag)//"| Reading NNP input from file: ", TRIM(file_name)
     307             :       END IF
     308             : 
     309             :       CALL parser_search_string(parser, "number_of_elements", .TRUE., found, line, &
     310          15 :                                 search_from_begin_of_file=.TRUE.)
     311          15 :       IF (found) THEN
     312          15 :          READ (line, *) dummy, nnp_env%n_ele
     313             :       ELSE
     314             :          CALL cp_abort(__LOCATION__, TRIM(printtag)// &
     315           0 :                        "| number of elements missing in NNP_INPUT_FILE")
     316             :       END IF
     317             : 
     318             :       CALL parser_search_string(parser, "scale_symmetry_functions_sigma", .TRUE., found, &
     319          15 :                                 search_from_begin_of_file=.TRUE.)
     320          15 :       nnp_env%scale_sigma_acsf = found
     321             : 
     322             :       CALL parser_search_string(parser, "scale_symmetry_functions", .TRUE., found, &
     323          15 :                                 search_from_begin_of_file=.TRUE.)
     324          15 :       nnp_env%scale_acsf = found
     325             : 
     326             :       ! Test if there are two keywords of this:
     327          15 :       CALL parser_search_string(parser, "scale_symmetry_functions", .TRUE., found)
     328          15 :       IF (found .AND. nnp_env%scale_sigma_acsf) THEN
     329           0 :          CPWARN('Two scaling keywords in the input, we will ignore sigma scaling in this case')
     330           0 :          nnp_env%scale_sigma_acsf = .FALSE.
     331          15 :       ELSE IF (.NOT. found .AND. nnp_env%scale_sigma_acsf) THEN
     332           0 :          nnp_env%scale_acsf = .FALSE.
     333             :       END IF
     334             : 
     335             :       CALL parser_search_string(parser, "scale_min_short_atomic", .TRUE., found, line, &
     336          15 :                                 search_from_begin_of_file=.TRUE.)
     337          15 :       IF (found) READ (line, *) dummy, nnp_env%scmin
     338             : 
     339             :       CALL parser_search_string(parser, "scale_max_short_atomic", .TRUE., found, line, &
     340          15 :                                 search_from_begin_of_file=.TRUE.)
     341          15 :       IF (found) READ (line, *) dummy, nnp_env%scmax
     342             : 
     343             :       CALL parser_search_string(parser, "center_symmetry_functions", .TRUE., found, &
     344          15 :                                 search_from_begin_of_file=.TRUE.)
     345          15 :       nnp_env%center_acsf = found
     346             :       ! n2p2 overwrites sigma scaling, if centering is requested:
     347          15 :       IF (nnp_env%scale_sigma_acsf .AND. nnp_env%center_acsf) THEN
     348           0 :          nnp_env%scale_sigma_acsf = .FALSE.
     349             :       END IF
     350             :       ! Print warning if centering and scaling is requested:
     351          15 :       IF (nnp_env%center_acsf .AND. nnp_env%scale_acsf) THEN
     352          15 :          IF ((ABS(nnp_env%scmin) > EPSILON(0.0_dp)*1.0E+4_dp) .OR. (ABS(nnp_env%scmax - 1.0_dp) > EPSILON(0.0_dp)*1.0E+4_dp)) THEN
     353             :             CALL cp_warn(__LOCATION__, &
     354             :                          "Centering and scaling of symmetry functions requested while scale_min_short_atomic != 0 and/or "// &
     355             :                          "scale_max_short_atomic != 1. Make sure that scaling and centering of symmetry functions in CP2K "// &
     356             :                          "is consistent with your training code. "// &
     357           0 :                          "In CP2K: G* = (G - ave(G)) / (max(G) - min(G)) * (Smax - Smin) + Smin")
     358             :          END IF
     359             :       END IF
     360             : 
     361             :       CALL parser_search_string(parser, "normalize_nodes", .TRUE., found, &
     362          15 :                                 search_from_begin_of_file=.TRUE.)
     363          15 :       nnp_env%normnodes = found
     364             : 
     365             :       CALL parser_search_string(parser, "cutoff_type", .TRUE., found, line, &
     366          15 :                                 search_from_begin_of_file=.TRUE.)
     367          15 :       IF (found) THEN
     368          15 :          READ (line, *) dummy, nnp_env%cut_type
     369             :       ELSE
     370             :          CALL cp_abort(__LOCATION__, TRIM(printtag)// &
     371           0 :                        "| no cutoff type specified in NNP_INPUT_FILE")
     372             :       END IF
     373             : 
     374             :       CALL parser_search_string(parser, "global_hidden_layers_short", .TRUE., found, line, &
     375          15 :                                 search_from_begin_of_file=.TRUE.)
     376          15 :       IF (found) THEN
     377          15 :          READ (line, *) dummy, nnp_env%n_hlayer
     378             :       ELSE
     379             :          CALL cp_abort(__LOCATION__, TRIM(printtag)// &
     380           0 :                        "| number of hidden layers missing in NNP_INPUT_FILE")
     381             :       END IF
     382          15 :       nnp_env%n_layer = nnp_env%n_hlayer + 2
     383             : 
     384          15 :       nele = nnp_env%n_ele
     385          76 :       ALLOCATE (nnp_env%rad(nele))
     386          76 :       ALLOCATE (nnp_env%ang(nele))
     387          45 :       ALLOCATE (nnp_env%n_rad(nele))
     388          30 :       ALLOCATE (nnp_env%n_ang(nele))
     389          45 :       ALLOCATE (nnp_env%actfnct(nnp_env%n_hlayer + 1))
     390          45 :       ALLOCATE (cactfnct(nnp_env%n_hlayer + 1))
     391          30 :       ALLOCATE (nnp_env%ele(nele))
     392          30 :       ALLOCATE (nnp_env%nuc_ele(nele))
     393          76 :       ALLOCATE (nnp_env%arc(nele))
     394          46 :       DO i = 1, nele
     395         217 :          ALLOCATE (nnp_env%arc(i)%layer(nnp_env%n_layer))
     396         108 :          ALLOCATE (nnp_env%arc(i)%n_nodes(nnp_env%n_layer))
     397             :       END DO
     398          45 :       ALLOCATE (nnp_env%n_hnodes(nnp_env%n_hlayer))
     399          45 :       ALLOCATE (nnp_env%atom_energies(nele))
     400          46 :       nnp_env%atom_energies = 0.0_dp
     401             : 
     402             :       ! read elements, broadcast and sort
     403          15 :       CALL parser_reset(parser)
     404             :       DO
     405          30 :          CALL parser_search_string(parser, "elements", .TRUE., found, line)
     406          30 :          IF (found) THEN
     407          30 :             READ (line, *) dummy
     408          30 :             IF (TRIM(ADJUSTL(dummy)) == "elements") THEN
     409          15 :                READ (line, *) dummy, nnp_env%ele(:)
     410          15 :                CALL nnp_sort_ele(nnp_env%ele, nnp_env%nuc_ele)
     411          15 :                EXIT
     412             :             END IF
     413             :          ELSE
     414             :             CALL cp_abort(__LOCATION__, TRIM(printtag)// &
     415           0 :                           "| elements not specified in NNP_INPUT_FILE")
     416             :          END IF
     417             :       END DO
     418             : 
     419             :       CALL parser_search_string(parser, "remove_atom_energies", .TRUE., atom_e_found, &
     420          15 :                                 search_from_begin_of_file=.TRUE.)
     421             : 
     422          15 :       IF (atom_e_found) THEN
     423           0 :          CALL parser_reset(parser)
     424           0 :          i = 0
     425             :          DO
     426           0 :             CALL parser_search_string(parser, "atom_energy", .TRUE., found, line)
     427           0 :             IF (found) THEN
     428           0 :                READ (line, *) dummy, ele, energy
     429           0 :                DO j = 1, nele
     430           0 :                   IF (nnp_env%ele(j) == TRIM(ele)) THEN
     431           0 :                      i = i + 1
     432           0 :                      nnp_env%atom_energies(j) = energy
     433             :                   END IF
     434             :                END DO
     435           0 :                IF (i == nele) EXIT
     436             :             ELSE
     437             :                CALL cp_abort(__LOCATION__, TRIM(printtag)// &
     438           0 :                              "| atom energies are not specified")
     439             :             END IF
     440             :          END DO
     441             :       END IF
     442             : 
     443             :       CALL parser_search_string(parser, "global_nodes_short", .TRUE., found, line, &
     444          15 :                                 search_from_begin_of_file=.TRUE.)
     445          15 :       IF (found) THEN
     446          15 :          READ (line, *) dummy, nnp_env%n_hnodes(:)
     447             :       ELSE
     448             :          CALL cp_abort(__LOCATION__, TRIM(printtag)// &
     449           0 :                        "NNP| global_nodes_short not specified in NNP_INPUT_FILE")
     450             :       END IF
     451             : 
     452             :       CALL parser_search_string(parser, "global_activation_short", .TRUE., found, line, &
     453          15 :                                 search_from_begin_of_file=.TRUE.)
     454          15 :       IF (found) THEN
     455          15 :          READ (line, *) dummy, cactfnct(:)
     456             :       ELSE
     457             :          CALL cp_abort(__LOCATION__, TRIM(printtag)// &
     458           0 :                        "| global_activation_short not specified in NNP_INPUT_FILE")
     459             :       END IF
     460             : 
     461          60 :       DO i = 1, nnp_env%n_hlayer + 1
     462          15 :          SELECT CASE (cactfnct(i))
     463             :          CASE ("t")
     464          30 :             nnp_env%actfnct(i) = nnp_actfnct_tanh
     465             :          CASE ("g")
     466           0 :             nnp_env%actfnct(i) = nnp_actfnct_gaus
     467             :          CASE ("l")
     468          15 :             nnp_env%actfnct(i) = nnp_actfnct_lin
     469             :          CASE ("c")
     470           0 :             nnp_env%actfnct(i) = nnp_actfnct_cos
     471             :          CASE ("s")
     472           0 :             nnp_env%actfnct(i) = nnp_actfnct_sig
     473             :          CASE ("S")
     474           0 :             nnp_env%actfnct(i) = nnp_actfnct_invsig
     475             :          CASE ("e")
     476           0 :             nnp_env%actfnct(i) = nnp_actfnct_exp
     477             :          CASE ("p")
     478           0 :             nnp_env%actfnct(i) = nnp_actfnct_softplus
     479             :          CASE ("h")
     480           0 :             nnp_env%actfnct(i) = nnp_actfnct_quad
     481             :          CASE DEFAULT
     482             :             CALL cp_abort(__LOCATION__, TRIM(printtag)// &
     483          45 :                           "| Activation function unkown")
     484             :          END SELECT
     485             :       END DO
     486             : 
     487             :       ! determine n_rad and n_ang
     488          46 :       DO i = 1, nele
     489          31 :          nnp_env%n_rad(i) = 0
     490          46 :          nnp_env%n_ang(i) = 0
     491             :       END DO
     492             : 
     493             :       ! count symfunctions
     494          15 :       CALL parser_reset(parser)
     495          15 :       first = .TRUE.
     496             :       DO
     497         871 :          CALL parser_search_string(parser, "symfunction_short", .TRUE., found, line)
     498         871 :          IF (found) THEN
     499         856 :             READ (line, *) dummy, ele, symfnct_type
     500        2626 :             DO i = 1, nele
     501        2626 :                IF (TRIM(ele) .EQ. nnp_env%ele(i)) THEN
     502         856 :                   IF (symfnct_type .EQ. 2) THEN
     503         486 :                      nnp_env%n_rad(i) = nnp_env%n_rad(i) + 1
     504         370 :                   ELSE IF (symfnct_type .EQ. 3) THEN
     505         370 :                      nnp_env%n_ang(i) = nnp_env%n_ang(i) + 1
     506             :                   ELSE
     507             :                      CALL cp_abort(__LOCATION__, TRIM(printtag)// &
     508           0 :                                    "| Symmetry function type not supported")
     509             :                   END IF
     510             :                END IF
     511             :             END DO
     512             :             first = .FALSE.
     513             :          ELSE
     514          15 :             IF (first) CALL cp_abort(__LOCATION__, TRIM(printtag)// &
     515           0 :                                      "| no symfunction_short specified in NNP_INPUT_FILE")
     516             :             ! no additional symfnct found
     517             :             EXIT
     518             :          END IF
     519             :       END DO
     520             : 
     521          46 :       DO i = 1, nele
     522          93 :          ALLOCATE (nnp_env%rad(i)%y(nnp_env%n_rad(i)))
     523          93 :          ALLOCATE (nnp_env%rad(i)%funccut(nnp_env%n_rad(i)))
     524          93 :          ALLOCATE (nnp_env%rad(i)%eta(nnp_env%n_rad(i)))
     525          93 :          ALLOCATE (nnp_env%rad(i)%rs(nnp_env%n_rad(i)))
     526          93 :          ALLOCATE (nnp_env%rad(i)%loc_min(nnp_env%n_rad(i)))
     527          93 :          ALLOCATE (nnp_env%rad(i)%loc_max(nnp_env%n_rad(i)))
     528          93 :          ALLOCATE (nnp_env%rad(i)%loc_av(nnp_env%n_rad(i)))
     529          93 :          ALLOCATE (nnp_env%rad(i)%sigma(nnp_env%n_rad(i)))
     530          62 :          ALLOCATE (nnp_env%rad(i)%ele(nnp_env%n_rad(i)))
     531          93 :          ALLOCATE (nnp_env%rad(i)%nuc_ele(nnp_env%n_rad(i)))
     532         517 :          nnp_env%rad(i)%funccut = 0.0_dp
     533         517 :          nnp_env%rad(i)%eta = 0.0_dp
     534         517 :          nnp_env%rad(i)%rs = 0.0_dp
     535         517 :          nnp_env%rad(i)%ele = 'X'
     536         517 :          nnp_env%rad(i)%nuc_ele = 0
     537             : 
     538          93 :          ALLOCATE (nnp_env%ang(i)%y(nnp_env%n_ang(i)))
     539          93 :          ALLOCATE (nnp_env%ang(i)%funccut(nnp_env%n_ang(i)))
     540          93 :          ALLOCATE (nnp_env%ang(i)%eta(nnp_env%n_ang(i)))
     541          93 :          ALLOCATE (nnp_env%ang(i)%zeta(nnp_env%n_ang(i)))
     542          93 :          ALLOCATE (nnp_env%ang(i)%prefzeta(nnp_env%n_ang(i)))
     543          93 :          ALLOCATE (nnp_env%ang(i)%lam(nnp_env%n_ang(i)))
     544          93 :          ALLOCATE (nnp_env%ang(i)%loc_min(nnp_env%n_ang(i)))
     545          93 :          ALLOCATE (nnp_env%ang(i)%loc_max(nnp_env%n_ang(i)))
     546          93 :          ALLOCATE (nnp_env%ang(i)%loc_av(nnp_env%n_ang(i)))
     547          93 :          ALLOCATE (nnp_env%ang(i)%sigma(nnp_env%n_ang(i)))
     548          62 :          ALLOCATE (nnp_env%ang(i)%ele1(nnp_env%n_ang(i)))
     549          62 :          ALLOCATE (nnp_env%ang(i)%ele2(nnp_env%n_ang(i)))
     550          93 :          ALLOCATE (nnp_env%ang(i)%nuc_ele1(nnp_env%n_ang(i)))
     551          93 :          ALLOCATE (nnp_env%ang(i)%nuc_ele2(nnp_env%n_ang(i)))
     552         401 :          nnp_env%ang(i)%funccut = 0.0_dp
     553         401 :          nnp_env%ang(i)%eta = 0.0_dp
     554         401 :          nnp_env%ang(i)%zeta = 0.0_dp
     555         401 :          nnp_env%ang(i)%prefzeta = 1.0_dp
     556         401 :          nnp_env%ang(i)%lam = 0.0_dp
     557         401 :          nnp_env%ang(i)%ele1 = 'X'
     558         401 :          nnp_env%ang(i)%ele2 = 'X'
     559         401 :          nnp_env%ang(i)%nuc_ele1 = 0
     560         401 :          nnp_env%ang(i)%nuc_ele2 = 0
     561             : 
     562             :          ! set number of nodes
     563          31 :          nnp_env%arc(i)%n_nodes(1) = nnp_env%n_rad(i) + nnp_env%n_ang(i)
     564          93 :          nnp_env%arc(i)%n_nodes(2:nnp_env%n_layer - 1) = nnp_env%n_hnodes
     565          31 :          nnp_env%arc(i)%n_nodes(nnp_env%n_layer) = 1
     566         170 :          DO j = 1, nnp_env%n_layer
     567         372 :             ALLOCATE (nnp_env%arc(i)%layer(j)%node(nnp_env%arc(i)%n_nodes(j)))
     568         372 :             ALLOCATE (nnp_env%arc(i)%layer(j)%node_grad(nnp_env%arc(i)%n_nodes(j)))
     569         527 :             ALLOCATE (nnp_env%arc(i)%layer(j)%tmp_der(nnp_env%arc(i)%n_nodes(1), nnp_env%arc(i)%n_nodes(j)))
     570             :          END DO
     571             :       END DO
     572             : 
     573             :       ! read, bcast and sort symfnct parameters
     574          46 :       DO i = 1, nele
     575          31 :          nnp_env%n_rad(i) = 0
     576          46 :          nnp_env%n_ang(i) = 0
     577             :       END DO
     578          15 :       CALL parser_reset(parser)
     579          15 :       first = .TRUE.
     580          15 :       nnp_env%max_cut = 0.0_dp
     581             :       DO
     582         871 :          CALL parser_search_string(parser, "symfunction_short", .TRUE., found, line)
     583         871 :          IF (found) THEN
     584         856 :             READ (line, *) dummy, ele, symfnct_type
     585        2626 :             DO i = 1, nele
     586        2626 :                IF (TRIM(ele) .EQ. nnp_env%ele(i)) THEN
     587         856 :                   IF (symfnct_type .EQ. 2) THEN
     588         486 :                      nnp_env%n_rad(i) = nnp_env%n_rad(i) + 1
     589         486 :                      READ (line, *) dummy, ele, symfnct_type, &
     590         486 :                         nnp_env%rad(i)%ele(nnp_env%n_rad(i)), &
     591         486 :                         nnp_env%rad(i)%eta(nnp_env%n_rad(i)), &
     592         486 :                         nnp_env%rad(i)%rs(nnp_env%n_rad(i)), &
     593         972 :                         nnp_env%rad(i)%funccut(nnp_env%n_rad(i))
     594         486 :                      IF (nnp_env%max_cut < nnp_env%rad(i)%funccut(nnp_env%n_rad(i))) THEN
     595          16 :                         nnp_env%max_cut = nnp_env%rad(i)%funccut(nnp_env%n_rad(i))
     596             :                      END IF
     597         370 :                   ELSE IF (symfnct_type .EQ. 3) THEN
     598         370 :                      nnp_env%n_ang(i) = nnp_env%n_ang(i) + 1
     599         370 :                      READ (line, *) dummy, ele, symfnct_type, &
     600         370 :                         nnp_env%ang(i)%ele1(nnp_env%n_ang(i)), &
     601         370 :                         nnp_env%ang(i)%ele2(nnp_env%n_ang(i)), &
     602         370 :                         nnp_env%ang(i)%eta(nnp_env%n_ang(i)), &
     603         370 :                         nnp_env%ang(i)%lam(nnp_env%n_ang(i)), &
     604         370 :                         nnp_env%ang(i)%zeta(nnp_env%n_ang(i)), &
     605         740 :                         nnp_env%ang(i)%funccut(nnp_env%n_ang(i))
     606             :                      nnp_env%ang(i)%prefzeta(nnp_env%n_ang(i)) = &
     607         370 :                         2.0_dp**(1.0_dp - nnp_env%ang(i)%zeta(nnp_env%n_ang(i)))
     608         370 :                      IF (nnp_env%max_cut < nnp_env%ang(i)%funccut(nnp_env%n_ang(i))) THEN
     609           0 :                         nnp_env%max_cut = nnp_env%ang(i)%funccut(nnp_env%n_ang(i))
     610             :                      END IF
     611             :                   ELSE
     612             :                      CALL cp_abort(__LOCATION__, TRIM(printtag)// &
     613           0 :                                    "| Symmetry function type not supported")
     614             :                   END IF
     615             :                END IF
     616             :             END DO
     617             :             first = .FALSE.
     618             :          ELSE
     619          15 :             IF (first) CALL cp_abort(__LOCATION__, TRIM(printtag)// &
     620           0 :                                      "| no symfunction_short specified in NNP_INPUT_FILE")
     621             :             ! no additional symfnct found
     622             :             EXIT
     623             :          END IF
     624             :       END DO
     625             : 
     626          46 :       DO i = 1, nele
     627         517 :          DO j = 1, nnp_env%n_rad(i)
     628         517 :             CALL get_ptable_info(nnp_env%rad(i)%ele(j), number=nnp_env%rad(i)%nuc_ele(j))
     629             :          END DO
     630         416 :          DO j = 1, nnp_env%n_ang(i)
     631         370 :             CALL get_ptable_info(nnp_env%ang(i)%ele1(j), number=nnp_env%ang(i)%nuc_ele1(j))
     632         370 :             CALL get_ptable_info(nnp_env%ang(i)%ele2(j), number=nnp_env%ang(i)%nuc_ele2(j))
     633             :             ! sort ele1 and ele2
     634         401 :             IF (nnp_env%ang(i)%nuc_ele1(j) .GT. nnp_env%ang(i)%nuc_ele2(j)) THEN
     635         164 :                ele = nnp_env%ang(i)%ele1(j)
     636         164 :                nnp_env%ang(i)%ele1(j) = nnp_env%ang(i)%ele2(j)
     637         164 :                nnp_env%ang(i)%ele2(j) = ele
     638         164 :                nuc_ele = nnp_env%ang(i)%nuc_ele1(j)
     639         164 :                nnp_env%ang(i)%nuc_ele1(j) = nnp_env%ang(i)%nuc_ele2(j)
     640         164 :                nnp_env%ang(i)%nuc_ele2(j) = nuc_ele
     641             :             END IF
     642             :          END DO
     643             :       END DO
     644             :       ! Done with input.nn file
     645          15 :       CALL parser_release(parser)
     646             : 
     647             :       ! sort symmetry functions and output information
     648          15 :       CALL nnp_sort_acsf(nnp_env)
     649          15 :       CALL nnp_write_acsf(nnp_env, logger%para_env, printtag)
     650          15 :       CALL nnp_write_arc(nnp_env, logger%para_env, printtag)
     651             : 
     652             :       ! read scaling information from file
     653          15 :       IF (nnp_env%scale_acsf .OR. nnp_env%center_acsf .OR. nnp_env%scale_sigma_acsf) THEN
     654          15 :          IF (logger%para_env%is_source()) THEN
     655           8 :             WRITE (unit_nr, *) TRIM(printtag)//"| Reading scaling information from file: ", TRIM(file_name)
     656             :          END IF
     657             :          CALL section_vals_val_get(nnp_env%nnp_input, "SCALE_FILE_NAME", &
     658          15 :                                    c_val=file_name)
     659          15 :          CALL parser_create(parser, file_name, para_env=logger%para_env)
     660             : 
     661             :          ! Get number of elements in scaling file
     662          15 :          CALL parser_read_line(parser, 1)
     663          15 :          k = 0
     664         119 :          DO WHILE (k < 7)
     665         105 :             READ (parser%input_line, *, IOSTAT=io) test_array(1:k)
     666         105 :             IF (io == -1) EXIT
     667         105 :             k = k + 1
     668             :          END DO
     669          15 :          k = k - 1
     670             : 
     671          15 :          IF (k == 5 .AND. nnp_env%scale_sigma_acsf) THEN
     672           0 :             CPABORT("Sigma scaling requested, but scaling.data does not contain sigma.")
     673             :          END IF
     674             : 
     675          15 :          CALL parser_reset(parser)
     676          46 :          DO i = 1, nnp_env%n_ele
     677         517 :             DO j = 1, nnp_env%n_rad(i)
     678         486 :                CALL parser_read_line(parser, 1)
     679         517 :                IF (nnp_env%scale_sigma_acsf) THEN
     680           0 :                   READ (parser%input_line, *) dummy, dummy, &
     681           0 :                      nnp_env%rad(i)%loc_min(j), &
     682           0 :                      nnp_env%rad(i)%loc_max(j), &
     683           0 :                      nnp_env%rad(i)%loc_av(j), &
     684           0 :                      nnp_env%rad(i)%sigma(j)
     685             :                ELSE
     686         486 :                   READ (parser%input_line, *) dummy, dummy, &
     687         486 :                      nnp_env%rad(i)%loc_min(j), &
     688         486 :                      nnp_env%rad(i)%loc_max(j), &
     689         972 :                      nnp_env%rad(i)%loc_av(j)
     690             :                END IF
     691             :             END DO
     692         416 :             DO j = 1, nnp_env%n_ang(i)
     693         370 :                CALL parser_read_line(parser, 1)
     694         401 :                IF (nnp_env%scale_sigma_acsf) THEN
     695           0 :                   READ (parser%input_line, *) dummy, dummy, &
     696           0 :                      nnp_env%ang(i)%loc_min(j), &
     697           0 :                      nnp_env%ang(i)%loc_max(j), &
     698           0 :                      nnp_env%ang(i)%loc_av(j), &
     699           0 :                      nnp_env%ang(i)%sigma(j)
     700             :                ELSE
     701         370 :                   READ (parser%input_line, *) dummy, dummy, &
     702         370 :                      nnp_env%ang(i)%loc_min(j), &
     703         370 :                      nnp_env%ang(i)%loc_max(j), &
     704         740 :                      nnp_env%ang(i)%loc_av(j)
     705             :                END IF
     706             :             END DO
     707             :          END DO
     708          15 :          CALL parser_release(parser)
     709             :       END IF
     710             : 
     711          15 :       CALL nnp_init_acsf_groups(nnp_env)
     712             : 
     713             :       ! read weights from file
     714          46 :       DO i = 1, nnp_env%n_ele
     715         139 :          DO j = 2, nnp_env%n_layer
     716           0 :             ALLOCATE (nnp_env%arc(i)%layer(j)%weights(nnp_env%arc(i)%n_nodes(j - 1), &
     717         465 :                                                       nnp_env%arc(i)%n_nodes(j), nnp_env%n_committee))
     718         403 :             ALLOCATE (nnp_env%arc(i)%layer(j)%bweights(nnp_env%arc(i)%n_nodes(j), nnp_env%n_committee))
     719             :          END DO
     720             :       END DO
     721         114 :       DO i_com = 1, nnp_env%n_committee
     722          99 :          CALL section_vals_val_get(model_section, "WEIGHTS", c_val=base_name, i_rep_section=i_com)
     723          99 :          IF (logger%para_env%is_source()) THEN
     724          50 :             WRITE (unit_nr, *) TRIM(printtag)//"| Initializing weights for model: ", i_com
     725             :          END IF
     726         313 :          DO i = 1, nnp_env%n_ele
     727         199 :             WRITE (file_name, '(A,I0.3,A)') TRIM(base_name)//".", nnp_env%nuc_ele(i), ".data"
     728         199 :             IF (logger%para_env%is_source()) THEN
     729         101 :                WRITE (unit_nr, *) TRIM(printtag)//"| Reading weights from file: ", TRIM(file_name)
     730             :             END IF
     731         199 :             CALL parser_create(parser, file_name, para_env=logger%para_env)
     732         199 :             n_weight = 0
     733      205629 :             DO WHILE (.TRUE.)
     734      205828 :                CALL parser_read_line(parser, 1, at_end)
     735      205828 :                IF (at_end) EXIT
     736      205629 :                n_weight = n_weight + 1
     737             :             END DO
     738             : 
     739         597 :             ALLOCATE (weights(n_weight))
     740             : 
     741         199 :             CALL parser_reset(parser)
     742      205828 :             DO j = 1, n_weight
     743      205629 :                CALL parser_read_line(parser, 1)
     744      205828 :                READ (parser%input_line, *) weights(j)
     745             :             END DO
     746         199 :             CALL parser_release(parser)
     747             : 
     748             :             ! sort weights into corresponding arrays
     749         199 :             iweight = 0
     750         796 :             DO j = 2, nnp_env%n_layer
     751       14231 :                DO k = 1, nnp_env%arc(i)%n_nodes(j - 1)
     752      211671 :                   DO l = 1, nnp_env%arc(i)%n_nodes(j)
     753      197440 :                      iweight = iweight + 1
     754      211074 :                      nnp_env%arc(i)%layer(j)%weights(k, l, i_com) = weights(iweight)
     755             :                   END DO
     756             :                END DO
     757             : 
     758        8985 :                DO k = 1, nnp_env%arc(i)%n_nodes(j)
     759        8189 :                   iweight = iweight + 1
     760        8786 :                   nnp_env%arc(i)%layer(j)%bweights(k, i_com) = weights(iweight)
     761             :                END DO
     762             :             END DO
     763             : 
     764         497 :             DEALLOCATE (weights)
     765             :          END DO
     766             :       END DO
     767             : 
     768             :       !Initialize extrapolation counter
     769          15 :       nnp_env%expol = 0
     770             : 
     771             :       ! Bias the standard deviation of committee disagreement
     772          15 :       NULLIFY (bias_section)
     773          15 :       explicit = .FALSE.
     774             :       !HELIUM NNP does atm not allow for bias (not even defined)
     775          15 :       bias_section => section_vals_get_subs_vals(nnp_env%nnp_input, "BIAS", can_return_null=.TRUE.)
     776          15 :       IF (ASSOCIATED(bias_section)) CALL section_vals_get(bias_section, explicit=explicit)
     777          15 :       nnp_env%bias = .FALSE.
     778          15 :       IF (explicit) THEN
     779           4 :          IF (nnp_env%n_committee > 1) THEN
     780           4 :             IF (logger%para_env%is_source()) THEN
     781           2 :                WRITE (unit_nr, *) "NNP| Biasing of committee disagreement enabled"
     782             :             END IF
     783           4 :             nnp_env%bias = .TRUE.
     784          12 :             ALLOCATE (nnp_env%bias_forces(3, nnp_env%num_atoms))
     785          12 :             ALLOCATE (nnp_env%bias_e_avrg(nnp_env%n_committee))
     786           4 :             CALL section_vals_val_get(bias_section, "SIGMA_0", r_val=nnp_env%bias_sigma0)
     787           4 :             CALL section_vals_val_get(bias_section, "K_B", r_val=nnp_env%bias_kb)
     788          36 :             nnp_env%bias_e_avrg(:) = 0.0_dp
     789           4 :             CALL section_vals_val_get(bias_section, "ALIGN_NNP_ENERGIES", explicit=explicit)
     790           4 :             nnp_env%bias_align = explicit
     791           4 :             IF (explicit) THEN
     792           4 :                NULLIFY (work)
     793           4 :                CALL section_vals_val_get(bias_section, "ALIGN_NNP_ENERGIES", r_vals=work)
     794           4 :                IF (SIZE(work) .NE. nnp_env%n_committee) THEN
     795           0 :                   CPABORT("ALIGN_NNP_ENERGIES size mismatch wrt committee size.")
     796             :                END IF
     797          68 :                nnp_env%bias_e_avrg(:) = work
     798           4 :                IF (logger%para_env%is_source()) THEN
     799           2 :                   WRITE (unit_nr, *) TRIM(printtag)//"| Biasing is aligned by shifting the energy prediction of the C-NNP members"
     800             :                END IF
     801             :             END IF
     802             :          ELSE
     803           0 :             CPWARN("NNP committee size is 1, BIAS section is ignored.")
     804             :          END IF
     805             :       END IF
     806             : 
     807          15 :       IF (logger%para_env%is_source()) THEN
     808           8 :          WRITE (unit_nr, *) TRIM(printtag)//"| NNP force environment initialized"
     809             :       END IF
     810             : 
     811          15 :       CALL timestop(handle)
     812             : 
     813          75 :    END SUBROUTINE nnp_init_model
     814             : 
     815             : END MODULE nnp_environment

Generated by: LCOV version 1.15