LCOV - code coverage report
Current view: top level - src/motion/thermostat - thermostat_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:fd1133a) Lines: 78.2 % 809 633
Test Date: 2025-12-07 06:28:01 Functions: 87.0 % 23 20

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Utilities for thermostats
      10              : !> \author teo [tlaino] - University of Zurich - 10.2007
      11              : ! **************************************************************************************************
      12              : MODULE thermostat_utils
      13              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      14              :                                               get_atomic_kind
      15              :    USE cell_types,                      ONLY: cell_type
      16              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      17              :                                               cp_logger_get_default_io_unit,&
      18              :                                               cp_logger_type,&
      19              :                                               cp_to_string
      20              :    USE cp_output_handling,              ONLY: cp_p_file,&
      21              :                                               cp_print_key_finished_output,&
      22              :                                               cp_print_key_should_output,&
      23              :                                               cp_print_key_unit_nr
      24              :    USE cp_units,                        ONLY: cp_unit_from_cp2k
      25              :    USE distribution_1d_types,           ONLY: distribution_1d_type
      26              :    USE extended_system_types,           ONLY: lnhc_parameters_type,&
      27              :                                               map_info_type,&
      28              :                                               npt_info_type
      29              :    USE input_constants,                 ONLY: &
      30              :         do_constr_atomic, do_constr_molec, do_region_defined, do_region_global, do_region_massive, &
      31              :         do_region_molecule, do_thermo_al, do_thermo_communication, do_thermo_csvr, do_thermo_gle, &
      32              :         do_thermo_no_communication, do_thermo_nose, isokin_ensemble, langevin_ensemble, &
      33              :         npe_f_ensemble, npe_i_ensemble, nph_uniaxial_damped_ensemble, nph_uniaxial_ensemble, &
      34              :         npt_f_ensemble, npt_i_ensemble, npt_ia_ensemble, nve_ensemble, nvt_adiabatic_ensemble, &
      35              :         nvt_ensemble, reftraj_ensemble
      36              :    USE input_section_types,             ONLY: section_vals_get,&
      37              :                                               section_vals_get_subs_vals,&
      38              :                                               section_vals_type,&
      39              :                                               section_vals_val_get
      40              :    USE kinds,                           ONLY: default_string_length,&
      41              :                                               dp
      42              :    USE machine,                         ONLY: m_flush
      43              :    USE message_passing,                 ONLY: mp_comm_type,&
      44              :                                               mp_para_env_type
      45              :    USE molecule_kind_types,             ONLY: get_molecule_kind,&
      46              :                                               get_molecule_kind_set,&
      47              :                                               molecule_kind_type,&
      48              :                                               write_colvar_constraint,&
      49              :                                               write_fixd_constraint,&
      50              :                                               write_g3x3_constraint,&
      51              :                                               write_g4x6_constraint,&
      52              :                                               write_vsite_constraint
      53              :    USE molecule_list_types,             ONLY: molecule_list_type
      54              :    USE molecule_types,                  ONLY: get_molecule,&
      55              :                                               global_constraint_type,&
      56              :                                               molecule_type
      57              :    USE motion_utils,                    ONLY: rot_ana
      58              :    USE particle_list_types,             ONLY: particle_list_type
      59              :    USE particle_types,                  ONLY: particle_type
      60              :    USE physcon,                         ONLY: femtoseconds
      61              :    USE qmmm_types,                      ONLY: qmmm_env_type
      62              :    USE shell_potential_types,           ONLY: shell_kind_type
      63              :    USE simpar_types,                    ONLY: simpar_type
      64              :    USE thermostat_types,                ONLY: thermostat_info_type,&
      65              :                                               thermostat_type,&
      66              :                                               thermostats_type
      67              : #include "../../base/base_uses.f90"
      68              : 
      69              :    IMPLICIT NONE
      70              : 
      71              :    PRIVATE
      72              :    PUBLIC :: compute_degrees_of_freedom, &
      73              :              compute_nfree, &
      74              :              setup_thermostat_info, &
      75              :              setup_adiabatic_thermostat_info, &
      76              :              ke_region_baro, &
      77              :              ke_region_particles, &
      78              :              ke_region_shells, &
      79              :              vel_rescale_baro, &
      80              :              vel_rescale_particles, &
      81              :              vel_rescale_shells, &
      82              :              get_thermostat_energies, &
      83              :              get_nhc_energies, &
      84              :              get_kin_energies, &
      85              :              communication_thermo_low2, &
      86              :              print_thermostats_status, &
      87              :              momentum_region_particles
      88              : 
      89              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'thermostat_utils'
      90              : 
      91              : CONTAINS
      92              : 
      93              : ! **************************************************************************************************
      94              : !> \brief ...
      95              : !> \param cell ...
      96              : !> \param simpar ...
      97              : !> \param molecule_kind_set ...
      98              : !> \param print_section ...
      99              : !> \param particles ...
     100              : !> \param gci ...
     101              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
     102              : ! **************************************************************************************************
     103            0 :    SUBROUTINE compute_nfree(cell, simpar, molecule_kind_set, &
     104              :                             print_section, particles, gci)
     105              : 
     106              :       TYPE(cell_type), POINTER                           :: cell
     107              :       TYPE(simpar_type), POINTER                         :: simpar
     108              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
     109              :       TYPE(section_vals_type), POINTER                   :: print_section
     110              :       TYPE(particle_list_type), POINTER                  :: particles
     111              :       TYPE(global_constraint_type), POINTER              :: gci
     112              : 
     113              :       INTEGER                                            :: natom, nconstraint_ext, nconstraint_int, &
     114              :                                                             nrestraints_int, rot_dof, &
     115              :                                                             roto_trasl_dof
     116              : 
     117              : ! Retrieve information on number of atoms, constraints (external and internal)
     118              : 
     119              :       CALL get_molecule_kind_set(molecule_kind_set=molecule_kind_set, &
     120            0 :                                  natom=natom, nconstraint=nconstraint_int, nrestraints=nrestraints_int)
     121              : 
     122              :       ! Compute degrees of freedom
     123              :       CALL rot_ana(particles%els, dof=roto_trasl_dof, rot_dof=rot_dof, &
     124              :                    print_section=print_section, keep_rotations=.FALSE., &
     125            0 :                    mass_weighted=.TRUE., natoms=natom)
     126              : 
     127            0 :       roto_trasl_dof = roto_trasl_dof - MIN(SUM(cell%perd(1:3)), rot_dof)
     128              : 
     129              :       ! Saving this value of simpar preliminar to the real count of constraints..
     130            0 :       simpar%nfree_rot_transl = roto_trasl_dof
     131              : 
     132              :       ! compute the total number of degrees of freedom for temperature
     133            0 :       nconstraint_ext = gci%ntot - gci%nrestraint
     134            0 :       simpar%nfree = 3*natom - nconstraint_int - nconstraint_ext - roto_trasl_dof
     135              : 
     136            0 :    END SUBROUTINE compute_nfree
     137              : 
     138              : ! **************************************************************************************************
     139              : !> \brief ...
     140              : !> \param thermostats ...
     141              : !> \param cell ...
     142              : !> \param simpar ...
     143              : !> \param molecule_kind_set ...
     144              : !> \param local_molecules ...
     145              : !> \param molecules ...
     146              : !> \param particles ...
     147              : !> \param print_section ...
     148              : !> \param region_sections ...
     149              : !> \param gci ...
     150              : !> \param region ...
     151              : !> \param qmmm_env ...
     152              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
     153              : ! **************************************************************************************************
     154         3538 :    SUBROUTINE compute_degrees_of_freedom(thermostats, cell, simpar, molecule_kind_set, &
     155              :                                          local_molecules, molecules, particles, print_section, region_sections, gci, &
     156              :                                          region, qmmm_env)
     157              : 
     158              :       TYPE(thermostats_type), POINTER                    :: thermostats
     159              :       TYPE(cell_type), POINTER                           :: cell
     160              :       TYPE(simpar_type), POINTER                         :: simpar
     161              :       TYPE(molecule_kind_type), DIMENSION(:), POINTER    :: molecule_kind_set
     162              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
     163              :       TYPE(molecule_list_type), POINTER                  :: molecules
     164              :       TYPE(particle_list_type), POINTER                  :: particles
     165              :       TYPE(section_vals_type), POINTER                   :: print_section, region_sections
     166              :       TYPE(global_constraint_type), POINTER              :: gci
     167              :       INTEGER, INTENT(IN)                                :: region
     168              :       TYPE(qmmm_env_type), POINTER                       :: qmmm_env
     169              : 
     170              :       INTEGER                                            :: ic, iw, natom, nconstraint_ext, &
     171              :                                                             nconstraint_int, nrestraints_int, &
     172              :                                                             rot_dof, roto_trasl_dof
     173              :       TYPE(cp_logger_type), POINTER                      :: logger
     174              : 
     175         1769 :       CPASSERT(ASSOCIATED(gci))
     176              : 
     177              :       ! Retrieve information on number of atoms, constraints (external and internal)
     178              :       CALL get_molecule_kind_set(molecule_kind_set=molecule_kind_set, &
     179         1769 :                                  natom=natom, nconstraint=nconstraint_int, nrestraints=nrestraints_int)
     180              : 
     181              :       ! Compute degrees of freedom
     182              :       CALL rot_ana(particles%els, dof=roto_trasl_dof, rot_dof=rot_dof, &
     183              :                    print_section=print_section, keep_rotations=.FALSE., &
     184         1769 :                    mass_weighted=.TRUE., natoms=natom)
     185              : 
     186         7076 :       roto_trasl_dof = roto_trasl_dof - MIN(SUM(cell%perd(1:3)), rot_dof)
     187              : 
     188              :       ! Collect info about thermostats
     189              :       CALL setup_thermostat_info(thermostats%thermostat_info_part, molecule_kind_set, &
     190              :                                  local_molecules, molecules, particles, region, simpar%ensemble, roto_trasl_dof, &
     191         1769 :                                  region_sections=region_sections, qmmm_env=qmmm_env)
     192              : 
     193              :       ! Saving this value of simpar preliminar to the real count of constraints..
     194         1769 :       simpar%nfree_rot_transl = roto_trasl_dof
     195              : 
     196              :       ! compute the total number of degrees of freedom for temperature
     197         1769 :       nconstraint_ext = gci%ntot - gci%nrestraint
     198         1769 :       simpar%nfree = 3*natom - nconstraint_int - nconstraint_ext - roto_trasl_dof
     199              : 
     200         1769 :       logger => cp_get_default_logger()
     201              :       iw = cp_print_key_unit_nr(logger, print_section, "PROGRAM_RUN_INFO", &
     202         1769 :                                 extension=".log")
     203         1769 :       IF (iw > 0) THEN
     204              :          WRITE (iw, '(/,T2,A)') &
     205          815 :             'DOF| Calculation of degrees of freedom'
     206              :          WRITE (iw, '(T2,A,T71,I10)') &
     207          815 :             'DOF| Number of atoms', natom, &
     208          815 :             'DOF| Number of intramolecular constraints', nconstraint_int, &
     209          815 :             'DOF| Number of intermolecular constraints', nconstraint_ext, &
     210          815 :             'DOF| Invariants (translations + rotations)', roto_trasl_dof, &
     211         1630 :             'DOF| Degrees of freedom', simpar%nfree
     212              :          WRITE (iw, '(/,T2,A)') &
     213          815 :             'DOF| Restraints information'
     214              :          WRITE (iw, '(T2,A,T71,I10)') &
     215          815 :             'DOF| Number of intramolecular restraints', nrestraints_int, &
     216         1630 :             'DOF| Number of intermolecular restraints', gci%nrestraint
     217          815 :          IF (ASSOCIATED(gci%colv_list)) THEN
     218           41 :             DO ic = 1, SIZE(gci%colv_list)
     219           41 :                CALL write_colvar_constraint(gci%colv_list(ic), ic, iw)
     220              :             END DO
     221              :          END IF
     222          815 :          IF (ASSOCIATED(gci%fixd_list)) THEN
     223            3 :             DO ic = 1, SIZE(gci%fixd_list)
     224            3 :                CALL write_fixd_constraint(gci%fixd_list(ic), ic, iw)
     225              :             END DO
     226              :          END IF
     227          815 :          IF (ASSOCIATED(gci%g3x3_list)) THEN
     228            4 :             DO ic = 1, SIZE(gci%g3x3_list)
     229            4 :                CALL write_g3x3_constraint(gci%g3x3_list(ic), ic, iw)
     230              :             END DO
     231              :          END IF
     232          815 :          IF (ASSOCIATED(gci%g4x6_list)) THEN
     233            4 :             DO ic = 1, SIZE(gci%g4x6_list)
     234            4 :                CALL write_g4x6_constraint(gci%g4x6_list(ic), ic, iw)
     235              :             END DO
     236              :          END IF
     237          815 :          IF (ASSOCIATED(gci%vsite_list)) THEN
     238            0 :             DO ic = 1, SIZE(gci%vsite_list)
     239            0 :                CALL write_vsite_constraint(gci%vsite_list(ic), ic, iw)
     240              :             END DO
     241              :          END IF
     242              :       END IF
     243              :       CALL cp_print_key_finished_output(iw, logger, print_section, &
     244         1769 :                                         "PROGRAM_RUN_INFO")
     245              : 
     246         1769 :    END SUBROUTINE compute_degrees_of_freedom
     247              : 
     248              : ! **************************************************************************************************
     249              : !> \brief ...
     250              : !> \param thermostat_info ...
     251              : !> \param molecule_kind_set ...
     252              : !> \param local_molecules ...
     253              : !> \param molecules ...
     254              : !> \param particles ...
     255              : !> \param region ...
     256              : !> \param ensemble ...
     257              : !> \param nfree ...
     258              : !> \param shell ...
     259              : !> \param region_sections ...
     260              : !> \param qmmm_env ...
     261              : !> \author 10.2011  CJM - PNNL
     262              : ! **************************************************************************************************
     263            0 :    SUBROUTINE setup_adiabatic_thermostat_info(thermostat_info, molecule_kind_set, local_molecules, &
     264              :                                               molecules, particles, region, ensemble, nfree, shell, region_sections, qmmm_env)
     265              :       TYPE(thermostat_info_type), POINTER                :: thermostat_info
     266              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
     267              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
     268              :       TYPE(molecule_list_type), POINTER                  :: molecules
     269              :       TYPE(particle_list_type), POINTER                  :: particles
     270              :       INTEGER, INTENT(IN)                                :: region, ensemble
     271              :       INTEGER, INTENT(INOUT), OPTIONAL                   :: nfree
     272              :       LOGICAL, INTENT(IN), OPTIONAL                      :: shell
     273              :       TYPE(section_vals_type), POINTER                   :: region_sections
     274              :       TYPE(qmmm_env_type), POINTER                       :: qmmm_env
     275              : 
     276              :       INTEGER :: dis_type, first_atom, i, ikind, imol, imol_global, ipart, itherm, katom, &
     277              :          last_atom, natom, natom_local, nkind, nmol_local, nmol_per_kind, nmolecule, nshell, &
     278              :          number, stat, sum_of_thermostats
     279            0 :       INTEGER, POINTER                                   :: molecule_list(:), thermolist(:)
     280              :       LOGICAL                                            :: check, do_shell, nointer, on_therm
     281              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     282            0 :       TYPE(molecule_type), POINTER                       :: molecule, molecule_set(:)
     283              : 
     284            0 :       NULLIFY (molecule_kind, molecule, thermostat_info%map_loc_thermo_gen, thermolist)
     285            0 :       nkind = SIZE(molecule_kind_set)
     286            0 :       do_shell = .FALSE.
     287            0 :       IF (PRESENT(shell)) do_shell = shell
     288              :       ! Counting the global number of thermostats
     289            0 :       sum_of_thermostats = 0
     290              :       ! Variable to denote independent thermostats (no communication necessary)
     291            0 :       nointer = .TRUE.
     292            0 :       check = .TRUE.
     293            0 :       number = 0
     294            0 :       dis_type = do_thermo_no_communication
     295              : 
     296              :       CALL get_adiabatic_region_info(region_sections, sum_of_thermostats, &
     297              :                                      thermolist=thermolist, &
     298              :                                      molecule_kind_set=molecule_kind_set, &
     299            0 :                                      molecules=molecules, particles=particles, qmmm_env=qmmm_env)
     300              : 
     301              : !    map_loc_thermo_gen=>thermostat_info%map_loc_thermo_gen
     302            0 :       molecule_set => molecules%els
     303            0 :       SELECT CASE (ensemble)
     304              :       CASE DEFAULT
     305            0 :          CPABORT('Unknown ensemble')
     306              :       CASE (nvt_adiabatic_ensemble)
     307            0 :          SELECT CASE (region)
     308              :          CASE (do_region_global)
     309              :             ! Global Thermostat
     310            0 :             nointer = .FALSE.
     311            0 :             sum_of_thermostats = 1
     312              :          CASE (do_region_molecule)
     313              :             ! Molecular Thermostat
     314              :             itherm = 0
     315            0 :             DO ikind = 1, nkind
     316            0 :                molecule_kind => molecule_kind_set(ikind)
     317            0 :                nmol_per_kind = local_molecules%n_el(ikind)
     318              :                CALL get_molecule_kind(molecule_kind, natom=natom, &
     319            0 :                                       molecule_list=molecule_list)
     320              : ! use thermolist ( ipart ) to get global indexing correct
     321            0 :                DO imol_global = 1, SIZE(molecule_list)
     322            0 :                   molecule => molecule_set(molecule_list(imol_global))
     323              :                   CALL get_molecule(molecule, first_atom=first_atom, &
     324            0 :                                     last_atom=last_atom)
     325            0 :                   on_therm = .TRUE.
     326            0 :                   DO katom = first_atom, last_atom
     327            0 :                      IF (thermolist(katom) == HUGE(0)) THEN
     328              :                         on_therm = .FALSE.
     329              :                         EXIT
     330              :                      END IF
     331              :                   END DO
     332            0 :                   IF (on_therm) THEN
     333            0 :                      itherm = itherm + 1
     334            0 :                      DO katom = first_atom, last_atom
     335            0 :                         thermolist(katom) = itherm
     336              :                      END DO
     337              :                   END IF
     338              :                END DO
     339              :             END DO
     340            0 :             DO i = 1, nkind
     341            0 :                molecule_kind => molecule_kind_set(i)
     342            0 :                CALL get_molecule_kind(molecule_kind, nmolecule=nmolecule, nshell=nshell)
     343            0 :                IF ((do_shell) .AND. (nshell == 0)) nmolecule = 0
     344            0 :                sum_of_thermostats = sum_of_thermostats + nmolecule
     345              :             END DO
     346              :             ! If we have ONE kind and ONE molecule, then effectively we have a GLOBAL thermostat
     347              :             ! and the degrees of freedom will be computed correctly for this special case
     348            0 :             IF ((nmolecule == 1) .AND. (nkind == 1)) nointer = .FALSE.
     349              :          CASE (do_region_massive)
     350              :             ! Massive Thermostat
     351            0 :             DO i = 1, nkind
     352            0 :                molecule_kind => molecule_kind_set(i)
     353              :                CALL get_molecule_kind(molecule_kind, nmolecule=nmolecule, &
     354            0 :                                       natom=natom, nshell=nshell)
     355            0 :                IF (do_shell) natom = nshell
     356            0 :                sum_of_thermostats = sum_of_thermostats + 3*natom*nmolecule
     357              :             END DO
     358              :          END SELECT
     359              : 
     360            0 :          natom_local = 0
     361            0 :          DO ikind = 1, SIZE(molecule_kind_set)
     362            0 :             nmol_per_kind = local_molecules%n_el(ikind)
     363            0 :             DO imol = 1, nmol_per_kind
     364            0 :                i = local_molecules%list(ikind)%array(imol)
     365            0 :                molecule => molecule_set(i)
     366            0 :                CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     367            0 :                DO ipart = first_atom, last_atom
     368            0 :                   natom_local = natom_local + 1
     369              :                END DO
     370              :             END DO
     371              :          END DO
     372              : 
     373              :          ! Now map the local atoms with the corresponding thermostat
     374            0 :          ALLOCATE (thermostat_info%map_loc_thermo_gen(natom_local), stat=stat)
     375            0 :          thermostat_info%map_loc_thermo_gen = HUGE(0)
     376            0 :          CPASSERT(stat == 0)
     377            0 :          natom_local = 0
     378            0 :          DO ikind = 1, SIZE(molecule_kind_set)
     379            0 :             nmol_per_kind = local_molecules%n_el(ikind)
     380            0 :             DO imol = 1, nmol_per_kind
     381            0 :                i = local_molecules%list(ikind)%array(imol)
     382            0 :                molecule => molecule_set(i)
     383            0 :                CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     384            0 :                DO ipart = first_atom, last_atom
     385            0 :                   natom_local = natom_local + 1
     386              : ! only map the correct region to the thermostat
     387            0 :                   IF (thermolist(ipart) /= HUGE(0)) &
     388            0 :                      thermostat_info%map_loc_thermo_gen(natom_local) = thermolist(ipart)
     389              :                END DO
     390              :             END DO
     391              :          END DO
     392              :          ! Here we decide which parallel algorithm to use.
     393              :          ! if there are only massive and molecule type thermostats we can use
     394              :          ! a local scheme, in cases involving any combination with a
     395              :          ! global thermostat we assume a coupling of  degrees of freedom
     396              :          ! from different processors
     397            0 :          IF (nointer) THEN
     398              :             ! Distributed thermostats, no interaction
     399            0 :             dis_type = do_thermo_no_communication
     400              :             ! we only count thermostats on this processor
     401              :             number = 0
     402            0 :             DO ikind = 1, nkind
     403            0 :                nmol_local = local_molecules%n_el(ikind)
     404            0 :                molecule_kind => molecule_kind_set(ikind)
     405            0 :                CALL get_molecule_kind(molecule_kind, natom=natom, nshell=nshell)
     406            0 :                IF (do_shell) THEN
     407            0 :                   natom = nshell
     408            0 :                   IF (nshell == 0) nmol_local = 0
     409              :                END IF
     410            0 :                IF (region == do_region_molecule) THEN
     411            0 :                   number = number + nmol_local
     412            0 :                ELSE IF (region == do_region_massive) THEN
     413            0 :                   number = number + 3*nmol_local*natom
     414              :                ELSE
     415            0 :                   CPABORT('Invalid region setup')
     416              :                END IF
     417              :             END DO
     418              :          ELSE
     419              :             ! REPlicated thermostats, INTERacting via communication
     420            0 :             dis_type = do_thermo_communication
     421            0 :             IF ((region == do_region_global) .OR. (region == do_region_molecule)) number = 1
     422              :          END IF
     423              : 
     424            0 :          IF (PRESENT(nfree)) THEN
     425              :             ! re-initializing simpar%nfree to zero because of multiple thermostats in the adiabatic sampling
     426            0 :             nfree = 0
     427              :          END IF
     428              :       END SELECT
     429              : 
     430              :       ! Saving information about thermostats
     431            0 :       thermostat_info%sum_of_thermostats = sum_of_thermostats
     432            0 :       thermostat_info%number_of_thermostats = number
     433            0 :       thermostat_info%dis_type = dis_type
     434              : 
     435            0 :       DEALLOCATE (thermolist)
     436              : 
     437            0 :    END SUBROUTINE setup_adiabatic_thermostat_info
     438              : 
     439              : ! **************************************************************************************************
     440              : !> \brief ...
     441              : !> \param region_sections ...
     442              : !> \param sum_of_thermostats ...
     443              : !> \param thermolist ...
     444              : !> \param molecule_kind_set ...
     445              : !> \param molecules ...
     446              : !> \param particles ...
     447              : !> \param qmmm_env ...
     448              : !> \author 10.2011 CJM -PNNL
     449              : ! **************************************************************************************************
     450            0 :    SUBROUTINE get_adiabatic_region_info(region_sections, sum_of_thermostats, &
     451              :                                         thermolist, molecule_kind_set, molecules, particles, &
     452              :                                         qmmm_env)
     453              :       TYPE(section_vals_type), POINTER                   :: region_sections
     454              :       INTEGER, INTENT(INOUT), OPTIONAL                   :: sum_of_thermostats
     455              :       INTEGER, DIMENSION(:), POINTER                     :: thermolist(:)
     456              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
     457              :       TYPE(molecule_list_type), POINTER                  :: molecules
     458              :       TYPE(particle_list_type), POINTER                  :: particles
     459              :       TYPE(qmmm_env_type), POINTER                       :: qmmm_env
     460              : 
     461              :       CHARACTER(LEN=default_string_length), &
     462            0 :          DIMENSION(:), POINTER                           :: tmpstringlist
     463              :       INTEGER                                            :: first_atom, i, ig, ikind, ilist, imol, &
     464              :                                                             ipart, itherm, jg, last_atom, &
     465              :                                                             mregions, n_rep, nregions, output_unit
     466            0 :       INTEGER, DIMENSION(:), POINTER                     :: tmplist
     467              :       TYPE(cp_logger_type), POINTER                      :: logger
     468              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     469              :       TYPE(molecule_type), DIMENSION(:), POINTER         :: molecule_set
     470              :       TYPE(molecule_type), POINTER                       :: molecule
     471              : 
     472            0 :       NULLIFY (tmplist, tmpstringlist, thermolist, molecule_kind, molecule, molecule_set)
     473            0 :       NULLIFY (logger)
     474            0 :       logger => cp_get_default_logger()
     475            0 :       output_unit = cp_logger_get_default_io_unit(logger)
     476              :       ! CPASSERT(.NOT.(ASSOCIATED(map_loc_thermo_gen)))
     477            0 :       CALL section_vals_get(region_sections, n_repetition=nregions)
     478            0 :       ALLOCATE (thermolist(particles%n_els))
     479            0 :       thermolist = HUGE(0)
     480            0 :       molecule_set => molecules%els
     481            0 :       mregions = nregions
     482            0 :       itherm = 0
     483            0 :       DO ig = 1, mregions
     484            0 :          CALL section_vals_val_get(region_sections, "LIST", i_rep_section=ig, n_rep_val=n_rep)
     485            0 :          DO jg = 1, n_rep
     486            0 :             CALL section_vals_val_get(region_sections, "LIST", i_rep_section=ig, i_rep_val=jg, i_vals=tmplist)
     487            0 :             DO i = 1, SIZE(tmplist)
     488            0 :                ipart = tmplist(i)
     489            0 :                CPASSERT(((ipart > 0) .AND. (ipart <= particles%n_els)))
     490            0 :                IF (thermolist(ipart) == HUGE(0)) THEN
     491            0 :                   itherm = itherm + 1
     492            0 :                   thermolist(ipart) = itherm
     493              :                ELSE
     494            0 :                   CPABORT("")
     495              :                END IF
     496              :             END DO
     497              :          END DO
     498            0 :          CALL section_vals_val_get(region_sections, "MOLNAME", i_rep_section=ig, n_rep_val=n_rep)
     499            0 :          DO jg = 1, n_rep
     500            0 :             CALL section_vals_val_get(region_sections, "MOLNAME", i_rep_section=ig, i_rep_val=jg, c_vals=tmpstringlist)
     501            0 :             DO ilist = 1, SIZE(tmpstringlist)
     502            0 :                DO ikind = 1, SIZE(molecule_kind_set)
     503            0 :                   molecule_kind => molecule_kind_set(ikind)
     504            0 :                   IF (molecule_kind%name == tmpstringlist(ilist)) THEN
     505            0 :                      DO imol = 1, SIZE(molecule_kind%molecule_list)
     506            0 :                         molecule => molecule_set(molecule_kind%molecule_list(imol))
     507            0 :                         CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     508            0 :                         DO ipart = first_atom, last_atom
     509            0 :                            IF (thermolist(ipart) == HUGE(0)) THEN
     510            0 :                               itherm = itherm + 1
     511            0 :                               thermolist(ipart) = itherm
     512              :                            ELSE
     513            0 :                               CPABORT("")
     514              :                            END IF
     515              :                         END DO
     516              :                      END DO
     517              :                   END IF
     518              :                END DO
     519              :             END DO
     520              :          END DO
     521              :          CALL setup_thermostat_subsys(region_sections, qmmm_env, thermolist, molecule_set, &
     522            0 :                                       subsys_qm=.FALSE., ig=ig, sum_of_thermostats=sum_of_thermostats, nregions=nregions)
     523              :          CALL setup_thermostat_subsys(region_sections, qmmm_env, thermolist, molecule_set, &
     524            0 :                                       subsys_qm=.TRUE., ig=ig, sum_of_thermostats=sum_of_thermostats, nregions=nregions)
     525              :       END DO
     526              : 
     527            0 :       CPASSERT(.NOT. ALL(thermolist == HUGE(0)))
     528              : 
     529              : !    natom_local = 0
     530              : !    DO ikind = 1, SIZE(molecule_kind_set)
     531              : !       nmol_per_kind = local_molecules%n_el(ikind)
     532              : !       DO imol = 1, nmol_per_kind
     533              : !          i = local_molecules%list(ikind)%array(imol)
     534              : !          molecule => molecule_set(i)
     535              : !          CALL get_molecule ( molecule, first_atom = first_atom, last_atom = last_atom )
     536              : !          DO ipart = first_atom, last_atom
     537              : !             natom_local = natom_local + 1
     538              : !          END DO
     539              : !       END DO
     540              : !    END DO
     541              : 
     542              :       ! Now map the local atoms with the corresponding thermostat
     543              : !    ALLOCATE(map_loc_thermo_gen(natom_local),stat=stat)
     544              : !    map_loc_thermo_gen  = HUGE ( 0 )
     545              : !    CPPostcondition(stat==0,cp_failure_level,routineP,failure)
     546              : !    natom_local = 0
     547              : !    DO ikind = 1, SIZE(molecule_kind_set)
     548              : !       nmol_per_kind = local_molecules%n_el(ikind)
     549              : !       DO imol = 1, nmol_per_kind
     550              : !          i = local_molecules%list(ikind)%array(imol)
     551              : !          molecule => molecule_set(i)
     552              : !          CALL get_molecule ( molecule, first_atom = first_atom, last_atom = last_atom )
     553              : !          DO ipart = first_atom, last_atom
     554              : !             natom_local = natom_local + 1
     555              : ! only map the correct region to the thermostat
     556              : !             IF ( thermolist (ipart ) /= HUGE ( 0 ) ) &
     557              : !             map_loc_thermo_gen(natom_local) = thermolist(ipart)
     558              : !          END DO
     559              : !       END DO
     560              : !    END DO
     561              : 
     562              : !    DEALLOCATE(thermolist, stat=stat)
     563              : !    CPPostcondition(stat==0,cp_failure_level,routineP,failure)
     564            0 :    END SUBROUTINE get_adiabatic_region_info
     565              : ! **************************************************************************************************
     566              : !> \brief ...
     567              : !> \param thermostat_info ...
     568              : !> \param molecule_kind_set ...
     569              : !> \param local_molecules ...
     570              : !> \param molecules ...
     571              : !> \param particles ...
     572              : !> \param region ...
     573              : !> \param ensemble ...
     574              : !> \param nfree ...
     575              : !> \param shell ...
     576              : !> \param region_sections ...
     577              : !> \param qmmm_env ...
     578              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
     579              : ! **************************************************************************************************
     580         1815 :    SUBROUTINE setup_thermostat_info(thermostat_info, molecule_kind_set, local_molecules, &
     581              :                                     molecules, particles, region, ensemble, nfree, shell, region_sections, qmmm_env)
     582              :       TYPE(thermostat_info_type), POINTER                :: thermostat_info
     583              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
     584              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
     585              :       TYPE(molecule_list_type), POINTER                  :: molecules
     586              :       TYPE(particle_list_type), POINTER                  :: particles
     587              :       INTEGER, INTENT(IN)                                :: region, ensemble
     588              :       INTEGER, INTENT(INOUT), OPTIONAL                   :: nfree
     589              :       LOGICAL, INTENT(IN), OPTIONAL                      :: shell
     590              :       TYPE(section_vals_type), POINTER                   :: region_sections
     591              :       TYPE(qmmm_env_type), POINTER                       :: qmmm_env
     592              : 
     593              :       INTEGER                                            :: dis_type, i, ikind, natom, nkind, &
     594              :                                                             nmol_local, nmolecule, nshell, number, &
     595              :                                                             sum_of_thermostats
     596              :       LOGICAL                                            :: check, do_shell, nointer
     597              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     598              : 
     599         1815 :       NULLIFY (molecule_kind)
     600         1815 :       nkind = SIZE(molecule_kind_set)
     601         1815 :       do_shell = .FALSE.
     602         1815 :       IF (PRESENT(shell)) do_shell = shell
     603              :       ! Counting the global number of thermostats
     604         1815 :       sum_of_thermostats = 0
     605              :       ! Variable to denote independent thermostats (no communication necessary)
     606         1815 :       nointer = .TRUE.
     607         1815 :       check = .TRUE.
     608         1815 :       number = 0
     609         1815 :       dis_type = do_thermo_no_communication
     610              : 
     611         1815 :       SELECT CASE (ensemble)
     612              :       CASE DEFAULT
     613            0 :          CPABORT('Unknown ensemble')
     614              :       CASE (isokin_ensemble, nph_uniaxial_ensemble, nph_uniaxial_damped_ensemble, &
     615              :             reftraj_ensemble, langevin_ensemble)
     616              :          ! Do Nothing
     617              :       CASE (nve_ensemble, nvt_ensemble, nvt_adiabatic_ensemble, npt_i_ensemble, &
     618              :             npt_f_ensemble, npe_i_ensemble, npe_f_ensemble, npt_ia_ensemble)
     619         1727 :          IF (ensemble == nve_ensemble) check = do_shell
     620         2958 :          IF (check) THEN
     621          876 :             SELECT CASE (region)
     622              :             CASE (do_region_global)
     623              :                ! Global Thermostat
     624          288 :                nointer = .FALSE.
     625          288 :                sum_of_thermostats = 1
     626              :             CASE (do_region_molecule)
     627              :                ! Molecular Thermostat
     628         6052 :                DO i = 1, nkind
     629         5916 :                   molecule_kind => molecule_kind_set(i)
     630         5916 :                   CALL get_molecule_kind(molecule_kind, nmolecule=nmolecule, nshell=nshell)
     631         5916 :                   IF ((do_shell) .AND. (nshell == 0)) nmolecule = 0
     632        11968 :                   sum_of_thermostats = sum_of_thermostats + nmolecule
     633              :                END DO
     634              :                ! If we have ONE kind and ONE molecule, then effectively we have a GLOBAL thermostat
     635              :                ! and the degrees of freedom will be computed correctly for this special case
     636          136 :                IF ((nmolecule == 1) .AND. (nkind == 1)) nointer = .FALSE.
     637              :             CASE (do_region_massive)
     638              :                ! Massive Thermostat
     639         8882 :                DO i = 1, nkind
     640         8750 :                   molecule_kind => molecule_kind_set(i)
     641              :                   CALL get_molecule_kind(molecule_kind, nmolecule=nmolecule, &
     642         8750 :                                          natom=natom, nshell=nshell)
     643         8750 :                   IF (do_shell) natom = nshell
     644        17632 :                   sum_of_thermostats = sum_of_thermostats + 3*natom*nmolecule
     645              :                END DO
     646              :             CASE (do_region_defined)
     647              :                ! User defined region to thermostat..
     648           32 :                nointer = .FALSE.
     649              :                ! Determine the number of thermostats defined in the input
     650           32 :                CALL section_vals_get(region_sections, n_repetition=sum_of_thermostats)
     651           32 :                IF (sum_of_thermostats < 1) &
     652              :                   CALL cp_abort(__LOCATION__, &
     653          588 :                                 "Provide at least 1 region (&DEFINE_REGION) when using the thermostat type DEFINED")
     654              :             END SELECT
     655              : 
     656              :             ! Here we decide which parallel algorithm to use.
     657              :             ! if there are only massive and molecule type thermostats we can use
     658              :             ! a local scheme, in cases involving any combination with a
     659              :             ! global thermostat we assume a coupling of  degrees of freedom
     660              :             ! from different processors
     661              :             IF (nointer) THEN
     662              :                ! Distributed thermostats, no interaction
     663        14926 :                dis_type = do_thermo_no_communication
     664              :                ! we only count thermostats on this processor
     665              :                number = 0
     666        14926 :                DO ikind = 1, nkind
     667        14662 :                   nmol_local = local_molecules%n_el(ikind)
     668        14662 :                   molecule_kind => molecule_kind_set(ikind)
     669        14662 :                   CALL get_molecule_kind(molecule_kind, natom=natom, nshell=nshell)
     670        14662 :                   IF (do_shell) THEN
     671           58 :                      natom = nshell
     672           58 :                      IF (nshell == 0) nmol_local = 0
     673              :                   END IF
     674        29588 :                   IF (region == do_region_molecule) THEN
     675         5912 :                      number = number + nmol_local
     676         8750 :                   ELSE IF (region == do_region_massive) THEN
     677         8750 :                      number = number + 3*nmol_local*natom
     678              :                   ELSE
     679            0 :                      CPABORT('Invalid region setup')
     680              :                   END IF
     681              :                END DO
     682              :             ELSE
     683              :                ! REPlicated thermostats, INTERacting via communication
     684          324 :                dis_type = do_thermo_communication
     685          324 :                IF ((region == do_region_global) .OR. (region == do_region_molecule)) THEN
     686          292 :                   number = 1
     687           32 :                ELSE IF (region == do_region_defined) THEN
     688              :                   CALL get_defined_region_info(region_sections, number, sum_of_thermostats, &
     689              :                                                map_loc_thermo_gen=thermostat_info%map_loc_thermo_gen, &
     690              :                                                local_molecules=local_molecules, molecule_kind_set=molecule_kind_set, &
     691           32 :                                                molecules=molecules, particles=particles, qmmm_env=qmmm_env)
     692              :                END IF
     693              :             END IF
     694              : 
     695          588 :             IF (PRESENT(nfree)) THEN
     696          542 :                IF ((sum_of_thermostats > 1) .OR. (dis_type == do_thermo_no_communication)) THEN
     697              :                   ! re-initializing simpar%nfree to zero because of multiple thermostats
     698          260 :                   nfree = 0
     699              :                END IF
     700              :             END IF
     701              :          END IF
     702              :       END SELECT
     703              : 
     704              :       ! Saving information about thermostats
     705         1815 :       thermostat_info%sum_of_thermostats = sum_of_thermostats
     706         1815 :       thermostat_info%number_of_thermostats = number
     707         1815 :       thermostat_info%dis_type = dis_type
     708         1815 :    END SUBROUTINE setup_thermostat_info
     709              : 
     710              : ! **************************************************************************************************
     711              : !> \brief ...
     712              : !> \param region_sections ...
     713              : !> \param number ...
     714              : !> \param sum_of_thermostats ...
     715              : !> \param map_loc_thermo_gen ...
     716              : !> \param local_molecules ...
     717              : !> \param molecule_kind_set ...
     718              : !> \param molecules ...
     719              : !> \param particles ...
     720              : !> \param qmmm_env ...
     721              : !> \author 11.2007 [tlaino] - Teodoro Laino - University of Zurich
     722              : ! **************************************************************************************************
     723           32 :    SUBROUTINE get_defined_region_info(region_sections, number, sum_of_thermostats, &
     724              :                                       map_loc_thermo_gen, local_molecules, molecule_kind_set, molecules, particles, &
     725              :                                       qmmm_env)
     726              :       TYPE(section_vals_type), POINTER                   :: region_sections
     727              :       INTEGER, INTENT(OUT), OPTIONAL                     :: number
     728              :       INTEGER, INTENT(INOUT), OPTIONAL                   :: sum_of_thermostats
     729              :       INTEGER, DIMENSION(:), POINTER                     :: map_loc_thermo_gen
     730              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
     731              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
     732              :       TYPE(molecule_list_type), POINTER                  :: molecules
     733              :       TYPE(particle_list_type), POINTER                  :: particles
     734              :       TYPE(qmmm_env_type), POINTER                       :: qmmm_env
     735              : 
     736              :       CHARACTER(LEN=default_string_length), &
     737           32 :          DIMENSION(:), POINTER                           :: tmpstringlist
     738              :       INTEGER :: first_atom, i, ig, ikind, ilist, imol, ipart, jg, last_atom, mregions, n_rep, &
     739              :          natom_local, nmol_per_kind, nregions, output_unit
     740           32 :       INTEGER, DIMENSION(:), POINTER                     :: thermolist, tmp, tmplist
     741              :       TYPE(cp_logger_type), POINTER                      :: logger
     742              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     743              :       TYPE(molecule_type), DIMENSION(:), POINTER         :: molecule_set
     744              :       TYPE(molecule_type), POINTER                       :: molecule
     745              : 
     746           32 :       NULLIFY (tmplist, tmpstringlist, thermolist, molecule_kind, molecule, molecule_set)
     747           32 :       NULLIFY (logger)
     748           64 :       logger => cp_get_default_logger()
     749           32 :       output_unit = cp_logger_get_default_io_unit(logger)
     750           32 :       CPASSERT(.NOT. (ASSOCIATED(map_loc_thermo_gen)))
     751           32 :       CALL section_vals_get(region_sections, n_repetition=nregions)
     752           96 :       ALLOCATE (thermolist(particles%n_els))
     753        43970 :       thermolist = HUGE(0)
     754           32 :       molecule_set => molecules%els
     755           32 :       mregions = nregions
     756          102 :       DO ig = 1, mregions
     757           70 :          CALL section_vals_val_get(region_sections, "LIST", i_rep_section=ig, n_rep_val=n_rep)
     758          184 :          DO jg = 1, n_rep
     759          114 :             CALL section_vals_val_get(region_sections, "LIST", i_rep_section=ig, i_rep_val=jg, i_vals=tmplist)
     760         2428 :             DO i = 1, SIZE(tmplist)
     761         2244 :                ipart = tmplist(i)
     762         2244 :                CPASSERT(((ipart > 0) .AND. (ipart <= particles%n_els)))
     763         2358 :                IF (thermolist(ipart) == HUGE(0)) THEN
     764         2244 :                   thermolist(ipart) = ig
     765              :                ELSE
     766            0 :                   CPABORT("")
     767              :                END IF
     768              :             END DO
     769              :          END DO
     770           70 :          CALL section_vals_val_get(region_sections, "MOLNAME", i_rep_section=ig, n_rep_val=n_rep)
     771           74 :          DO jg = 1, n_rep
     772            4 :             CALL section_vals_val_get(region_sections, "MOLNAME", i_rep_section=ig, i_rep_val=jg, c_vals=tmpstringlist)
     773           78 :             DO ilist = 1, SIZE(tmpstringlist)
     774           20 :                DO ikind = 1, SIZE(molecule_kind_set)
     775           12 :                   molecule_kind => molecule_kind_set(ikind)
     776           16 :                   IF (molecule_kind%name == tmpstringlist(ilist)) THEN
     777           48 :                      DO imol = 1, SIZE(molecule_kind%molecule_list)
     778           44 :                         molecule => molecule_set(molecule_kind%molecule_list(imol))
     779           44 :                         CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     780          180 :                         DO ipart = first_atom, last_atom
     781          176 :                            IF (thermolist(ipart) == HUGE(0)) THEN
     782          132 :                               thermolist(ipart) = ig
     783              :                            ELSE
     784            0 :                               CPABORT("")
     785              :                            END IF
     786              :                         END DO
     787              :                      END DO
     788              :                   END IF
     789              :                END DO
     790              :             END DO
     791              :          END DO
     792              :          CALL setup_thermostat_subsys(region_sections, qmmm_env, thermolist, molecule_set, &
     793           70 :                                       subsys_qm=.FALSE., ig=ig, sum_of_thermostats=sum_of_thermostats, nregions=nregions)
     794              :          CALL setup_thermostat_subsys(region_sections, qmmm_env, thermolist, molecule_set, &
     795          242 :                                       subsys_qm=.TRUE., ig=ig, sum_of_thermostats=sum_of_thermostats, nregions=nregions)
     796              :       END DO
     797              : 
     798              :       ! Dump IO warning for not thermalized particles
     799        29100 :       IF (ANY(thermolist == HUGE(0))) THEN
     800           14 :          nregions = nregions + 1
     801           14 :          sum_of_thermostats = sum_of_thermostats + 1
     802        15008 :          ALLOCATE (tmp(COUNT(thermolist == HUGE(0))))
     803        14980 :          ilist = 0
     804        14980 :          DO i = 1, SIZE(thermolist)
     805        14980 :             IF (thermolist(i) == HUGE(0)) THEN
     806        13894 :                ilist = ilist + 1
     807        13894 :                tmp(ilist) = i
     808        13894 :                thermolist(i) = nregions
     809              :             END IF
     810              :          END DO
     811           14 :          IF (output_unit > 0) THEN
     812            7 :             WRITE (output_unit, '(A)') " WARNING| No thermostats defined for the following atoms:"
     813         6954 :             IF (ilist > 0) WRITE (output_unit, '(" WARNING|",9I8)') tmp
     814            7 :             WRITE (output_unit, '(A)') " WARNING| They will be included in a further unique thermostat!"
     815              :          END IF
     816           14 :          DEALLOCATE (tmp)
     817              :       END IF
     818        43970 :       CPASSERT(ALL(thermolist /= HUGE(0)))
     819              : 
     820              :       ! Now identify the local number of thermostats
     821           96 :       ALLOCATE (tmp(nregions))
     822          116 :       tmp = 0
     823           32 :       natom_local = 0
     824           98 :       DO ikind = 1, SIZE(molecule_kind_set)
     825           66 :          nmol_per_kind = local_molecules%n_el(ikind)
     826         7384 :          DO imol = 1, nmol_per_kind
     827         7286 :             i = local_molecules%list(ikind)%array(imol)
     828         7286 :             molecule => molecule_set(i)
     829         7286 :             CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     830        29321 :             DO ipart = first_atom, last_atom
     831        21969 :                natom_local = natom_local + 1
     832        29255 :                tmp(thermolist(ipart)) = 1
     833              :             END DO
     834              :          END DO
     835              :       END DO
     836          116 :       number = SUM(tmp)
     837           32 :       DEALLOCATE (tmp)
     838              : 
     839              :       ! Now map the local atoms with the corresponding thermostat
     840           96 :       ALLOCATE (map_loc_thermo_gen(natom_local))
     841           32 :       natom_local = 0
     842           98 :       DO ikind = 1, SIZE(molecule_kind_set)
     843           66 :          nmol_per_kind = local_molecules%n_el(ikind)
     844         7384 :          DO imol = 1, nmol_per_kind
     845         7286 :             i = local_molecules%list(ikind)%array(imol)
     846         7286 :             molecule => molecule_set(i)
     847         7286 :             CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     848        29321 :             DO ipart = first_atom, last_atom
     849        21969 :                natom_local = natom_local + 1
     850        29255 :                map_loc_thermo_gen(natom_local) = thermolist(ipart)
     851              :             END DO
     852              :          END DO
     853              :       END DO
     854              : 
     855           32 :       DEALLOCATE (thermolist)
     856           64 :    END SUBROUTINE get_defined_region_info
     857              : 
     858              : ! **************************************************************************************************
     859              : !> \brief ...
     860              : !> \param region_sections ...
     861              : !> \param qmmm_env ...
     862              : !> \param thermolist ...
     863              : !> \param molecule_set ...
     864              : !> \param subsys_qm ...
     865              : !> \param ig ...
     866              : !> \param sum_of_thermostats ...
     867              : !> \param nregions ...
     868              : !> \author 11.2007 [tlaino] - Teodoro Laino - University of Zurich
     869              : ! **************************************************************************************************
     870          140 :    SUBROUTINE setup_thermostat_subsys(region_sections, qmmm_env, thermolist, &
     871              :                                       molecule_set, subsys_qm, ig, sum_of_thermostats, nregions)
     872              :       TYPE(section_vals_type), POINTER                   :: region_sections
     873              :       TYPE(qmmm_env_type), POINTER                       :: qmmm_env
     874              :       INTEGER, DIMENSION(:), POINTER                     :: thermolist
     875              :       TYPE(molecule_type), DIMENSION(:), POINTER         :: molecule_set
     876              :       LOGICAL, INTENT(IN)                                :: subsys_qm
     877              :       INTEGER, INTENT(IN)                                :: ig
     878              :       INTEGER, INTENT(INOUT)                             :: sum_of_thermostats, nregions
     879              : 
     880              :       CHARACTER(LEN=default_string_length)               :: label1, label2
     881              :       INTEGER                                            :: first_atom, i, imolecule, ipart, &
     882              :                                                             last_atom, nrep, thermo1
     883          140 :       INTEGER, DIMENSION(:), POINTER                     :: atom_index1
     884              :       LOGICAL                                            :: explicit
     885              :       TYPE(molecule_type), POINTER                       :: molecule
     886              : 
     887          140 :       label1 = "MM_SUBSYS"
     888          140 :       label2 = "QM_SUBSYS"
     889          140 :       IF (subsys_qm) THEN
     890           70 :          label1 = "QM_SUBSYS"
     891           70 :          label2 = "MM_SUBSYS"
     892              :       END IF
     893              :       CALL section_vals_val_get(region_sections, TRIM(label1), i_rep_section=ig, &
     894          140 :                                 n_rep_val=nrep, explicit=explicit)
     895          140 :       IF (nrep == 1 .AND. explicit) THEN
     896            8 :          IF (ASSOCIATED(qmmm_env)) THEN
     897            8 :             atom_index1 => qmmm_env%qm%mm_atom_index
     898            8 :             IF (subsys_qm) THEN
     899            4 :                atom_index1 => qmmm_env%qm%qm_atom_index
     900              :             END IF
     901            8 :             CALL section_vals_val_get(region_sections, TRIM(label1), i_val=thermo1, i_rep_section=ig)
     902            4 :             SELECT CASE (thermo1)
     903              :             CASE (do_constr_atomic)
     904        13820 :                DO i = 1, SIZE(atom_index1)
     905        13816 :                   ipart = atom_index1(i)
     906        13816 :                   IF (subsys_qm .AND. qmmm_env%qm%qmmm_link .AND. ASSOCIATED(qmmm_env%qm%mm_link_atoms)) THEN
     907           46 :                      IF (ANY(ipart == qmmm_env%qm%mm_link_atoms)) CYCLE
     908              :                   END IF
     909        13818 :                   IF (thermolist(ipart) == HUGE(0)) THEN
     910        13814 :                      thermolist(ipart) = ig
     911              :                   ELSE
     912              :                      CALL cp_abort(__LOCATION__, &
     913              :                                    'One atom ('//cp_to_string(ipart)//') of the '// &
     914              :                                    TRIM(label1)//' was already assigned to'// &
     915              :                                    ' the thermostatting region Nr.'//cp_to_string(thermolist(ipart))// &
     916            0 :                                    '. Please check the input for inconsistencies!')
     917              :                   END IF
     918              :                END DO
     919              :             CASE (do_constr_molec)
     920         9168 :                DO imolecule = 1, SIZE(molecule_set)
     921         9160 :                   molecule => molecule_set(imolecule)
     922         9160 :                   CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     923     15908454 :                   IF (ANY(atom_index1 >= first_atom .AND. atom_index1 <= last_atom)) THEN
     924        18436 :                      DO ipart = first_atom, last_atom
     925        18436 :                         IF (thermolist(ipart) == HUGE(0)) THEN
     926        13854 :                            thermolist(ipart) = ig
     927              :                         ELSE
     928              :                            CALL cp_abort(__LOCATION__, &
     929              :                                          'One atom ('//cp_to_string(ipart)//') of the '// &
     930              :                                          TRIM(label1)//' was already assigned to'// &
     931              :                                          ' the thermostatting region Nr.'//cp_to_string(thermolist(ipart))// &
     932            0 :                                          '. Please check the input for inconsistencies!')
     933              :                         END IF
     934              :                      END DO
     935              :                   END IF
     936              :                END DO
     937              :             END SELECT
     938              :          ELSE
     939            0 :             sum_of_thermostats = sum_of_thermostats - 1
     940            0 :             nregions = nregions - 1
     941              :          END IF
     942              :       END IF
     943          140 :    END SUBROUTINE setup_thermostat_subsys
     944              : 
     945              : ! **************************************************************************************************
     946              : !> \brief ...
     947              : !> \param map_info ...
     948              : !> \param npt ...
     949              : !> \param group ...
     950              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
     951              : ! **************************************************************************************************
     952         5444 :    SUBROUTINE ke_region_baro(map_info, npt, group)
     953              :       TYPE(map_info_type), POINTER                       :: map_info
     954              :       TYPE(npt_info_type), DIMENSION(:, :), &
     955              :          INTENT(INOUT)                                   :: npt
     956              :       TYPE(mp_comm_type), INTENT(IN)                     :: group
     957              : 
     958              :       INTEGER                                            :: i, j, ncoef
     959              : 
     960        10888 :       map_info%v_scale = 1.0_dp
     961        10888 :       map_info%s_kin = 0.0_dp
     962         5444 :       ncoef = 0
     963        13672 :       DO i = 1, SIZE(npt, 1)
     964        30252 :          DO j = 1, SIZE(npt, 2)
     965        16580 :             ncoef = ncoef + 1
     966              :             map_info%p_kin(1, ncoef)%point = map_info%p_kin(1, ncoef)%point &
     967        24808 :                                              + npt(i, j)%mass*npt(i, j)%v**2
     968              :          END DO
     969              :       END DO
     970              : 
     971         5444 :       IF (map_info%dis_type == do_thermo_communication) CALL group%sum(map_info%s_kin)
     972              : 
     973         5444 :    END SUBROUTINE ke_region_baro
     974              : 
     975              : ! **************************************************************************************************
     976              : !> \brief ...
     977              : !> \param map_info ...
     978              : !> \param npt ...
     979              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
     980              : ! **************************************************************************************************
     981         4360 :    SUBROUTINE vel_rescale_baro(map_info, npt)
     982              :       TYPE(map_info_type), POINTER                       :: map_info
     983              :       TYPE(npt_info_type), DIMENSION(:, :), &
     984              :          INTENT(INOUT)                                   :: npt
     985              : 
     986              :       INTEGER                                            :: i, j, ncoef
     987              : 
     988         4360 :       ncoef = 0
     989        11344 :       DO i = 1, SIZE(npt, 1)
     990        26200 :          DO j = 1, SIZE(npt, 2)
     991        14856 :             ncoef = ncoef + 1
     992        21840 :             npt(i, j)%v = npt(i, j)%v*map_info%p_scale(1, ncoef)%point
     993              :          END DO
     994              :       END DO
     995              : 
     996         4360 :    END SUBROUTINE vel_rescale_baro
     997              : 
     998              : ! **************************************************************************************************
     999              : !> \brief ...
    1000              : !> \param map_info ...
    1001              : !> \param particle_set ...
    1002              : !> \param molecule_kind_set ...
    1003              : !> \param local_molecules ...
    1004              : !> \param molecule_set ...
    1005              : !> \param group ...
    1006              : !> \param vel ...
    1007              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
    1008              : ! **************************************************************************************************
    1009        25708 :    SUBROUTINE ke_region_particles(map_info, particle_set, molecule_kind_set, &
    1010        25708 :                                   local_molecules, molecule_set, group, vel)
    1011              : 
    1012              :       TYPE(map_info_type), POINTER                       :: map_info
    1013              :       TYPE(particle_type), POINTER                       :: particle_set(:)
    1014              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
    1015              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
    1016              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
    1017              :       TYPE(mp_comm_type), INTENT(IN)                     :: group
    1018              :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: vel(:, :)
    1019              : 
    1020              :       INTEGER                                            :: first_atom, ii, ikind, imol, imol_local, &
    1021              :                                                             ipart, last_atom, nmol_local
    1022              :       LOGICAL                                            :: present_vel
    1023              :       REAL(KIND=dp)                                      :: mass
    1024              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1025              :       TYPE(molecule_type), POINTER                       :: molecule
    1026              : 
    1027      1553576 :       map_info%v_scale = 1.0_dp
    1028      1553576 :       map_info%s_kin = 0.0_dp
    1029        25708 :       present_vel = PRESENT(vel)
    1030        25708 :       ii = 0
    1031      1271176 :       DO ikind = 1, SIZE(molecule_kind_set)
    1032      1245468 :          nmol_local = local_molecules%n_el(ikind)
    1033      2656966 :          DO imol_local = 1, nmol_local
    1034      1385790 :             imol = local_molecules%list(ikind)%array(imol_local)
    1035      1385790 :             molecule => molecule_set(imol)
    1036      1385790 :             CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
    1037      5677896 :             DO ipart = first_atom, last_atom
    1038      3046638 :                ii = ii + 1
    1039      3046638 :                atomic_kind => particle_set(ipart)%atomic_kind
    1040      3046638 :                CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
    1041      4432428 :                IF (present_vel) THEN
    1042      1523319 :                   IF (ASSOCIATED(map_info%p_kin(1, ii)%point)) &
    1043      1523319 :                      map_info%p_kin(1, ii)%point = map_info%p_kin(1, ii)%point + mass*vel(1, ipart)**2
    1044      1523319 :                   IF (ASSOCIATED(map_info%p_kin(2, ii)%point)) &
    1045      1523319 :                      map_info%p_kin(2, ii)%point = map_info%p_kin(2, ii)%point + mass*vel(2, ipart)**2
    1046      1523319 :                   IF (ASSOCIATED(map_info%p_kin(3, ii)%point)) &
    1047      1523319 :                      map_info%p_kin(3, ii)%point = map_info%p_kin(3, ii)%point + mass*vel(3, ipart)**2
    1048              :                ELSE
    1049      1523319 :                   IF (ASSOCIATED(map_info%p_kin(1, ii)%point)) &
    1050      1523319 :                      map_info%p_kin(1, ii)%point = map_info%p_kin(1, ii)%point + mass*particle_set(ipart)%v(1)**2
    1051      1523319 :                   IF (ASSOCIATED(map_info%p_kin(2, ii)%point)) &
    1052      1523319 :                      map_info%p_kin(2, ii)%point = map_info%p_kin(2, ii)%point + mass*particle_set(ipart)%v(2)**2
    1053      1523319 :                   IF (ASSOCIATED(map_info%p_kin(3, ii)%point)) &
    1054      1523319 :                      map_info%p_kin(3, ii)%point = map_info%p_kin(3, ii)%point + mass*particle_set(ipart)%v(3)**2
    1055              :                END IF
    1056              :             END DO
    1057              :          END DO
    1058              :       END DO
    1059              : 
    1060        62732 :       IF (map_info%dis_type == do_thermo_communication) CALL group%sum(map_info%s_kin)
    1061              : 
    1062        25708 :    END SUBROUTINE ke_region_particles
    1063              : 
    1064              : ! **************************************************************************************************
    1065              : !> \brief ...
    1066              : !> \param map_info ...
    1067              : !> \param particle_set ...
    1068              : !> \param molecule_kind_set ...
    1069              : !> \param local_molecules ...
    1070              : !> \param molecule_set ...
    1071              : !> \param group ...
    1072              : !> \param vel ...
    1073              : !> \author 07.2009 MI
    1074              : ! **************************************************************************************************
    1075          800 :    SUBROUTINE momentum_region_particles(map_info, particle_set, molecule_kind_set, &
    1076          800 :                                         local_molecules, molecule_set, group, vel)
    1077              : 
    1078              :       TYPE(map_info_type), POINTER                       :: map_info
    1079              :       TYPE(particle_type), POINTER                       :: particle_set(:)
    1080              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
    1081              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
    1082              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
    1083              :       TYPE(mp_comm_type), INTENT(IN)                     :: group
    1084              :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: vel(:, :)
    1085              : 
    1086              :       INTEGER                                            :: first_atom, ii, ikind, imol, imol_local, &
    1087              :                                                             ipart, last_atom, nmol_local
    1088              :       LOGICAL                                            :: present_vel
    1089              :       REAL(KIND=dp)                                      :: mass
    1090              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1091              :       TYPE(molecule_type), POINTER                       :: molecule
    1092              : 
    1093       130400 :       map_info%v_scale = 1.0_dp
    1094       130400 :       map_info%s_kin = 0.0_dp
    1095          800 :       present_vel = PRESENT(vel)
    1096          800 :       ii = 0
    1097        87200 :       DO ikind = 1, SIZE(molecule_kind_set)
    1098        86400 :          nmol_local = local_molecules%n_el(ikind)
    1099       130400 :          DO imol_local = 1, nmol_local
    1100        43200 :             imol = local_molecules%list(ikind)%array(imol_local)
    1101        43200 :             molecule => molecule_set(imol)
    1102        43200 :             CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
    1103       172800 :             DO ipart = first_atom, last_atom
    1104        43200 :                ii = ii + 1
    1105        43200 :                atomic_kind => particle_set(ipart)%atomic_kind
    1106        43200 :                CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
    1107        86400 :                IF (present_vel) THEN
    1108        21600 :                   map_info%p_kin(1, ii)%point = map_info%p_kin(1, ii)%point + SQRT(mass)*vel(1, ipart)
    1109        21600 :                   map_info%p_kin(2, ii)%point = map_info%p_kin(2, ii)%point + SQRT(mass)*vel(2, ipart)
    1110        21600 :                   map_info%p_kin(3, ii)%point = map_info%p_kin(3, ii)%point + SQRT(mass)*vel(3, ipart)
    1111              :                ELSE
    1112        21600 :                   map_info%p_kin(1, ii)%point = map_info%p_kin(1, ii)%point + SQRT(mass)*particle_set(ipart)%v(1)
    1113        21600 :                   map_info%p_kin(2, ii)%point = map_info%p_kin(2, ii)%point + SQRT(mass)*particle_set(ipart)%v(2)
    1114        21600 :                   map_info%p_kin(3, ii)%point = map_info%p_kin(3, ii)%point + SQRT(mass)*particle_set(ipart)%v(3)
    1115              :                END IF
    1116              :             END DO
    1117              :          END DO
    1118              :       END DO
    1119              : 
    1120          800 :       IF (map_info%dis_type == do_thermo_communication) CALL group%sum(map_info%s_kin)
    1121              : 
    1122          800 :    END SUBROUTINE momentum_region_particles
    1123              : 
    1124              : ! **************************************************************************************************
    1125              : !> \brief ...
    1126              : !> \param map_info ...
    1127              : !> \param molecule_kind_set ...
    1128              : !> \param molecule_set ...
    1129              : !> \param particle_set ...
    1130              : !> \param local_molecules ...
    1131              : !> \param shell_adiabatic ...
    1132              : !> \param shell_particle_set ...
    1133              : !> \param core_particle_set ...
    1134              : !> \param vel ...
    1135              : !> \param shell_vel ...
    1136              : !> \param core_vel ...
    1137              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
    1138              : ! **************************************************************************************************
    1139        19480 :    SUBROUTINE vel_rescale_particles(map_info, molecule_kind_set, molecule_set, &
    1140              :                                     particle_set, local_molecules, shell_adiabatic, shell_particle_set, &
    1141        19480 :                                     core_particle_set, vel, shell_vel, core_vel)
    1142              : 
    1143              :       TYPE(map_info_type), POINTER                       :: map_info
    1144              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
    1145              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
    1146              :       TYPE(particle_type), POINTER                       :: particle_set(:)
    1147              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
    1148              :       LOGICAL, INTENT(IN)                                :: shell_adiabatic
    1149              :       TYPE(particle_type), OPTIONAL, POINTER             :: shell_particle_set(:), &
    1150              :                                                             core_particle_set(:)
    1151              :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: vel(:, :), shell_vel(:, :), &
    1152              :                                                             core_vel(:, :)
    1153              : 
    1154              :       INTEGER                                            :: first_atom, ii, ikind, imol, imol_local, &
    1155              :                                                             ipart, jj, last_atom, nmol_local, &
    1156              :                                                             shell_index
    1157              :       LOGICAL                                            :: present_vel
    1158              :       REAL(KIND=dp)                                      :: fac_massc, fac_masss, mass, vc(3), vs(3)
    1159              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1160              :       TYPE(molecule_type), POINTER                       :: molecule
    1161              :       TYPE(shell_kind_type), POINTER                     :: shell
    1162              : 
    1163        19480 :       ii = 0
    1164        19480 :       jj = 0
    1165        19480 :       present_vel = PRESENT(vel)
    1166              :       ! Just few checks for consistency
    1167        19480 :       IF (present_vel) THEN
    1168         9740 :          IF (shell_adiabatic) THEN
    1169         1410 :             CPASSERT(PRESENT(shell_vel))
    1170         1410 :             CPASSERT(PRESENT(core_vel))
    1171              :          END IF
    1172              :       ELSE
    1173         9740 :          IF (shell_adiabatic) THEN
    1174         1410 :             CPASSERT(PRESENT(shell_particle_set))
    1175         1410 :             CPASSERT(PRESENT(core_particle_set))
    1176              :          END IF
    1177              :       END IF
    1178       826036 :       Kind: DO ikind = 1, SIZE(molecule_kind_set)
    1179       806556 :          nmol_local = local_molecules%n_el(ikind)
    1180      1733072 :          Mol_local: DO imol_local = 1, nmol_local
    1181       907036 :             imol = local_molecules%list(ikind)%array(imol_local)
    1182       907036 :             molecule => molecule_set(imol)
    1183       907036 :             CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
    1184      3697444 :             Particle: DO ipart = first_atom, last_atom
    1185      1983852 :                ii = ii + 1
    1186      1983852 :                IF (present_vel) THEN
    1187       991926 :                   vel(1, ipart) = vel(1, ipart)*map_info%p_scale(1, ii)%point
    1188       991926 :                   vel(2, ipart) = vel(2, ipart)*map_info%p_scale(2, ii)%point
    1189       991926 :                   vel(3, ipart) = vel(3, ipart)*map_info%p_scale(3, ii)%point
    1190              :                ELSE
    1191       991926 :                   particle_set(ipart)%v(1) = particle_set(ipart)%v(1)*map_info%p_scale(1, ii)%point
    1192       991926 :                   particle_set(ipart)%v(2) = particle_set(ipart)%v(2)*map_info%p_scale(2, ii)%point
    1193       991926 :                   particle_set(ipart)%v(3) = particle_set(ipart)%v(3)*map_info%p_scale(3, ii)%point
    1194              :                END IF
    1195              :                ! If Shell Adiabatic then apply the NHC thermostat also to the Shells
    1196      2890888 :                IF (shell_adiabatic) THEN
    1197       152160 :                   shell_index = particle_set(ipart)%shell_index
    1198       152160 :                   IF (shell_index /= 0) THEN
    1199       150880 :                      jj = jj + 2
    1200       150880 :                      atomic_kind => particle_set(ipart)%atomic_kind
    1201       150880 :                      CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass, shell=shell)
    1202       150880 :                      fac_masss = shell%mass_shell/mass
    1203       150880 :                      fac_massc = shell%mass_core/mass
    1204       150880 :                      IF (present_vel) THEN
    1205       301760 :                         vs(1:3) = shell_vel(1:3, shell_index)
    1206       301760 :                         vc(1:3) = core_vel(1:3, shell_index)
    1207        75440 :                         shell_vel(1, shell_index) = vel(1, ipart) + fac_massc*(vs(1) - vc(1))
    1208        75440 :                         shell_vel(2, shell_index) = vel(2, ipart) + fac_massc*(vs(2) - vc(2))
    1209        75440 :                         shell_vel(3, shell_index) = vel(3, ipart) + fac_massc*(vs(3) - vc(3))
    1210        75440 :                         core_vel(1, shell_index) = vel(1, ipart) + fac_masss*(vc(1) - vs(1))
    1211        75440 :                         core_vel(2, shell_index) = vel(2, ipart) + fac_masss*(vc(2) - vs(2))
    1212        75440 :                         core_vel(3, shell_index) = vel(3, ipart) + fac_masss*(vc(3) - vs(3))
    1213              :                      ELSE
    1214       301760 :                         vs(1:3) = shell_particle_set(shell_index)%v(1:3)
    1215       301760 :                         vc(1:3) = core_particle_set(shell_index)%v(1:3)
    1216        75440 :                         shell_particle_set(shell_index)%v(1) = particle_set(ipart)%v(1) + fac_massc*(vs(1) - vc(1))
    1217        75440 :                         shell_particle_set(shell_index)%v(2) = particle_set(ipart)%v(2) + fac_massc*(vs(2) - vc(2))
    1218        75440 :                         shell_particle_set(shell_index)%v(3) = particle_set(ipart)%v(3) + fac_massc*(vs(3) - vc(3))
    1219        75440 :                         core_particle_set(shell_index)%v(1) = particle_set(ipart)%v(1) + fac_masss*(vc(1) - vs(1))
    1220        75440 :                         core_particle_set(shell_index)%v(2) = particle_set(ipart)%v(2) + fac_masss*(vc(2) - vs(2))
    1221        75440 :                         core_particle_set(shell_index)%v(3) = particle_set(ipart)%v(3) + fac_masss*(vc(3) - vs(3))
    1222              :                      END IF
    1223              :                   END IF
    1224              :                END IF
    1225              :             END DO Particle
    1226              :          END DO Mol_local
    1227              :       END DO Kind
    1228              : 
    1229        19480 :    END SUBROUTINE vel_rescale_particles
    1230              : 
    1231              : ! **************************************************************************************************
    1232              : !> \brief ...
    1233              : !> \param map_info ...
    1234              : !> \param particle_set ...
    1235              : !> \param atomic_kind_set ...
    1236              : !> \param local_particles ...
    1237              : !> \param group ...
    1238              : !> \param core_particle_set ...
    1239              : !> \param shell_particle_set ...
    1240              : !> \param core_vel ...
    1241              : !> \param shell_vel ...
    1242              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
    1243              : ! **************************************************************************************************
    1244         1840 :    SUBROUTINE ke_region_shells(map_info, particle_set, atomic_kind_set, &
    1245              :                                local_particles, group, core_particle_set, shell_particle_set, &
    1246         1840 :                                core_vel, shell_vel)
    1247              : 
    1248              :       TYPE(map_info_type), POINTER                       :: map_info
    1249              :       TYPE(particle_type), POINTER                       :: particle_set(:)
    1250              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind_set(:)
    1251              :       TYPE(distribution_1d_type), POINTER                :: local_particles
    1252              :       TYPE(mp_comm_type), INTENT(IN)                     :: group
    1253              :       TYPE(particle_type), OPTIONAL, POINTER             :: core_particle_set(:), &
    1254              :                                                             shell_particle_set(:)
    1255              :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: core_vel(:, :), shell_vel(:, :)
    1256              : 
    1257              :       INTEGER                                            :: ii, iparticle, iparticle_kind, &
    1258              :                                                             iparticle_local, nparticle_kind, &
    1259              :                                                             nparticle_local, shell_index
    1260              :       LOGICAL                                            :: is_shell, present_vel
    1261              :       REAL(dp)                                           :: mass, mu_mass, v_sc(3)
    1262              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1263              :       TYPE(shell_kind_type), POINTER                     :: shell
    1264              : 
    1265         1840 :       present_vel = PRESENT(shell_vel)
    1266              :       ! Preliminary checks for consistency usage
    1267         1840 :       IF (present_vel) THEN
    1268          920 :          CPASSERT(PRESENT(core_vel))
    1269              :       ELSE
    1270          920 :          CPASSERT(PRESENT(shell_particle_set))
    1271          920 :          CPASSERT(PRESENT(core_particle_set))
    1272              :       END IF
    1273              :       ! get force on first thermostat for all the chains in the system.
    1274       154040 :       map_info%v_scale = 1.0_dp
    1275       154040 :       map_info%s_kin = 0.0_dp
    1276         1840 :       ii = 0
    1277              : 
    1278         1840 :       nparticle_kind = SIZE(atomic_kind_set)
    1279         5520 :       DO iparticle_kind = 1, nparticle_kind
    1280         3680 :          atomic_kind => atomic_kind_set(iparticle_kind)
    1281         3680 :          CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass, shell_active=is_shell, shell=shell)
    1282         5520 :          IF (is_shell) THEN
    1283         3680 :             mu_mass = shell%mass_shell*shell%mass_core/mass
    1284         3680 :             nparticle_local = local_particles%n_el(iparticle_kind)
    1285        92000 :             DO iparticle_local = 1, nparticle_local
    1286        88320 :                iparticle = local_particles%list(iparticle_kind)%array(iparticle_local)
    1287        88320 :                shell_index = particle_set(iparticle)%shell_index
    1288        88320 :                ii = ii + 1
    1289        92000 :                IF (present_vel) THEN
    1290        44160 :                   v_sc(1) = core_vel(1, shell_index) - shell_vel(1, shell_index)
    1291        44160 :                   v_sc(2) = core_vel(2, shell_index) - shell_vel(2, shell_index)
    1292        44160 :                   v_sc(3) = core_vel(3, shell_index) - shell_vel(3, shell_index)
    1293        44160 :                   map_info%p_kin(1, ii)%point = map_info%p_kin(1, ii)%point + mu_mass*v_sc(1)**2
    1294        44160 :                   map_info%p_kin(2, ii)%point = map_info%p_kin(2, ii)%point + mu_mass*v_sc(2)**2
    1295        44160 :                   map_info%p_kin(3, ii)%point = map_info%p_kin(3, ii)%point + mu_mass*v_sc(3)**2
    1296              :                ELSE
    1297        44160 :                   v_sc(1) = core_particle_set(shell_index)%v(1) - shell_particle_set(shell_index)%v(1)
    1298        44160 :                   v_sc(2) = core_particle_set(shell_index)%v(2) - shell_particle_set(shell_index)%v(2)
    1299        44160 :                   v_sc(3) = core_particle_set(shell_index)%v(3) - shell_particle_set(shell_index)%v(3)
    1300        44160 :                   map_info%p_kin(1, ii)%point = map_info%p_kin(1, ii)%point + mu_mass*v_sc(1)**2
    1301        44160 :                   map_info%p_kin(2, ii)%point = map_info%p_kin(2, ii)%point + mu_mass*v_sc(2)**2
    1302        44160 :                   map_info%p_kin(3, ii)%point = map_info%p_kin(3, ii)%point + mu_mass*v_sc(3)**2
    1303              :                END IF
    1304              :             END DO
    1305              :          END IF
    1306              :       END DO
    1307         2880 :       IF (map_info%dis_type == do_thermo_communication) CALL group%sum(map_info%s_kin)
    1308              : 
    1309         1840 :    END SUBROUTINE ke_region_shells
    1310              : 
    1311              : ! **************************************************************************************************
    1312              : !> \brief ...
    1313              : !> \param map_info ...
    1314              : !> \param atomic_kind_set ...
    1315              : !> \param particle_set ...
    1316              : !> \param local_particles ...
    1317              : !> \param shell_particle_set ...
    1318              : !> \param core_particle_set ...
    1319              : !> \param shell_vel ...
    1320              : !> \param core_vel ...
    1321              : !> \param vel ...
    1322              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
    1323              : ! **************************************************************************************************
    1324         1600 :    SUBROUTINE vel_rescale_shells(map_info, atomic_kind_set, particle_set, local_particles, &
    1325         1600 :                                  shell_particle_set, core_particle_set, shell_vel, core_vel, vel)
    1326              : 
    1327              :       TYPE(map_info_type), POINTER                       :: map_info
    1328              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind_set(:)
    1329              :       TYPE(particle_type), POINTER                       :: particle_set(:)
    1330              :       TYPE(distribution_1d_type), POINTER                :: local_particles
    1331              :       TYPE(particle_type), OPTIONAL, POINTER             :: shell_particle_set(:), &
    1332              :                                                             core_particle_set(:)
    1333              :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: shell_vel(:, :), core_vel(:, :), &
    1334              :                                                             vel(:, :)
    1335              : 
    1336              :       INTEGER                                            :: ii, iparticle, iparticle_kind, &
    1337              :                                                             iparticle_local, nparticle_kind, &
    1338              :                                                             nparticle_local, shell_index
    1339              :       LOGICAL                                            :: is_shell, present_vel
    1340              :       REAL(dp)                                           :: mass, massc, masss, umass, v(3), vc(3), &
    1341              :                                                             vs(3)
    1342              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1343              :       TYPE(shell_kind_type), POINTER                     :: shell
    1344              : 
    1345         1600 :       present_vel = PRESENT(vel)
    1346              :       ! Preliminary checks for consistency usage
    1347         1600 :       IF (present_vel) THEN
    1348          800 :          CPASSERT(PRESENT(shell_vel))
    1349          800 :          CPASSERT(PRESENT(core_vel))
    1350              :       ELSE
    1351          800 :          CPASSERT(PRESENT(shell_particle_set))
    1352          800 :          CPASSERT(PRESENT(core_particle_set))
    1353              :       END IF
    1354         1600 :       ii = 0
    1355         1600 :       nparticle_kind = SIZE(atomic_kind_set)
    1356              :       ! now scale the core-shell velocities
    1357         4800 :       Kind: DO iparticle_kind = 1, nparticle_kind
    1358         3200 :          atomic_kind => atomic_kind_set(iparticle_kind)
    1359         3200 :          CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass, shell_active=is_shell, shell=shell)
    1360         4800 :          IF (is_shell) THEN
    1361         3200 :             umass = 1.0_dp/mass
    1362         3200 :             masss = shell%mass_shell*umass
    1363         3200 :             massc = shell%mass_core*umass
    1364              : 
    1365         3200 :             nparticle_local = local_particles%n_el(iparticle_kind)
    1366        80000 :             Particles: DO iparticle_local = 1, nparticle_local
    1367        76800 :                iparticle = local_particles%list(iparticle_kind)%array(iparticle_local)
    1368        76800 :                shell_index = particle_set(iparticle)%shell_index
    1369        76800 :                ii = ii + 1
    1370        80000 :                IF (present_vel) THEN
    1371       153600 :                   vc(1:3) = core_vel(1:3, shell_index)
    1372       153600 :                   vs(1:3) = shell_vel(1:3, shell_index)
    1373       153600 :                   v(1:3) = vel(1:3, iparticle)
    1374        38400 :                   shell_vel(1, shell_index) = v(1) + map_info%p_scale(1, ii)%point*massc*(vs(1) - vc(1))
    1375        38400 :                   shell_vel(2, shell_index) = v(2) + map_info%p_scale(2, ii)%point*massc*(vs(2) - vc(2))
    1376        38400 :                   shell_vel(3, shell_index) = v(3) + map_info%p_scale(3, ii)%point*massc*(vs(3) - vc(3))
    1377        38400 :                   core_vel(1, shell_index) = v(1) + map_info%p_scale(1, ii)%point*masss*(vc(1) - vs(1))
    1378        38400 :                   core_vel(2, shell_index) = v(2) + map_info%p_scale(2, ii)%point*masss*(vc(2) - vs(2))
    1379        38400 :                   core_vel(3, shell_index) = v(3) + map_info%p_scale(3, ii)%point*masss*(vc(3) - vs(3))
    1380              :                ELSE
    1381       153600 :                   vc(1:3) = core_particle_set(shell_index)%v(1:3)
    1382       153600 :                   vs(1:3) = shell_particle_set(shell_index)%v(1:3)
    1383       153600 :                   v(1:3) = particle_set(iparticle)%v(1:3)
    1384        38400 :                   shell_particle_set(shell_index)%v(1) = v(1) + map_info%p_scale(1, ii)%point*massc*(vs(1) - vc(1))
    1385        38400 :                   shell_particle_set(shell_index)%v(2) = v(2) + map_info%p_scale(2, ii)%point*massc*(vs(2) - vc(2))
    1386        38400 :                   shell_particle_set(shell_index)%v(3) = v(3) + map_info%p_scale(3, ii)%point*massc*(vs(3) - vc(3))
    1387        38400 :                   core_particle_set(shell_index)%v(1) = v(1) + map_info%p_scale(1, ii)%point*masss*(vc(1) - vs(1))
    1388        38400 :                   core_particle_set(shell_index)%v(2) = v(2) + map_info%p_scale(2, ii)%point*masss*(vc(2) - vs(2))
    1389        38400 :                   core_particle_set(shell_index)%v(3) = v(3) + map_info%p_scale(3, ii)%point*masss*(vc(3) - vs(3))
    1390              :                END IF
    1391              :             END DO Particles
    1392              :          END IF
    1393              :       END DO Kind
    1394              : 
    1395         1600 :    END SUBROUTINE vel_rescale_shells
    1396              : 
    1397              : ! **************************************************************************************************
    1398              : !> \brief Calculates kinetic energy and potential energy of the nhc variables
    1399              : !> \param nhc ...
    1400              : !> \param nhc_pot ...
    1401              : !> \param nhc_kin ...
    1402              : !> \param para_env ...
    1403              : !> \param array_kin ...
    1404              : !> \param array_pot ...
    1405              : !> \par History
    1406              : !>      none
    1407              : !> \author CJM
    1408              : ! **************************************************************************************************
    1409        10668 :    SUBROUTINE get_nhc_energies(nhc, nhc_pot, nhc_kin, para_env, array_kin, array_pot)
    1410              :       TYPE(lnhc_parameters_type), POINTER                :: nhc
    1411              :       REAL(KIND=dp), INTENT(OUT)                         :: nhc_pot, nhc_kin
    1412              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1413              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: array_kin, array_pot
    1414              : 
    1415              :       INTEGER                                            :: imap, l, n, number
    1416              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: akin, vpot
    1417              : 
    1418        10668 :       number = nhc%glob_num_nhc
    1419        32004 :       ALLOCATE (akin(number))
    1420        32004 :       ALLOCATE (vpot(number))
    1421       774122 :       akin = 0.0_dp
    1422       774122 :       vpot = 0.0_dp
    1423       395929 :       DO n = 1, nhc%loc_num_nhc
    1424       385261 :          imap = nhc%map_info%index(n)
    1425      1796878 :          DO l = 1, nhc%nhc_len
    1426      1400949 :             akin(imap) = akin(imap) + 0.5_dp*nhc%nvt(l, n)%mass*nhc%nvt(l, n)%v**2
    1427      1786210 :             vpot(imap) = vpot(imap) + nhc%nvt(l, n)%nkt*nhc%nvt(l, n)%eta
    1428              :          END DO
    1429              :       END DO
    1430              : 
    1431              :       ! Handle the thermostat distribution
    1432        10668 :       IF (nhc%map_info%dis_type == do_thermo_no_communication) THEN
    1433         3726 :          CALL para_env%sum(akin)
    1434         3726 :          CALL para_env%sum(vpot)
    1435         6942 :       ELSE IF (nhc%map_info%dis_type == do_thermo_communication) THEN
    1436         4958 :          CALL communication_thermo_low1(akin, number, para_env)
    1437         4958 :          CALL communication_thermo_low1(vpot, number, para_env)
    1438              :       END IF
    1439       774122 :       nhc_kin = SUM(akin)
    1440       774122 :       nhc_pot = SUM(vpot)
    1441              : 
    1442              :       ! Possibly give back kinetic or potential energy arrays
    1443        10668 :       IF (PRESENT(array_pot)) THEN
    1444          274 :          IF (ASSOCIATED(array_pot)) THEN
    1445            0 :             CPASSERT(SIZE(array_pot) == number)
    1446              :          ELSE
    1447          822 :             ALLOCATE (array_pot(number))
    1448              :          END IF
    1449        35794 :          array_pot = vpot
    1450              :       END IF
    1451        10668 :       IF (PRESENT(array_kin)) THEN
    1452          274 :          IF (ASSOCIATED(array_kin)) THEN
    1453            0 :             CPASSERT(SIZE(array_kin) == number)
    1454              :          ELSE
    1455          822 :             ALLOCATE (array_kin(number))
    1456              :          END IF
    1457        35794 :          array_kin = akin
    1458              :       END IF
    1459        10668 :       DEALLOCATE (akin)
    1460        10668 :       DEALLOCATE (vpot)
    1461        10668 :    END SUBROUTINE get_nhc_energies
    1462              : 
    1463              : ! **************************************************************************************************
    1464              : !> \brief Calculates kinetic energy and potential energy
    1465              : !>      of the csvr  and gle thermostats
    1466              : !> \param map_info ...
    1467              : !> \param loc_num ...
    1468              : !> \param glob_num ...
    1469              : !> \param thermo_energy ...
    1470              : !> \param thermostat_kin ...
    1471              : !> \param para_env ...
    1472              : !> \param array_pot ...
    1473              : !> \param array_kin ...
    1474              : !> \par History generalized MI [07.2009]
    1475              : !> \author Teodoro Laino [tlaino] - 10.2007 - University of Zurich
    1476              : ! **************************************************************************************************
    1477         4532 :    SUBROUTINE get_kin_energies(map_info, loc_num, glob_num, thermo_energy, thermostat_kin, &
    1478              :                                para_env, array_pot, array_kin)
    1479              : 
    1480              :       TYPE(map_info_type), POINTER                       :: map_info
    1481              :       INTEGER, INTENT(IN)                                :: loc_num, glob_num
    1482              :       REAL(dp), DIMENSION(:), INTENT(IN)                 :: thermo_energy
    1483              :       REAL(KIND=dp), INTENT(OUT)                         :: thermostat_kin
    1484              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1485              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: array_pot, array_kin
    1486              : 
    1487              :       INTEGER                                            :: imap, n, number
    1488              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: akin
    1489              : 
    1490         4532 :       number = glob_num
    1491        13596 :       ALLOCATE (akin(number))
    1492       278686 :       akin = 0.0_dp
    1493       143368 :       DO n = 1, loc_num
    1494       138836 :          imap = map_info%index(n)
    1495       143368 :          akin(imap) = thermo_energy(n)
    1496              :       END DO
    1497              : 
    1498              :       ! Handle the thermostat distribution
    1499         4532 :       IF (map_info%dis_type == do_thermo_no_communication) THEN
    1500         1306 :          CALL para_env%sum(akin)
    1501         3226 :       ELSE IF (map_info%dis_type == do_thermo_communication) THEN
    1502         2538 :          CALL communication_thermo_low1(akin, number, para_env)
    1503              :       END IF
    1504       278686 :       thermostat_kin = SUM(akin)
    1505              : 
    1506              :       ! Possibly give back kinetic or potential energy arrays
    1507         4532 :       IF (PRESENT(array_pot)) THEN
    1508           22 :          IF (ASSOCIATED(array_pot)) THEN
    1509            0 :             CPASSERT(SIZE(array_pot) == number)
    1510              :          ELSE
    1511           66 :             ALLOCATE (array_pot(number))
    1512              :          END IF
    1513           66 :          array_pot = 0.0_dp
    1514              :       END IF
    1515         4532 :       IF (PRESENT(array_kin)) THEN
    1516          440 :          IF (ASSOCIATED(array_kin)) THEN
    1517          418 :             CPASSERT(SIZE(array_kin) == number)
    1518              :          ELSE
    1519           66 :             ALLOCATE (array_kin(number))
    1520              :          END IF
    1521        22856 :          array_kin = akin
    1522              :       END IF
    1523         4532 :       DEALLOCATE (akin)
    1524         4532 :    END SUBROUTINE get_kin_energies
    1525              : 
    1526              : ! **************************************************************************************************
    1527              : !> \brief Calculates the temperatures of the regions when a thermostat is
    1528              : !>        applied
    1529              : !> \param map_info ...
    1530              : !> \param loc_num ...
    1531              : !> \param glob_num ...
    1532              : !> \param nkt ...
    1533              : !> \param dof ...
    1534              : !> \param para_env ...
    1535              : !> \param temp_tot ...
    1536              : !> \param array_temp ...
    1537              : !> \par History generalized MI [07.2009]
    1538              : !> \author Teodoro Laino [tlaino] - 10.2007 - University of Zurich
    1539              : ! **************************************************************************************************
    1540          274 :    SUBROUTINE get_temperatures(map_info, loc_num, glob_num, nkt, dof, para_env, &
    1541              :                                temp_tot, array_temp)
    1542              :       TYPE(map_info_type), POINTER                       :: map_info
    1543              :       INTEGER, INTENT(IN)                                :: loc_num, glob_num
    1544              :       REAL(dp), DIMENSION(:), INTENT(IN)                 :: nkt, dof
    1545              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1546              :       REAL(KIND=dp), INTENT(OUT)                         :: temp_tot
    1547              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: array_temp
    1548              : 
    1549              :       INTEGER                                            :: i, imap, imap2, n, number
    1550              :       REAL(KIND=dp)                                      :: fdeg_of_free
    1551              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: akin, deg_of_free
    1552              : 
    1553          274 :       number = glob_num
    1554          822 :       ALLOCATE (akin(number))
    1555          822 :       ALLOCATE (deg_of_free(number))
    1556        35816 :       akin = 0.0_dp
    1557        35816 :       deg_of_free = 0.0_dp
    1558        18120 :       DO n = 1, loc_num
    1559        17846 :          imap = map_info%index(n)
    1560        17846 :          imap2 = map_info%map_index(n)
    1561        17846 :          IF (nkt(n) == 0.0_dp) CYCLE
    1562        17846 :          deg_of_free(imap) = REAL(dof(n), KIND=dp)
    1563        18120 :          akin(imap) = map_info%s_kin(imap2)
    1564              :       END DO
    1565              : 
    1566              :       ! Handle the thermostat distribution
    1567          274 :       IF (map_info%dis_type == do_thermo_no_communication) THEN
    1568          146 :          CALL para_env%sum(akin)
    1569          146 :          CALL para_env%sum(deg_of_free)
    1570          128 :       ELSE IF (map_info%dis_type == do_thermo_communication) THEN
    1571           22 :          CALL communication_thermo_low1(akin, number, para_env)
    1572           22 :          CALL communication_thermo_low1(deg_of_free, number, para_env)
    1573              :       END IF
    1574        35816 :       temp_tot = SUM(akin)
    1575        35816 :       fdeg_of_free = SUM(deg_of_free)
    1576              : 
    1577          274 :       temp_tot = temp_tot/fdeg_of_free
    1578          274 :       temp_tot = cp_unit_from_cp2k(temp_tot, "K_temp")
    1579              :       ! Possibly give back temperatures of the full set of regions
    1580          274 :       IF (PRESENT(array_temp)) THEN
    1581          274 :          IF (ASSOCIATED(array_temp)) THEN
    1582            0 :             CPASSERT(SIZE(array_temp) == number)
    1583              :          ELSE
    1584          822 :             ALLOCATE (array_temp(number))
    1585              :          END IF
    1586        35816 :          DO i = 1, number
    1587        35542 :             array_temp(i) = akin(i)/deg_of_free(i)
    1588        35816 :             array_temp(i) = cp_unit_from_cp2k(array_temp(i), "K_temp")
    1589              :          END DO
    1590              :       END IF
    1591          274 :       DEALLOCATE (akin)
    1592          274 :       DEALLOCATE (deg_of_free)
    1593          274 :    END SUBROUTINE get_temperatures
    1594              : 
    1595              : ! **************************************************************************************************
    1596              : !> \brief Calculates energy associated with a thermostat
    1597              : !> \param thermostat ...
    1598              : !> \param thermostat_pot ...
    1599              : !> \param thermostat_kin ...
    1600              : !> \param para_env ...
    1601              : !> \param array_pot ...
    1602              : !> \param array_kin ...
    1603              : !> \author Teodoro Laino [tlaino] - 10.2007 - University of Zurich
    1604              : ! **************************************************************************************************
    1605        55327 :    SUBROUTINE get_thermostat_energies(thermostat, thermostat_pot, thermostat_kin, para_env, &
    1606              :                                       array_pot, array_kin)
    1607              :       TYPE(thermostat_type), POINTER                     :: thermostat
    1608              :       REAL(KIND=dp), INTENT(OUT)                         :: thermostat_pot, thermostat_kin
    1609              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1610              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: array_pot, array_kin
    1611              : 
    1612              :       INTEGER                                            :: i
    1613        55327 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: thermo_energy
    1614              : 
    1615        55327 :       thermostat_pot = 0.0_dp
    1616        55327 :       thermostat_kin = 0.0_dp
    1617        55327 :       IF (ASSOCIATED(thermostat)) THEN
    1618        14468 :          IF (thermostat%type_of_thermostat == do_thermo_nose) THEN
    1619              :             ! Energy associated with the Nose-Hoover thermostat
    1620        10338 :             CPASSERT(ASSOCIATED(thermostat%nhc))
    1621              :             CALL get_nhc_energies(thermostat%nhc, thermostat_pot, thermostat_kin, para_env, &
    1622        10338 :                                   array_pot, array_kin)
    1623         4130 :          ELSE IF (thermostat%type_of_thermostat == do_thermo_csvr) THEN
    1624              :             ! Energy associated with the CSVR thermostat
    1625         3706 :             CPASSERT(ASSOCIATED(thermostat%csvr))
    1626        11118 :             ALLOCATE (thermo_energy(thermostat%csvr%loc_num_csvr))
    1627        65108 :             DO i = 1, thermostat%csvr%loc_num_csvr
    1628        65108 :                thermo_energy(i) = thermostat%csvr%nvt(i)%thermostat_energy
    1629              :             END DO
    1630              :             CALL get_kin_energies(thermostat%csvr%map_info, thermostat%csvr%loc_num_csvr, &
    1631              :                                   thermostat%csvr%glob_num_csvr, thermo_energy, &
    1632         3706 :                                   thermostat_kin, para_env, array_pot, array_kin)
    1633         3706 :             DEALLOCATE (thermo_energy)
    1634              : 
    1635          424 :          ELSE IF (thermostat%type_of_thermostat == do_thermo_gle) THEN
    1636              :             ! Energy associated with the GLE thermostat
    1637          408 :             CPASSERT(ASSOCIATED(thermostat%gle))
    1638         1224 :             ALLOCATE (thermo_energy(thermostat%gle%loc_num_gle))
    1639        66504 :             DO i = 1, thermostat%gle%loc_num_gle
    1640        66504 :                thermo_energy(i) = thermostat%gle%nvt(i)%thermostat_energy
    1641              :             END DO
    1642              :             CALL get_kin_energies(thermostat%gle%map_info, thermostat%gle%loc_num_gle, &
    1643              :                                   thermostat%gle%glob_num_gle, thermo_energy, &
    1644          408 :                                   thermostat_kin, para_env, array_pot, array_kin)
    1645          408 :             DEALLOCATE (thermo_energy)
    1646              : 
    1647              :             ![NB] nothing to do for Ad-Langevin?
    1648              : 
    1649              :          END IF
    1650              :       END IF
    1651              : 
    1652        55327 :    END SUBROUTINE get_thermostat_energies
    1653              : 
    1654              : ! **************************************************************************************************
    1655              : !> \brief Calculates the temperatures for each region associated to a thermostat
    1656              : !> \param thermostat ...
    1657              : !> \param tot_temperature ...
    1658              : !> \param para_env ...
    1659              : !> \param array_temp ...
    1660              : !> \author Teodoro Laino [tlaino] - 02.2008 - University of Zurich
    1661              : ! **************************************************************************************************
    1662          274 :    SUBROUTINE get_region_temperatures(thermostat, tot_temperature, para_env, array_temp)
    1663              :       TYPE(thermostat_type), POINTER                     :: thermostat
    1664              :       REAL(KIND=dp), INTENT(OUT)                         :: tot_temperature
    1665              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1666              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: array_temp
    1667              : 
    1668              :       INTEGER                                            :: i
    1669          274 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: dof, nkt
    1670              : 
    1671          274 :       IF (ASSOCIATED(thermostat)) THEN
    1672          274 :          IF (thermostat%type_of_thermostat == do_thermo_nose) THEN
    1673              :             ! Energy associated with the Nose-Hoover thermostat
    1674          252 :             CPASSERT(ASSOCIATED(thermostat%nhc))
    1675          756 :             ALLOCATE (nkt(thermostat%nhc%loc_num_nhc))
    1676          756 :             ALLOCATE (dof(thermostat%nhc%loc_num_nhc))
    1677        18054 :             DO i = 1, thermostat%nhc%loc_num_nhc
    1678        17802 :                nkt(i) = thermostat%nhc%nvt(1, i)%nkt
    1679        18054 :                dof(i) = REAL(thermostat%nhc%nvt(1, i)%degrees_of_freedom, KIND=dp)
    1680              :             END DO
    1681              :             CALL get_temperatures(thermostat%nhc%map_info, thermostat%nhc%loc_num_nhc, &
    1682          252 :                                   thermostat%nhc%glob_num_nhc, nkt, dof, para_env, tot_temperature, array_temp)
    1683          252 :             DEALLOCATE (nkt)
    1684          252 :             DEALLOCATE (dof)
    1685           22 :          ELSE IF (thermostat%type_of_thermostat == do_thermo_csvr) THEN
    1686              :             ! Energy associated with the CSVR thermostat
    1687           22 :             CPASSERT(ASSOCIATED(thermostat%csvr))
    1688              : 
    1689           66 :             ALLOCATE (nkt(thermostat%csvr%loc_num_csvr))
    1690           66 :             ALLOCATE (dof(thermostat%csvr%loc_num_csvr))
    1691           66 :             DO i = 1, thermostat%csvr%loc_num_csvr
    1692           44 :                nkt(i) = thermostat%csvr%nvt(i)%nkt
    1693           66 :                dof(i) = REAL(thermostat%csvr%nvt(i)%degrees_of_freedom, KIND=dp)
    1694              :             END DO
    1695              :             CALL get_temperatures(thermostat%csvr%map_info, thermostat%csvr%loc_num_csvr, &
    1696           22 :                                   thermostat%csvr%glob_num_csvr, nkt, dof, para_env, tot_temperature, array_temp)
    1697           22 :             DEALLOCATE (nkt)
    1698           22 :             DEALLOCATE (dof)
    1699            0 :          ELSE IF (thermostat%type_of_thermostat == do_thermo_al) THEN
    1700              :             ! Energy associated with the AD_LANGEVIN thermostat
    1701            0 :             CPASSERT(ASSOCIATED(thermostat%al))
    1702              : 
    1703            0 :             ALLOCATE (nkt(thermostat%al%loc_num_al))
    1704            0 :             ALLOCATE (dof(thermostat%al%loc_num_al))
    1705            0 :             DO i = 1, thermostat%al%loc_num_al
    1706            0 :                nkt(i) = thermostat%al%nvt(i)%nkt
    1707            0 :                dof(i) = REAL(thermostat%al%nvt(i)%degrees_of_freedom, KIND=dp)
    1708              :             END DO
    1709              :             CALL get_temperatures(thermostat%al%map_info, thermostat%al%loc_num_al, &
    1710            0 :                                   thermostat%al%glob_num_al, nkt, dof, para_env, tot_temperature, array_temp)
    1711            0 :             DEALLOCATE (nkt)
    1712            0 :             DEALLOCATE (dof)
    1713            0 :          ELSE IF (thermostat%type_of_thermostat == do_thermo_gle) THEN
    1714              :             ! Energy associated with the GLE thermostat
    1715            0 :             CPASSERT(ASSOCIATED(thermostat%gle))
    1716              : 
    1717            0 :             ALLOCATE (nkt(thermostat%gle%loc_num_gle))
    1718            0 :             ALLOCATE (dof(thermostat%gle%loc_num_gle))
    1719            0 :             DO i = 1, thermostat%gle%loc_num_gle
    1720            0 :                nkt(i) = thermostat%gle%nvt(i)%nkt
    1721            0 :                dof(i) = REAL(thermostat%gle%nvt(i)%degrees_of_freedom, KIND=dp)
    1722              :             END DO
    1723              :             CALL get_temperatures(thermostat%gle%map_info, thermostat%gle%loc_num_gle, &
    1724            0 :                                   thermostat%gle%glob_num_gle, nkt, dof, para_env, tot_temperature, array_temp)
    1725            0 :             DEALLOCATE (nkt)
    1726            0 :             DEALLOCATE (dof)
    1727              :          END IF
    1728              :       END IF
    1729              : 
    1730          274 :    END SUBROUTINE get_region_temperatures
    1731              : 
    1732              : ! **************************************************************************************************
    1733              : !> \brief Prints status of all thermostats during an MD run
    1734              : !> \param thermostats ...
    1735              : !> \param para_env ...
    1736              : !> \param my_pos ...
    1737              : !> \param my_act ...
    1738              : !> \param itimes ...
    1739              : !> \param time ...
    1740              : !> \author Teodoro Laino [tlaino] - 02.2008 - University of Zurich
    1741              : ! **************************************************************************************************
    1742        42149 :    SUBROUTINE print_thermostats_status(thermostats, para_env, my_pos, my_act, itimes, time)
    1743              :       TYPE(thermostats_type), POINTER                    :: thermostats
    1744              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1745              :       CHARACTER(LEN=default_string_length)               :: my_pos, my_act
    1746              :       INTEGER, INTENT(IN)                                :: itimes
    1747              :       REAL(KIND=dp), INTENT(IN)                          :: time
    1748              : 
    1749        42149 :       IF (ASSOCIATED(thermostats)) THEN
    1750        10480 :          IF (ASSOCIATED(thermostats%thermostat_part)) THEN
    1751        10146 :             CALL print_thermostat_status(thermostats%thermostat_part, para_env, my_pos, my_act, itimes, time)
    1752              :          END IF
    1753        10480 :          IF (ASSOCIATED(thermostats%thermostat_shell)) THEN
    1754          830 :             CALL print_thermostat_status(thermostats%thermostat_shell, para_env, my_pos, my_act, itimes, time)
    1755              :          END IF
    1756        10480 :          IF (ASSOCIATED(thermostats%thermostat_coef)) THEN
    1757            0 :             CALL print_thermostat_status(thermostats%thermostat_coef, para_env, my_pos, my_act, itimes, time)
    1758              :          END IF
    1759        10480 :          IF (ASSOCIATED(thermostats%thermostat_baro)) THEN
    1760         2302 :             CALL print_thermostat_status(thermostats%thermostat_baro, para_env, my_pos, my_act, itimes, time)
    1761              :          END IF
    1762              :       END IF
    1763        42149 :    END SUBROUTINE print_thermostats_status
    1764              : 
    1765              : ! **************************************************************************************************
    1766              : !> \brief Prints status of a specific thermostat
    1767              : !> \param thermostat ...
    1768              : !> \param para_env ...
    1769              : !> \param my_pos ...
    1770              : !> \param my_act ...
    1771              : !> \param itimes ...
    1772              : !> \param time ...
    1773              : !> \author Teodoro Laino [tlaino] - 02.2008 - University of Zurich
    1774              : ! **************************************************************************************************
    1775        13278 :    SUBROUTINE print_thermostat_status(thermostat, para_env, my_pos, my_act, itimes, time)
    1776              :       TYPE(thermostat_type), POINTER                     :: thermostat
    1777              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1778              :       CHARACTER(LEN=default_string_length)               :: my_pos, my_act
    1779              :       INTEGER, INTENT(IN)                                :: itimes
    1780              :       REAL(KIND=dp), INTENT(IN)                          :: time
    1781              : 
    1782              :       INTEGER                                            :: i, unit
    1783              :       LOGICAL                                            :: new_file
    1784              :       REAL(KIND=dp)                                      :: thermo_kin, thermo_pot, tot_temperature
    1785        13278 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: array_kin, array_pot, array_temp
    1786              :       TYPE(cp_logger_type), POINTER                      :: logger
    1787              :       TYPE(section_vals_type), POINTER                   :: print_key
    1788              : 
    1789        13278 :       NULLIFY (logger, print_key, array_pot, array_kin, array_temp)
    1790        26556 :       logger => cp_get_default_logger()
    1791              : 
    1792        13278 :       IF (ASSOCIATED(thermostat)) THEN
    1793              :          ! Print Energies
    1794        13278 :          print_key => section_vals_get_subs_vals(thermostat%section, "PRINT%ENERGY")
    1795        13278 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    1796          296 :             CALL get_thermostat_energies(thermostat, thermo_pot, thermo_kin, para_env, array_pot, array_kin)
    1797              :             unit = cp_print_key_unit_nr(logger, thermostat%section, "PRINT%ENERGY", &
    1798              :                                         extension="."//TRIM(thermostat%label)//".tener", file_position=my_pos, &
    1799          296 :                                         file_action=my_act, is_new_file=new_file)
    1800          296 :             IF (unit > 0) THEN
    1801          148 :                IF (new_file) THEN
    1802           13 :                   WRITE (unit, '(A)') "# Thermostat Potential and Kinetic Energies - Total and per Region"
    1803           13 :                   WRITE (unit, '("#",3X,A,2X,A,13X,A,10X,A)') "Step Nr.", "Time[fs]", "Kin.[a.u.]", "Pot.[a.u.]"
    1804              :                END IF
    1805          148 :                WRITE (UNIT=unit, FMT="(I8, F12.3,6X,2F20.10)") itimes, time*femtoseconds, thermo_kin, thermo_pot
    1806          148 :                WRITE (unit, '(A,4F20.10)') "# KINETIC ENERGY REGIONS: ", array_kin(1:MIN(4, SIZE(array_kin)))
    1807         4499 :                DO i = 5, SIZE(array_kin), 4
    1808         4499 :                   WRITE (UNIT=unit, FMT='("#",25X,4F20.10)') array_kin(i:MIN(i + 3, SIZE(array_kin)))
    1809              :                END DO
    1810          148 :                WRITE (unit, '(A,4F20.10)') "# POTENT. ENERGY REGIONS: ", array_pot(1:MIN(4, SIZE(array_pot)))
    1811         4499 :                DO i = 5, SIZE(array_pot), 4
    1812         4499 :                   WRITE (UNIT=unit, FMT='("#",25X,4F20.10)') array_pot(i:MIN(i + 3, SIZE(array_pot)))
    1813              :                END DO
    1814          148 :                CALL m_flush(unit)
    1815              :             END IF
    1816          296 :             DEALLOCATE (array_kin)
    1817          296 :             DEALLOCATE (array_pot)
    1818          296 :             CALL cp_print_key_finished_output(unit, logger, thermostat%section, "PRINT%ENERGY")
    1819              :          END IF
    1820              :          ! Print Temperatures of the regions
    1821        13278 :          print_key => section_vals_get_subs_vals(thermostat%section, "PRINT%TEMPERATURE")
    1822        13278 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    1823          274 :             CALL get_region_temperatures(thermostat, tot_temperature, para_env, array_temp)
    1824              :             unit = cp_print_key_unit_nr(logger, thermostat%section, "PRINT%TEMPERATURE", &
    1825              :                                         extension="."//TRIM(thermostat%label)//".temp", file_position=my_pos, &
    1826          274 :                                         file_action=my_act, is_new_file=new_file)
    1827          274 :             IF (unit > 0) THEN
    1828          137 :                IF (new_file) THEN
    1829           12 :                   WRITE (unit, '(A)') "# Temperature Total and per Region"
    1830           12 :                   WRITE (unit, '("#",3X,A,2X,A,10X,A)') "Step Nr.", "Time[fs]", "Temp.[K]"
    1831              :                END IF
    1832          137 :                WRITE (UNIT=unit, FMT="(I8, F12.3,3X,F20.10)") itimes, time*femtoseconds, tot_temperature
    1833          137 :                WRITE (unit, '(A,I10)') "# TEMPERATURE REGIONS: ", SIZE(array_temp)
    1834         4625 :                DO i = 1, SIZE(array_temp), 4
    1835         4625 :                   WRITE (UNIT=unit, FMT='("#",22X,4F20.10)') array_temp(i:MIN(i + 3, SIZE(array_temp)))
    1836              :                END DO
    1837          137 :                CALL m_flush(unit)
    1838              :             END IF
    1839          274 :             DEALLOCATE (array_temp)
    1840          274 :             CALL cp_print_key_finished_output(unit, logger, thermostat%section, "PRINT%TEMPERATURE")
    1841              :          END IF
    1842              :       END IF
    1843        13278 :    END SUBROUTINE print_thermostat_status
    1844              : 
    1845              : ! **************************************************************************************************
    1846              : !> \brief Handles the communication for thermostats (1D array)
    1847              : !> \param array ...
    1848              : !> \param number ...
    1849              : !> \param para_env ...
    1850              : !> \author Teodoro Laino [tlaino] - University of Zurich 11.2007
    1851              : ! **************************************************************************************************
    1852        12498 :    SUBROUTINE communication_thermo_low1(array, number, para_env)
    1853              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: array
    1854              :       INTEGER, INTENT(IN)                                :: number
    1855              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1856              : 
    1857              :       INTEGER                                            :: i, icheck, ncheck
    1858        12498 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: work, work2
    1859              : 
    1860        37494 :       ALLOCATE (work(para_env%num_pe))
    1861        26028 :       DO i = 1, number
    1862        40590 :          work = 0.0_dp
    1863        13530 :          work(para_env%mepos + 1) = array(i)
    1864        67650 :          CALL para_env%sum(work)
    1865        40590 :          ncheck = COUNT(work /= 0.0_dp)
    1866        13530 :          array(i) = 0.0_dp
    1867        26028 :          IF (ncheck /= 0) THEN
    1868        38202 :             ALLOCATE (work2(ncheck))
    1869        12734 :             ncheck = 0
    1870        38202 :             DO icheck = 1, para_env%num_pe
    1871        38202 :                IF (work(icheck) /= 0.0_dp) THEN
    1872        25060 :                   ncheck = ncheck + 1
    1873        25060 :                   work2(ncheck) = work(icheck)
    1874              :                END IF
    1875              :             END DO
    1876        12734 :             CPASSERT(ncheck == SIZE(work2))
    1877        37794 :             CPASSERT(ALL(work2 == work2(1)))
    1878              : 
    1879        12734 :             array(i) = work2(1)
    1880        12734 :             DEALLOCATE (work2)
    1881              :          END IF
    1882              :       END DO
    1883        12498 :       DEALLOCATE (work)
    1884        12498 :    END SUBROUTINE communication_thermo_low1
    1885              : 
    1886              : ! **************************************************************************************************
    1887              : !> \brief Handles the communication for thermostats (2D array)
    1888              : !> \param array ...
    1889              : !> \param number1 ...
    1890              : !> \param number2 ...
    1891              : !> \param para_env ...
    1892              : !> \author Teodoro Laino [tlaino] - University of Zurich 11.2007
    1893              : ! **************************************************************************************************
    1894          250 :    SUBROUTINE communication_thermo_low2(array, number1, number2, para_env)
    1895              :       INTEGER, DIMENSION(:, :), INTENT(INOUT)            :: array
    1896              :       INTEGER, INTENT(IN)                                :: number1, number2
    1897              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1898              : 
    1899              :       INTEGER                                            :: i, icheck, j, ncheck
    1900          250 :       INTEGER, DIMENSION(:, :), POINTER                  :: work, work2
    1901              : 
    1902         1000 :       ALLOCATE (work(number1, para_env%num_pe))
    1903          606 :       DO i = 1, number2
    1904       309364 :          work = 0
    1905       154504 :          work(:, para_env%mepos + 1) = array(:, i)
    1906       618372 :          CALL para_env%sum(work)
    1907          356 :          ncheck = 0
    1908         1068 :          DO j = 1, para_env%num_pe
    1909        23584 :             IF (ANY(work(:, j) /= 0)) THEN
    1910          660 :                ncheck = ncheck + 1
    1911              :             END IF
    1912              :          END DO
    1913       154504 :          array(:, i) = 0
    1914          606 :          IF (ncheck /= 0) THEN
    1915         1424 :             ALLOCATE (work2(number1, ncheck))
    1916          356 :             ncheck = 0
    1917         1068 :             DO icheck = 1, para_env%num_pe
    1918        23584 :                IF (ANY(work(:, icheck) /= 0)) THEN
    1919          660 :                   ncheck = ncheck + 1
    1920       572880 :                   work2(:, ncheck) = work(:, icheck)
    1921              :                END IF
    1922              :             END DO
    1923          356 :             CPASSERT(ncheck == SIZE(work2, 2))
    1924         1016 :             DO j = 1, ncheck
    1925       286796 :                CPASSERT(ALL(work2(:, j) == work2(:, 1)))
    1926              :             END DO
    1927       154504 :             array(:, i) = work2(:, 1)
    1928          356 :             DEALLOCATE (work2)
    1929              :          END IF
    1930              :       END DO
    1931          250 :       DEALLOCATE (work)
    1932          250 :    END SUBROUTINE communication_thermo_low2
    1933              : 
    1934              : END MODULE thermostat_utils
        

Generated by: LCOV version 2.0-1