LCOV - code coverage report
Current view: top level - src/motion/thermostat - thermostat_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:cb5d5fc) Lines: 78.1 % 821 641
Test Date: 2026-04-24 07:01:27 Functions: 87.0 % 23 20

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 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_region_thermal, do_thermo_al, do_thermo_communication, &
      32              :         do_thermo_csvr, do_thermo_gle, do_thermo_no_communication, do_thermo_nose, &
      33              :         isokin_ensemble, langevin_ensemble, npe_f_ensemble, npe_i_ensemble, &
      34              :         nph_uniaxial_damped_ensemble, nph_uniaxial_ensemble, npt_f_ensemble, npt_i_ensemble, &
      35              :         npt_ia_ensemble, nve_ensemble, nvt_adiabatic_ensemble, 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         3592 :    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         1796 :       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         1796 :                                  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         1796 :                    mass_weighted=.TRUE., natoms=natom)
     185              : 
     186         7184 :       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         1796 :                                  region_sections=region_sections, qmmm_env=qmmm_env)
     192              : 
     193              :       ! Saving this value of simpar preliminar to the real count of constraints..
     194         1796 :       simpar%nfree_rot_transl = roto_trasl_dof
     195              : 
     196              :       ! compute the total number of degrees of freedom for temperature
     197         1796 :       nconstraint_ext = gci%ntot - gci%nrestraint
     198         1796 :       simpar%nfree = 3*natom - nconstraint_int - nconstraint_ext - roto_trasl_dof
     199              : 
     200         1796 :       logger => cp_get_default_logger()
     201              :       iw = cp_print_key_unit_nr(logger, print_section, "PROGRAM_RUN_INFO", &
     202         1796 :                                 extension=".log")
     203         1796 :       IF (iw > 0) THEN
     204              :          WRITE (iw, '(/,T2,A)') &
     205          820 :             'DOF| Calculation of degrees of freedom'
     206              :          WRITE (iw, '(T2,A,T71,I10)') &
     207          820 :             'DOF| Number of atoms', natom, &
     208          820 :             'DOF| Number of intramolecular constraints', nconstraint_int, &
     209          820 :             'DOF| Number of intermolecular constraints', nconstraint_ext, &
     210          820 :             'DOF| Invariants (translations + rotations)', roto_trasl_dof, &
     211         1640 :             'DOF| Degrees of freedom', simpar%nfree
     212              :          WRITE (iw, '(/,T2,A)') &
     213          820 :             'DOF| Restraints information'
     214              :          WRITE (iw, '(T2,A,T71,I10)') &
     215          820 :             'DOF| Number of intramolecular restraints', nrestraints_int, &
     216         1640 :             'DOF| Number of intermolecular restraints', gci%nrestraint
     217          820 :          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          820 :          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          820 :          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          820 :          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          820 :          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         1796 :                                         "PROGRAM_RUN_INFO")
     245              : 
     246         1796 :    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         1842 :    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         1842 :       NULLIFY (molecule_kind)
     600         1842 :       nkind = SIZE(molecule_kind_set)
     601         1842 :       do_shell = .FALSE.
     602         1842 :       IF (PRESENT(shell)) do_shell = shell
     603              :       ! Counting the global number of thermostats
     604         1842 :       sum_of_thermostats = 0
     605              :       ! Variable to denote independent thermostats (no communication necessary)
     606         1842 :       nointer = .TRUE.
     607         1842 :       check = .TRUE.
     608         1842 :       number = 0
     609         1842 :       dis_type = do_thermo_no_communication
     610              : 
     611         1842 :       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         1754 :          IF (ensemble == nve_ensemble) check = do_shell
     620         3014 :          IF (check) THEN
     621          872 :             SELECT CASE (region)
     622              :             CASE (do_region_global)
     623              :                ! Global Thermostat
     624          286 :                nointer = .FALSE.
     625          286 :                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              :                                 "A thermostat type DEFINED is requested but no thermostat "// &
     654            0 :                                 "regions are defined in THERMOSTAT/DEFINE_REGION.")
     655              :             CASE (do_region_thermal)
     656              :                ! Similar to defined region above, but in THERMAL_REGION%DEFINE_REGION
     657            0 :                nointer = .FALSE.
     658              :                ! Determine the number of thermostats defined in the input
     659            0 :                CALL section_vals_get(region_sections, n_repetition=sum_of_thermostats)
     660            0 :                IF (sum_of_thermostats < 1) &
     661              :                   CALL cp_abort(__LOCATION__, &
     662              :                                 "A thermostat type THERMAL is requested but no thermal "// &
     663          586 :                                 "regions are defined in THERMAL_REGION/DEFINE_REGION.")
     664              :             END SELECT
     665              : 
     666              :             ! Here we decide which parallel algorithm to use.
     667              :             ! if there are only massive and molecule type thermostats we can use
     668              :             ! a local scheme, in cases involving any combination with a
     669              :             ! global thermostat we assume a coupling of  degrees of freedom
     670              :             ! from different processors
     671              :             IF (nointer) THEN
     672              :                ! Distributed thermostats, no interaction
     673        14926 :                dis_type = do_thermo_no_communication
     674              :                ! we only count thermostats on this processor
     675              :                number = 0
     676        14926 :                DO ikind = 1, nkind
     677        14662 :                   nmol_local = local_molecules%n_el(ikind)
     678        14662 :                   molecule_kind => molecule_kind_set(ikind)
     679        14662 :                   CALL get_molecule_kind(molecule_kind, natom=natom, nshell=nshell)
     680        14662 :                   IF (do_shell) THEN
     681           58 :                      natom = nshell
     682           58 :                      IF (nshell == 0) nmol_local = 0
     683              :                   END IF
     684        29588 :                   IF (region == do_region_molecule) THEN
     685         5912 :                      number = number + nmol_local
     686         8750 :                   ELSE IF (region == do_region_massive) THEN
     687         8750 :                      number = number + 3*nmol_local*natom
     688              :                   ELSE
     689            0 :                      CPABORT('Invalid region setup')
     690              :                   END IF
     691              :                END DO
     692              :             ELSE
     693              :                ! REPlicated thermostats, INTERacting via communication
     694          322 :                dis_type = do_thermo_communication
     695          322 :                IF ((region == do_region_global) .OR. (region == do_region_molecule)) THEN
     696          290 :                   number = 1
     697           32 :                ELSE IF ((region == do_region_defined) .OR. (region == do_region_thermal)) THEN
     698              :                   CALL get_defined_region_info(region_sections, number, sum_of_thermostats, &
     699              :                                                map_loc_thermo_gen=thermostat_info%map_loc_thermo_gen, &
     700              :                                                local_molecules=local_molecules, molecule_kind_set=molecule_kind_set, &
     701           32 :                                                molecules=molecules, particles=particles, qmmm_env=qmmm_env)
     702              :                END IF
     703              :             END IF
     704              : 
     705          586 :             IF (PRESENT(nfree)) THEN
     706          540 :                IF ((sum_of_thermostats > 1) .OR. (dis_type == do_thermo_no_communication)) THEN
     707              :                   ! re-initializing simpar%nfree to zero because of multiple thermostats
     708          260 :                   nfree = 0
     709              :                END IF
     710              :             END IF
     711              :          END IF
     712              :       END SELECT
     713              : 
     714              :       ! Saving information about thermostats
     715         1842 :       thermostat_info%sum_of_thermostats = sum_of_thermostats
     716         1842 :       thermostat_info%number_of_thermostats = number
     717         1842 :       thermostat_info%dis_type = dis_type
     718         1842 :    END SUBROUTINE setup_thermostat_info
     719              : 
     720              : ! **************************************************************************************************
     721              : !> \brief ...
     722              : !> \param region_sections ...
     723              : !> \param number ...
     724              : !> \param sum_of_thermostats ...
     725              : !> \param map_loc_thermo_gen ...
     726              : !> \param local_molecules ...
     727              : !> \param molecule_kind_set ...
     728              : !> \param molecules ...
     729              : !> \param particles ...
     730              : !> \param qmmm_env ...
     731              : !> \author 11.2007 [tlaino] - Teodoro Laino - University of Zurich
     732              : ! **************************************************************************************************
     733           32 :    SUBROUTINE get_defined_region_info(region_sections, number, sum_of_thermostats, &
     734              :                                       map_loc_thermo_gen, local_molecules, molecule_kind_set, molecules, particles, &
     735              :                                       qmmm_env)
     736              :       TYPE(section_vals_type), POINTER                   :: region_sections
     737              :       INTEGER, INTENT(OUT), OPTIONAL                     :: number
     738              :       INTEGER, INTENT(INOUT), OPTIONAL                   :: sum_of_thermostats
     739              :       INTEGER, DIMENSION(:), POINTER                     :: map_loc_thermo_gen
     740              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
     741              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
     742              :       TYPE(molecule_list_type), POINTER                  :: molecules
     743              :       TYPE(particle_list_type), POINTER                  :: particles
     744              :       TYPE(qmmm_env_type), POINTER                       :: qmmm_env
     745              : 
     746              :       CHARACTER(LEN=default_string_length), &
     747           32 :          DIMENSION(:), POINTER                           :: tmpstringlist
     748              :       INTEGER :: first_atom, i, ig, ikind, ilist, imol, ipart, jg, last_atom, mregions, n_rep, &
     749              :          natom_local, nmol_per_kind, nregions, output_unit
     750           32 :       INTEGER, DIMENSION(:), POINTER                     :: thermolist, tmp, tmplist
     751              :       TYPE(cp_logger_type), POINTER                      :: logger
     752              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     753              :       TYPE(molecule_type), DIMENSION(:), POINTER         :: molecule_set
     754              :       TYPE(molecule_type), POINTER                       :: molecule
     755              : 
     756           32 :       NULLIFY (tmplist, tmpstringlist, thermolist, molecule_kind, molecule, molecule_set)
     757           32 :       NULLIFY (logger)
     758           64 :       logger => cp_get_default_logger()
     759           32 :       output_unit = cp_logger_get_default_io_unit(logger)
     760           32 :       CPASSERT(.NOT. (ASSOCIATED(map_loc_thermo_gen)))
     761           32 :       CALL section_vals_get(region_sections, n_repetition=nregions)
     762           96 :       ALLOCATE (thermolist(particles%n_els))
     763        43970 :       thermolist = HUGE(0)
     764           32 :       molecule_set => molecules%els
     765           32 :       mregions = nregions
     766          102 :       DO ig = 1, mregions
     767           70 :          CALL section_vals_val_get(region_sections, "LIST", i_rep_section=ig, n_rep_val=n_rep)
     768           70 :          IF (n_rep > 0) THEN
     769          172 :             DO jg = 1, n_rep
     770          114 :                CALL section_vals_val_get(region_sections, "LIST", i_rep_section=ig, i_rep_val=jg, i_vals=tmplist)
     771         2416 :                DO i = 1, SIZE(tmplist)
     772         2244 :                   ipart = tmplist(i)
     773         2244 :                   CPASSERT(((ipart > 0) .AND. (ipart <= particles%n_els)))
     774         2358 :                   IF (thermolist(ipart) == HUGE(0) .OR. thermolist(ipart) == ig) THEN
     775         2244 :                      thermolist(ipart) = ig
     776              :                   ELSE
     777              :                      CALL cp_abort(__LOCATION__, &
     778              :                                    "The atom "//cp_to_string(ipart)//" has been "// &
     779              :                                    "assigned to different thermostat regions "// &
     780              :                                    cp_to_string(thermolist(ipart))//" and "// &
     781            0 :                                    cp_to_string(ig)//" which is not allowed!")
     782              :                   END IF
     783              :                END DO
     784              :             END DO
     785              :          END IF
     786           70 :          CALL section_vals_val_get(region_sections, "MOLNAME", i_rep_section=ig, n_rep_val=n_rep)
     787           70 :          IF (n_rep > 0) THEN
     788            8 :             DO jg = 1, n_rep
     789            4 :                CALL section_vals_val_get(region_sections, "MOLNAME", i_rep_section=ig, i_rep_val=jg, c_vals=tmpstringlist)
     790           12 :                DO ilist = 1, SIZE(tmpstringlist)
     791           20 :                   DO ikind = 1, SIZE(molecule_kind_set)
     792           12 :                      molecule_kind => molecule_kind_set(ikind)
     793           16 :                      IF (molecule_kind%name == tmpstringlist(ilist)) THEN
     794           48 :                         DO imol = 1, SIZE(molecule_kind%molecule_list)
     795           44 :                            molecule => molecule_set(molecule_kind%molecule_list(imol))
     796           44 :                            CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     797          180 :                            DO ipart = first_atom, last_atom
     798          176 :                               IF (thermolist(ipart) == HUGE(0) .OR. thermolist(ipart) == ig) THEN
     799          132 :                                  thermolist(ipart) = ig
     800              :                               ELSE
     801              :                                  CALL cp_abort(__LOCATION__, &
     802              :                                                "The atom "//cp_to_string(ipart)//" has been "// &
     803              :                                                "assigned to different thermostat regions "// &
     804              :                                                cp_to_string(thermolist(ipart))//" and "// &
     805            0 :                                                cp_to_string(ig)//" which is not allowed!")
     806              :                               END IF
     807              :                            END DO
     808              :                         END DO
     809              :                      END IF
     810              :                   END DO
     811              :                END DO
     812              :             END DO
     813              :          END IF
     814              :          CALL setup_thermostat_subsys(region_sections, qmmm_env, thermolist, molecule_set, &
     815           70 :                                       subsys_qm=.FALSE., ig=ig, sum_of_thermostats=sum_of_thermostats, nregions=nregions)
     816              :          CALL setup_thermostat_subsys(region_sections, qmmm_env, thermolist, molecule_set, &
     817          242 :                                       subsys_qm=.TRUE., ig=ig, sum_of_thermostats=sum_of_thermostats, nregions=nregions)
     818              :       END DO
     819              : 
     820              :       ! Dump IO warning for not thermalized particles
     821        29100 :       IF (ANY(thermolist == HUGE(0))) THEN
     822           14 :          nregions = nregions + 1
     823           14 :          sum_of_thermostats = sum_of_thermostats + 1
     824        15008 :          ALLOCATE (tmp(COUNT(thermolist == HUGE(0))))
     825        14980 :          ilist = 0
     826        14980 :          DO i = 1, SIZE(thermolist)
     827        14980 :             IF (thermolist(i) == HUGE(0)) THEN
     828        13894 :                ilist = ilist + 1
     829        13894 :                tmp(ilist) = i
     830        13894 :                thermolist(i) = nregions
     831              :             END IF
     832              :          END DO
     833           14 :          IF (ilist > 0) THEN
     834           14 :             IF (output_unit > 0) THEN
     835              :                WRITE (output_unit, '(/,T2,A)') &
     836            7 :                   "THERMOSTAT| Warning: No thermostats defined for the following atoms:"
     837          877 :                DO i = 1, ilist, 8
     838          877 :                   WRITE (output_unit, '(T2,A,T17,8I8)') "THERMOSTAT|", tmp(i:MIN(i + 7, ilist))
     839              :                END DO
     840              :                WRITE (output_unit, '(T2,A)') &
     841            7 :                   "THERMOSTAT| They will be included in a further unique thermostat!"
     842              :             END IF
     843              :          END IF
     844           14 :          DEALLOCATE (tmp)
     845              :       END IF
     846        43970 :       CPASSERT(ALL(thermolist /= HUGE(0)))
     847              : 
     848              :       ! Output thermostat region mapping to particles
     849              :       ! The region indices are assumed to be 0-999
     850           32 :       IF (output_unit > 0) THEN
     851              :          WRITE (output_unit, '(/,T2,A)') &
     852           16 :             "THERMOSTAT| Mapping of thermostat region indices to particles"
     853         1390 :          DO ipart = 1, particles%n_els, 16
     854              :             WRITE (output_unit, '(T2,A,T17,16(" ",I3))') &
     855         1390 :                "THERMOSTAT|", thermolist(ipart:MIN(ipart + 15, particles%n_els))
     856              :          END DO
     857              :       END IF
     858              : 
     859              :       ! Now identify the local number of thermostats
     860           96 :       ALLOCATE (tmp(nregions))
     861          116 :       tmp = 0
     862           32 :       natom_local = 0
     863           98 :       DO ikind = 1, SIZE(molecule_kind_set)
     864           66 :          nmol_per_kind = local_molecules%n_el(ikind)
     865         7384 :          DO imol = 1, nmol_per_kind
     866         7286 :             i = local_molecules%list(ikind)%array(imol)
     867         7286 :             molecule => molecule_set(i)
     868         7286 :             CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     869        29321 :             DO ipart = first_atom, last_atom
     870        21969 :                natom_local = natom_local + 1
     871        29255 :                tmp(thermolist(ipart)) = 1
     872              :             END DO
     873              :          END DO
     874              :       END DO
     875          116 :       number = SUM(tmp)
     876           32 :       DEALLOCATE (tmp)
     877              : 
     878              :       ! Now map the local atoms with the corresponding thermostat
     879           96 :       ALLOCATE (map_loc_thermo_gen(natom_local))
     880           32 :       natom_local = 0
     881           98 :       DO ikind = 1, SIZE(molecule_kind_set)
     882           66 :          nmol_per_kind = local_molecules%n_el(ikind)
     883         7384 :          DO imol = 1, nmol_per_kind
     884         7286 :             i = local_molecules%list(ikind)%array(imol)
     885         7286 :             molecule => molecule_set(i)
     886         7286 :             CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     887        29321 :             DO ipart = first_atom, last_atom
     888        21969 :                natom_local = natom_local + 1
     889        29255 :                map_loc_thermo_gen(natom_local) = thermolist(ipart)
     890              :             END DO
     891              :          END DO
     892              :       END DO
     893              : 
     894           32 :       DEALLOCATE (thermolist)
     895           64 :    END SUBROUTINE get_defined_region_info
     896              : 
     897              : ! **************************************************************************************************
     898              : !> \brief ...
     899              : !> \param region_sections ...
     900              : !> \param qmmm_env ...
     901              : !> \param thermolist ...
     902              : !> \param molecule_set ...
     903              : !> \param subsys_qm ...
     904              : !> \param ig ...
     905              : !> \param sum_of_thermostats ...
     906              : !> \param nregions ...
     907              : !> \author 11.2007 [tlaino] - Teodoro Laino - University of Zurich
     908              : ! **************************************************************************************************
     909          140 :    SUBROUTINE setup_thermostat_subsys(region_sections, qmmm_env, thermolist, &
     910              :                                       molecule_set, subsys_qm, ig, sum_of_thermostats, nregions)
     911              :       TYPE(section_vals_type), POINTER                   :: region_sections
     912              :       TYPE(qmmm_env_type), POINTER                       :: qmmm_env
     913              :       INTEGER, DIMENSION(:), POINTER                     :: thermolist
     914              :       TYPE(molecule_type), DIMENSION(:), POINTER         :: molecule_set
     915              :       LOGICAL, INTENT(IN)                                :: subsys_qm
     916              :       INTEGER, INTENT(IN)                                :: ig
     917              :       INTEGER, INTENT(INOUT)                             :: sum_of_thermostats, nregions
     918              : 
     919              :       CHARACTER(LEN=default_string_length)               :: label1, label2
     920              :       INTEGER                                            :: first_atom, i, imolecule, ipart, &
     921              :                                                             last_atom, nrep, thermo1
     922          140 :       INTEGER, DIMENSION(:), POINTER                     :: atom_index1
     923              :       LOGICAL                                            :: explicit
     924              :       TYPE(molecule_type), POINTER                       :: molecule
     925              : 
     926          140 :       label1 = "MM_SUBSYS"
     927          140 :       label2 = "QM_SUBSYS"
     928          140 :       IF (subsys_qm) THEN
     929           70 :          label1 = "QM_SUBSYS"
     930           70 :          label2 = "MM_SUBSYS"
     931              :       END IF
     932              :       CALL section_vals_val_get(region_sections, TRIM(label1), i_rep_section=ig, &
     933          140 :                                 n_rep_val=nrep, explicit=explicit)
     934          140 :       IF (nrep == 1 .AND. explicit) THEN
     935            8 :          IF (ASSOCIATED(qmmm_env)) THEN
     936            8 :             atom_index1 => qmmm_env%qm%mm_atom_index
     937            8 :             IF (subsys_qm) THEN
     938            4 :                atom_index1 => qmmm_env%qm%qm_atom_index
     939              :             END IF
     940            8 :             CALL section_vals_val_get(region_sections, TRIM(label1), i_val=thermo1, i_rep_section=ig)
     941            4 :             SELECT CASE (thermo1)
     942              :             CASE (do_constr_atomic)
     943        13820 :                DO i = 1, SIZE(atom_index1)
     944        13816 :                   ipart = atom_index1(i)
     945        13816 :                   IF (subsys_qm .AND. qmmm_env%qm%qmmm_link .AND. ASSOCIATED(qmmm_env%qm%mm_link_atoms)) THEN
     946           46 :                      IF (ANY(ipart == qmmm_env%qm%mm_link_atoms)) CYCLE
     947              :                   END IF
     948        13818 :                   IF (thermolist(ipart) == HUGE(0)) THEN
     949        13814 :                      thermolist(ipart) = ig
     950              :                   ELSE
     951              :                      CALL cp_abort(__LOCATION__, &
     952              :                                    'One atom ('//cp_to_string(ipart)//') of the '// &
     953              :                                    TRIM(label1)//' was already assigned to'// &
     954              :                                    ' the thermostatting region Nr.'//cp_to_string(thermolist(ipart))// &
     955            0 :                                    '. Please check the input for inconsistencies!')
     956              :                   END IF
     957              :                END DO
     958              :             CASE (do_constr_molec)
     959         9168 :                DO imolecule = 1, SIZE(molecule_set)
     960         9160 :                   molecule => molecule_set(imolecule)
     961         9160 :                   CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     962     15908454 :                   IF (ANY(atom_index1 >= first_atom .AND. atom_index1 <= last_atom)) THEN
     963        18436 :                      DO ipart = first_atom, last_atom
     964        18436 :                         IF (thermolist(ipart) == HUGE(0)) THEN
     965        13854 :                            thermolist(ipart) = ig
     966              :                         ELSE
     967              :                            CALL cp_abort(__LOCATION__, &
     968              :                                          'One atom ('//cp_to_string(ipart)//') of the '// &
     969              :                                          TRIM(label1)//' was already assigned to'// &
     970              :                                          ' the thermostatting region Nr.'//cp_to_string(thermolist(ipart))// &
     971            0 :                                          '. Please check the input for inconsistencies!')
     972              :                         END IF
     973              :                      END DO
     974              :                   END IF
     975              :                END DO
     976              :             END SELECT
     977              :          ELSE
     978            0 :             sum_of_thermostats = sum_of_thermostats - 1
     979            0 :             nregions = nregions - 1
     980              :          END IF
     981              :       END IF
     982          140 :    END SUBROUTINE setup_thermostat_subsys
     983              : 
     984              : ! **************************************************************************************************
     985              : !> \brief ...
     986              : !> \param map_info ...
     987              : !> \param npt ...
     988              : !> \param group ...
     989              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
     990              : ! **************************************************************************************************
     991         5444 :    SUBROUTINE ke_region_baro(map_info, npt, group)
     992              :       TYPE(map_info_type), POINTER                       :: map_info
     993              :       TYPE(npt_info_type), DIMENSION(:, :), &
     994              :          INTENT(INOUT)                                   :: npt
     995              :       TYPE(mp_comm_type), INTENT(IN)                     :: group
     996              : 
     997              :       INTEGER                                            :: i, j, ncoef
     998              : 
     999        10888 :       map_info%v_scale = 1.0_dp
    1000        10888 :       map_info%s_kin = 0.0_dp
    1001         5444 :       ncoef = 0
    1002        13672 :       DO i = 1, SIZE(npt, 1)
    1003        30252 :          DO j = 1, SIZE(npt, 2)
    1004        16580 :             ncoef = ncoef + 1
    1005              :             map_info%p_kin(1, ncoef)%point = map_info%p_kin(1, ncoef)%point &
    1006        24808 :                                              + npt(i, j)%mass*npt(i, j)%v**2
    1007              :          END DO
    1008              :       END DO
    1009              : 
    1010         5444 :       IF (map_info%dis_type == do_thermo_communication) CALL group%sum(map_info%s_kin)
    1011              : 
    1012         5444 :    END SUBROUTINE ke_region_baro
    1013              : 
    1014              : ! **************************************************************************************************
    1015              : !> \brief ...
    1016              : !> \param map_info ...
    1017              : !> \param npt ...
    1018              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
    1019              : ! **************************************************************************************************
    1020         4360 :    SUBROUTINE vel_rescale_baro(map_info, npt)
    1021              :       TYPE(map_info_type), POINTER                       :: map_info
    1022              :       TYPE(npt_info_type), DIMENSION(:, :), &
    1023              :          INTENT(INOUT)                                   :: npt
    1024              : 
    1025              :       INTEGER                                            :: i, j, ncoef
    1026              : 
    1027         4360 :       ncoef = 0
    1028        11344 :       DO i = 1, SIZE(npt, 1)
    1029        26200 :          DO j = 1, SIZE(npt, 2)
    1030        14856 :             ncoef = ncoef + 1
    1031        21840 :             npt(i, j)%v = npt(i, j)%v*map_info%p_scale(1, ncoef)%point
    1032              :          END DO
    1033              :       END DO
    1034              : 
    1035         4360 :    END SUBROUTINE vel_rescale_baro
    1036              : 
    1037              : ! **************************************************************************************************
    1038              : !> \brief ...
    1039              : !> \param map_info ...
    1040              : !> \param particle_set ...
    1041              : !> \param molecule_kind_set ...
    1042              : !> \param local_molecules ...
    1043              : !> \param molecule_set ...
    1044              : !> \param group ...
    1045              : !> \param vel ...
    1046              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
    1047              : ! **************************************************************************************************
    1048        25708 :    SUBROUTINE ke_region_particles(map_info, particle_set, molecule_kind_set, &
    1049        25708 :                                   local_molecules, molecule_set, group, vel)
    1050              : 
    1051              :       TYPE(map_info_type), POINTER                       :: map_info
    1052              :       TYPE(particle_type), POINTER                       :: particle_set(:)
    1053              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
    1054              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
    1055              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
    1056              :       TYPE(mp_comm_type), INTENT(IN)                     :: group
    1057              :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: vel(:, :)
    1058              : 
    1059              :       INTEGER                                            :: first_atom, ii, ikind, imol, imol_local, &
    1060              :                                                             ipart, last_atom, nmol_local
    1061              :       LOGICAL                                            :: present_vel
    1062              :       REAL(KIND=dp)                                      :: mass
    1063              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1064              :       TYPE(molecule_type), POINTER                       :: molecule
    1065              : 
    1066      1553576 :       map_info%v_scale = 1.0_dp
    1067      1553576 :       map_info%s_kin = 0.0_dp
    1068        25708 :       present_vel = PRESENT(vel)
    1069        25708 :       ii = 0
    1070      1271176 :       DO ikind = 1, SIZE(molecule_kind_set)
    1071      1245468 :          nmol_local = local_molecules%n_el(ikind)
    1072      2656966 :          DO imol_local = 1, nmol_local
    1073      1385790 :             imol = local_molecules%list(ikind)%array(imol_local)
    1074      1385790 :             molecule => molecule_set(imol)
    1075      1385790 :             CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
    1076      5677896 :             DO ipart = first_atom, last_atom
    1077      3046638 :                ii = ii + 1
    1078      3046638 :                atomic_kind => particle_set(ipart)%atomic_kind
    1079      3046638 :                CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
    1080      4432428 :                IF (present_vel) THEN
    1081      1523319 :                   IF (ASSOCIATED(map_info%p_kin(1, ii)%point)) &
    1082      1523319 :                      map_info%p_kin(1, ii)%point = map_info%p_kin(1, ii)%point + mass*vel(1, ipart)**2
    1083      1523319 :                   IF (ASSOCIATED(map_info%p_kin(2, ii)%point)) &
    1084      1523319 :                      map_info%p_kin(2, ii)%point = map_info%p_kin(2, ii)%point + mass*vel(2, ipart)**2
    1085      1523319 :                   IF (ASSOCIATED(map_info%p_kin(3, ii)%point)) &
    1086      1523319 :                      map_info%p_kin(3, ii)%point = map_info%p_kin(3, ii)%point + mass*vel(3, ipart)**2
    1087              :                ELSE
    1088      1523319 :                   IF (ASSOCIATED(map_info%p_kin(1, ii)%point)) &
    1089      1523319 :                      map_info%p_kin(1, ii)%point = map_info%p_kin(1, ii)%point + mass*particle_set(ipart)%v(1)**2
    1090      1523319 :                   IF (ASSOCIATED(map_info%p_kin(2, ii)%point)) &
    1091      1523319 :                      map_info%p_kin(2, ii)%point = map_info%p_kin(2, ii)%point + mass*particle_set(ipart)%v(2)**2
    1092      1523319 :                   IF (ASSOCIATED(map_info%p_kin(3, ii)%point)) &
    1093      1523319 :                      map_info%p_kin(3, ii)%point = map_info%p_kin(3, ii)%point + mass*particle_set(ipart)%v(3)**2
    1094              :                END IF
    1095              :             END DO
    1096              :          END DO
    1097              :       END DO
    1098              : 
    1099        62732 :       IF (map_info%dis_type == do_thermo_communication) CALL group%sum(map_info%s_kin)
    1100              : 
    1101        25708 :    END SUBROUTINE ke_region_particles
    1102              : 
    1103              : ! **************************************************************************************************
    1104              : !> \brief ...
    1105              : !> \param map_info ...
    1106              : !> \param particle_set ...
    1107              : !> \param molecule_kind_set ...
    1108              : !> \param local_molecules ...
    1109              : !> \param molecule_set ...
    1110              : !> \param group ...
    1111              : !> \param vel ...
    1112              : !> \author 07.2009 MI
    1113              : ! **************************************************************************************************
    1114          800 :    SUBROUTINE momentum_region_particles(map_info, particle_set, molecule_kind_set, &
    1115          800 :                                         local_molecules, molecule_set, group, vel)
    1116              : 
    1117              :       TYPE(map_info_type), POINTER                       :: map_info
    1118              :       TYPE(particle_type), POINTER                       :: particle_set(:)
    1119              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
    1120              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
    1121              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
    1122              :       TYPE(mp_comm_type), INTENT(IN)                     :: group
    1123              :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: vel(:, :)
    1124              : 
    1125              :       INTEGER                                            :: first_atom, ii, ikind, imol, imol_local, &
    1126              :                                                             ipart, last_atom, nmol_local
    1127              :       LOGICAL                                            :: present_vel
    1128              :       REAL(KIND=dp)                                      :: mass
    1129              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1130              :       TYPE(molecule_type), POINTER                       :: molecule
    1131              : 
    1132       130400 :       map_info%v_scale = 1.0_dp
    1133       130400 :       map_info%s_kin = 0.0_dp
    1134          800 :       present_vel = PRESENT(vel)
    1135          800 :       ii = 0
    1136        87200 :       DO ikind = 1, SIZE(molecule_kind_set)
    1137        86400 :          nmol_local = local_molecules%n_el(ikind)
    1138       130400 :          DO imol_local = 1, nmol_local
    1139        43200 :             imol = local_molecules%list(ikind)%array(imol_local)
    1140        43200 :             molecule => molecule_set(imol)
    1141        43200 :             CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
    1142       172800 :             DO ipart = first_atom, last_atom
    1143        43200 :                ii = ii + 1
    1144        43200 :                atomic_kind => particle_set(ipart)%atomic_kind
    1145        43200 :                CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass)
    1146        86400 :                IF (present_vel) THEN
    1147        21600 :                   map_info%p_kin(1, ii)%point = map_info%p_kin(1, ii)%point + SQRT(mass)*vel(1, ipart)
    1148        21600 :                   map_info%p_kin(2, ii)%point = map_info%p_kin(2, ii)%point + SQRT(mass)*vel(2, ipart)
    1149        21600 :                   map_info%p_kin(3, ii)%point = map_info%p_kin(3, ii)%point + SQRT(mass)*vel(3, ipart)
    1150              :                ELSE
    1151        21600 :                   map_info%p_kin(1, ii)%point = map_info%p_kin(1, ii)%point + SQRT(mass)*particle_set(ipart)%v(1)
    1152        21600 :                   map_info%p_kin(2, ii)%point = map_info%p_kin(2, ii)%point + SQRT(mass)*particle_set(ipart)%v(2)
    1153        21600 :                   map_info%p_kin(3, ii)%point = map_info%p_kin(3, ii)%point + SQRT(mass)*particle_set(ipart)%v(3)
    1154              :                END IF
    1155              :             END DO
    1156              :          END DO
    1157              :       END DO
    1158              : 
    1159          800 :       IF (map_info%dis_type == do_thermo_communication) CALL group%sum(map_info%s_kin)
    1160              : 
    1161          800 :    END SUBROUTINE momentum_region_particles
    1162              : 
    1163              : ! **************************************************************************************************
    1164              : !> \brief ...
    1165              : !> \param map_info ...
    1166              : !> \param molecule_kind_set ...
    1167              : !> \param molecule_set ...
    1168              : !> \param particle_set ...
    1169              : !> \param local_molecules ...
    1170              : !> \param shell_adiabatic ...
    1171              : !> \param shell_particle_set ...
    1172              : !> \param core_particle_set ...
    1173              : !> \param vel ...
    1174              : !> \param shell_vel ...
    1175              : !> \param core_vel ...
    1176              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
    1177              : ! **************************************************************************************************
    1178        19480 :    SUBROUTINE vel_rescale_particles(map_info, molecule_kind_set, molecule_set, &
    1179              :                                     particle_set, local_molecules, shell_adiabatic, shell_particle_set, &
    1180        19480 :                                     core_particle_set, vel, shell_vel, core_vel)
    1181              : 
    1182              :       TYPE(map_info_type), POINTER                       :: map_info
    1183              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
    1184              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
    1185              :       TYPE(particle_type), POINTER                       :: particle_set(:)
    1186              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
    1187              :       LOGICAL, INTENT(IN)                                :: shell_adiabatic
    1188              :       TYPE(particle_type), OPTIONAL, POINTER             :: shell_particle_set(:), &
    1189              :                                                             core_particle_set(:)
    1190              :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: vel(:, :), shell_vel(:, :), &
    1191              :                                                             core_vel(:, :)
    1192              : 
    1193              :       INTEGER                                            :: first_atom, ii, ikind, imol, imol_local, &
    1194              :                                                             ipart, jj, last_atom, nmol_local, &
    1195              :                                                             shell_index
    1196              :       LOGICAL                                            :: present_vel
    1197              :       REAL(KIND=dp)                                      :: fac_massc, fac_masss, mass, vc(3), vs(3)
    1198              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1199              :       TYPE(molecule_type), POINTER                       :: molecule
    1200              :       TYPE(shell_kind_type), POINTER                     :: shell
    1201              : 
    1202        19480 :       ii = 0
    1203        19480 :       jj = 0
    1204        19480 :       present_vel = PRESENT(vel)
    1205              :       ! Just few checks for consistency
    1206        19480 :       IF (present_vel) THEN
    1207         9740 :          IF (shell_adiabatic) THEN
    1208         1410 :             CPASSERT(PRESENT(shell_vel))
    1209         1410 :             CPASSERT(PRESENT(core_vel))
    1210              :          END IF
    1211              :       ELSE
    1212         9740 :          IF (shell_adiabatic) THEN
    1213         1410 :             CPASSERT(PRESENT(shell_particle_set))
    1214         1410 :             CPASSERT(PRESENT(core_particle_set))
    1215              :          END IF
    1216              :       END IF
    1217       826036 :       Kind: DO ikind = 1, SIZE(molecule_kind_set)
    1218       806556 :          nmol_local = local_molecules%n_el(ikind)
    1219      1733072 :          Mol_local: DO imol_local = 1, nmol_local
    1220       907036 :             imol = local_molecules%list(ikind)%array(imol_local)
    1221       907036 :             molecule => molecule_set(imol)
    1222       907036 :             CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
    1223      3697444 :             Particle: DO ipart = first_atom, last_atom
    1224      1983852 :                ii = ii + 1
    1225      1983852 :                IF (present_vel) THEN
    1226       991926 :                   vel(1, ipart) = vel(1, ipart)*map_info%p_scale(1, ii)%point
    1227       991926 :                   vel(2, ipart) = vel(2, ipart)*map_info%p_scale(2, ii)%point
    1228       991926 :                   vel(3, ipart) = vel(3, ipart)*map_info%p_scale(3, ii)%point
    1229              :                ELSE
    1230       991926 :                   particle_set(ipart)%v(1) = particle_set(ipart)%v(1)*map_info%p_scale(1, ii)%point
    1231       991926 :                   particle_set(ipart)%v(2) = particle_set(ipart)%v(2)*map_info%p_scale(2, ii)%point
    1232       991926 :                   particle_set(ipart)%v(3) = particle_set(ipart)%v(3)*map_info%p_scale(3, ii)%point
    1233              :                END IF
    1234              :                ! If Shell Adiabatic then apply the NHC thermostat also to the Shells
    1235      2890888 :                IF (shell_adiabatic) THEN
    1236       152160 :                   shell_index = particle_set(ipart)%shell_index
    1237       152160 :                   IF (shell_index /= 0) THEN
    1238       150880 :                      jj = jj + 2
    1239       150880 :                      atomic_kind => particle_set(ipart)%atomic_kind
    1240       150880 :                      CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass, shell=shell)
    1241       150880 :                      fac_masss = shell%mass_shell/mass
    1242       150880 :                      fac_massc = shell%mass_core/mass
    1243       150880 :                      IF (present_vel) THEN
    1244       301760 :                         vs(1:3) = shell_vel(1:3, shell_index)
    1245       301760 :                         vc(1:3) = core_vel(1:3, shell_index)
    1246        75440 :                         shell_vel(1, shell_index) = vel(1, ipart) + fac_massc*(vs(1) - vc(1))
    1247        75440 :                         shell_vel(2, shell_index) = vel(2, ipart) + fac_massc*(vs(2) - vc(2))
    1248        75440 :                         shell_vel(3, shell_index) = vel(3, ipart) + fac_massc*(vs(3) - vc(3))
    1249        75440 :                         core_vel(1, shell_index) = vel(1, ipart) + fac_masss*(vc(1) - vs(1))
    1250        75440 :                         core_vel(2, shell_index) = vel(2, ipart) + fac_masss*(vc(2) - vs(2))
    1251        75440 :                         core_vel(3, shell_index) = vel(3, ipart) + fac_masss*(vc(3) - vs(3))
    1252              :                      ELSE
    1253       301760 :                         vs(1:3) = shell_particle_set(shell_index)%v(1:3)
    1254       301760 :                         vc(1:3) = core_particle_set(shell_index)%v(1:3)
    1255        75440 :                         shell_particle_set(shell_index)%v(1) = particle_set(ipart)%v(1) + fac_massc*(vs(1) - vc(1))
    1256        75440 :                         shell_particle_set(shell_index)%v(2) = particle_set(ipart)%v(2) + fac_massc*(vs(2) - vc(2))
    1257        75440 :                         shell_particle_set(shell_index)%v(3) = particle_set(ipart)%v(3) + fac_massc*(vs(3) - vc(3))
    1258        75440 :                         core_particle_set(shell_index)%v(1) = particle_set(ipart)%v(1) + fac_masss*(vc(1) - vs(1))
    1259        75440 :                         core_particle_set(shell_index)%v(2) = particle_set(ipart)%v(2) + fac_masss*(vc(2) - vs(2))
    1260        75440 :                         core_particle_set(shell_index)%v(3) = particle_set(ipart)%v(3) + fac_masss*(vc(3) - vs(3))
    1261              :                      END IF
    1262              :                   END IF
    1263              :                END IF
    1264              :             END DO Particle
    1265              :          END DO Mol_local
    1266              :       END DO Kind
    1267              : 
    1268        19480 :    END SUBROUTINE vel_rescale_particles
    1269              : 
    1270              : ! **************************************************************************************************
    1271              : !> \brief ...
    1272              : !> \param map_info ...
    1273              : !> \param particle_set ...
    1274              : !> \param atomic_kind_set ...
    1275              : !> \param local_particles ...
    1276              : !> \param group ...
    1277              : !> \param core_particle_set ...
    1278              : !> \param shell_particle_set ...
    1279              : !> \param core_vel ...
    1280              : !> \param shell_vel ...
    1281              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
    1282              : ! **************************************************************************************************
    1283         1840 :    SUBROUTINE ke_region_shells(map_info, particle_set, atomic_kind_set, &
    1284              :                                local_particles, group, core_particle_set, shell_particle_set, &
    1285         1840 :                                core_vel, shell_vel)
    1286              : 
    1287              :       TYPE(map_info_type), POINTER                       :: map_info
    1288              :       TYPE(particle_type), POINTER                       :: particle_set(:)
    1289              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind_set(:)
    1290              :       TYPE(distribution_1d_type), POINTER                :: local_particles
    1291              :       TYPE(mp_comm_type), INTENT(IN)                     :: group
    1292              :       TYPE(particle_type), OPTIONAL, POINTER             :: core_particle_set(:), &
    1293              :                                                             shell_particle_set(:)
    1294              :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: core_vel(:, :), shell_vel(:, :)
    1295              : 
    1296              :       INTEGER                                            :: ii, iparticle, iparticle_kind, &
    1297              :                                                             iparticle_local, nparticle_kind, &
    1298              :                                                             nparticle_local, shell_index
    1299              :       LOGICAL                                            :: is_shell, present_vel
    1300              :       REAL(dp)                                           :: mass, mu_mass, v_sc(3)
    1301              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1302              :       TYPE(shell_kind_type), POINTER                     :: shell
    1303              : 
    1304         1840 :       present_vel = PRESENT(shell_vel)
    1305              :       ! Preliminary checks for consistency usage
    1306         1840 :       IF (present_vel) THEN
    1307          920 :          CPASSERT(PRESENT(core_vel))
    1308              :       ELSE
    1309          920 :          CPASSERT(PRESENT(shell_particle_set))
    1310          920 :          CPASSERT(PRESENT(core_particle_set))
    1311              :       END IF
    1312              :       ! get force on first thermostat for all the chains in the system.
    1313       154040 :       map_info%v_scale = 1.0_dp
    1314       154040 :       map_info%s_kin = 0.0_dp
    1315         1840 :       ii = 0
    1316              : 
    1317         1840 :       nparticle_kind = SIZE(atomic_kind_set)
    1318         5520 :       DO iparticle_kind = 1, nparticle_kind
    1319         3680 :          atomic_kind => atomic_kind_set(iparticle_kind)
    1320         3680 :          CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass, shell_active=is_shell, shell=shell)
    1321         5520 :          IF (is_shell) THEN
    1322         3680 :             mu_mass = shell%mass_shell*shell%mass_core/mass
    1323         3680 :             nparticle_local = local_particles%n_el(iparticle_kind)
    1324        92000 :             DO iparticle_local = 1, nparticle_local
    1325        88320 :                iparticle = local_particles%list(iparticle_kind)%array(iparticle_local)
    1326        88320 :                shell_index = particle_set(iparticle)%shell_index
    1327        88320 :                ii = ii + 1
    1328        92000 :                IF (present_vel) THEN
    1329        44160 :                   v_sc(1) = core_vel(1, shell_index) - shell_vel(1, shell_index)
    1330        44160 :                   v_sc(2) = core_vel(2, shell_index) - shell_vel(2, shell_index)
    1331        44160 :                   v_sc(3) = core_vel(3, shell_index) - shell_vel(3, shell_index)
    1332        44160 :                   map_info%p_kin(1, ii)%point = map_info%p_kin(1, ii)%point + mu_mass*v_sc(1)**2
    1333        44160 :                   map_info%p_kin(2, ii)%point = map_info%p_kin(2, ii)%point + mu_mass*v_sc(2)**2
    1334        44160 :                   map_info%p_kin(3, ii)%point = map_info%p_kin(3, ii)%point + mu_mass*v_sc(3)**2
    1335              :                ELSE
    1336        44160 :                   v_sc(1) = core_particle_set(shell_index)%v(1) - shell_particle_set(shell_index)%v(1)
    1337        44160 :                   v_sc(2) = core_particle_set(shell_index)%v(2) - shell_particle_set(shell_index)%v(2)
    1338        44160 :                   v_sc(3) = core_particle_set(shell_index)%v(3) - shell_particle_set(shell_index)%v(3)
    1339        44160 :                   map_info%p_kin(1, ii)%point = map_info%p_kin(1, ii)%point + mu_mass*v_sc(1)**2
    1340        44160 :                   map_info%p_kin(2, ii)%point = map_info%p_kin(2, ii)%point + mu_mass*v_sc(2)**2
    1341        44160 :                   map_info%p_kin(3, ii)%point = map_info%p_kin(3, ii)%point + mu_mass*v_sc(3)**2
    1342              :                END IF
    1343              :             END DO
    1344              :          END IF
    1345              :       END DO
    1346         2880 :       IF (map_info%dis_type == do_thermo_communication) CALL group%sum(map_info%s_kin)
    1347              : 
    1348         1840 :    END SUBROUTINE ke_region_shells
    1349              : 
    1350              : ! **************************************************************************************************
    1351              : !> \brief ...
    1352              : !> \param map_info ...
    1353              : !> \param atomic_kind_set ...
    1354              : !> \param particle_set ...
    1355              : !> \param local_particles ...
    1356              : !> \param shell_particle_set ...
    1357              : !> \param core_particle_set ...
    1358              : !> \param shell_vel ...
    1359              : !> \param core_vel ...
    1360              : !> \param vel ...
    1361              : !> \author 10.2007 [tlaino] - Teodoro Laino - University of Zurich
    1362              : ! **************************************************************************************************
    1363         1600 :    SUBROUTINE vel_rescale_shells(map_info, atomic_kind_set, particle_set, local_particles, &
    1364         1600 :                                  shell_particle_set, core_particle_set, shell_vel, core_vel, vel)
    1365              : 
    1366              :       TYPE(map_info_type), POINTER                       :: map_info
    1367              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind_set(:)
    1368              :       TYPE(particle_type), POINTER                       :: particle_set(:)
    1369              :       TYPE(distribution_1d_type), POINTER                :: local_particles
    1370              :       TYPE(particle_type), OPTIONAL, POINTER             :: shell_particle_set(:), &
    1371              :                                                             core_particle_set(:)
    1372              :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: shell_vel(:, :), core_vel(:, :), &
    1373              :                                                             vel(:, :)
    1374              : 
    1375              :       INTEGER                                            :: ii, iparticle, iparticle_kind, &
    1376              :                                                             iparticle_local, nparticle_kind, &
    1377              :                                                             nparticle_local, shell_index
    1378              :       LOGICAL                                            :: is_shell, present_vel
    1379              :       REAL(dp)                                           :: mass, massc, masss, umass, v(3), vc(3), &
    1380              :                                                             vs(3)
    1381              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
    1382              :       TYPE(shell_kind_type), POINTER                     :: shell
    1383              : 
    1384         1600 :       present_vel = PRESENT(vel)
    1385              :       ! Preliminary checks for consistency usage
    1386         1600 :       IF (present_vel) THEN
    1387          800 :          CPASSERT(PRESENT(shell_vel))
    1388          800 :          CPASSERT(PRESENT(core_vel))
    1389              :       ELSE
    1390          800 :          CPASSERT(PRESENT(shell_particle_set))
    1391          800 :          CPASSERT(PRESENT(core_particle_set))
    1392              :       END IF
    1393         1600 :       ii = 0
    1394         1600 :       nparticle_kind = SIZE(atomic_kind_set)
    1395              :       ! now scale the core-shell velocities
    1396         4800 :       Kind: DO iparticle_kind = 1, nparticle_kind
    1397         3200 :          atomic_kind => atomic_kind_set(iparticle_kind)
    1398         3200 :          CALL get_atomic_kind(atomic_kind=atomic_kind, mass=mass, shell_active=is_shell, shell=shell)
    1399         4800 :          IF (is_shell) THEN
    1400         3200 :             umass = 1.0_dp/mass
    1401         3200 :             masss = shell%mass_shell*umass
    1402         3200 :             massc = shell%mass_core*umass
    1403              : 
    1404         3200 :             nparticle_local = local_particles%n_el(iparticle_kind)
    1405        80000 :             Particles: DO iparticle_local = 1, nparticle_local
    1406        76800 :                iparticle = local_particles%list(iparticle_kind)%array(iparticle_local)
    1407        76800 :                shell_index = particle_set(iparticle)%shell_index
    1408        76800 :                ii = ii + 1
    1409        80000 :                IF (present_vel) THEN
    1410       153600 :                   vc(1:3) = core_vel(1:3, shell_index)
    1411       153600 :                   vs(1:3) = shell_vel(1:3, shell_index)
    1412       153600 :                   v(1:3) = vel(1:3, iparticle)
    1413        38400 :                   shell_vel(1, shell_index) = v(1) + map_info%p_scale(1, ii)%point*massc*(vs(1) - vc(1))
    1414        38400 :                   shell_vel(2, shell_index) = v(2) + map_info%p_scale(2, ii)%point*massc*(vs(2) - vc(2))
    1415        38400 :                   shell_vel(3, shell_index) = v(3) + map_info%p_scale(3, ii)%point*massc*(vs(3) - vc(3))
    1416        38400 :                   core_vel(1, shell_index) = v(1) + map_info%p_scale(1, ii)%point*masss*(vc(1) - vs(1))
    1417        38400 :                   core_vel(2, shell_index) = v(2) + map_info%p_scale(2, ii)%point*masss*(vc(2) - vs(2))
    1418        38400 :                   core_vel(3, shell_index) = v(3) + map_info%p_scale(3, ii)%point*masss*(vc(3) - vs(3))
    1419              :                ELSE
    1420       153600 :                   vc(1:3) = core_particle_set(shell_index)%v(1:3)
    1421       153600 :                   vs(1:3) = shell_particle_set(shell_index)%v(1:3)
    1422       153600 :                   v(1:3) = particle_set(iparticle)%v(1:3)
    1423        38400 :                   shell_particle_set(shell_index)%v(1) = v(1) + map_info%p_scale(1, ii)%point*massc*(vs(1) - vc(1))
    1424        38400 :                   shell_particle_set(shell_index)%v(2) = v(2) + map_info%p_scale(2, ii)%point*massc*(vs(2) - vc(2))
    1425        38400 :                   shell_particle_set(shell_index)%v(3) = v(3) + map_info%p_scale(3, ii)%point*massc*(vs(3) - vc(3))
    1426        38400 :                   core_particle_set(shell_index)%v(1) = v(1) + map_info%p_scale(1, ii)%point*masss*(vc(1) - vs(1))
    1427        38400 :                   core_particle_set(shell_index)%v(2) = v(2) + map_info%p_scale(2, ii)%point*masss*(vc(2) - vs(2))
    1428        38400 :                   core_particle_set(shell_index)%v(3) = v(3) + map_info%p_scale(3, ii)%point*masss*(vc(3) - vs(3))
    1429              :                END IF
    1430              :             END DO Particles
    1431              :          END IF
    1432              :       END DO Kind
    1433              : 
    1434         1600 :    END SUBROUTINE vel_rescale_shells
    1435              : 
    1436              : ! **************************************************************************************************
    1437              : !> \brief Calculates kinetic energy and potential energy of the nhc variables
    1438              : !> \param nhc ...
    1439              : !> \param nhc_pot ...
    1440              : !> \param nhc_kin ...
    1441              : !> \param para_env ...
    1442              : !> \param array_kin ...
    1443              : !> \param array_pot ...
    1444              : !> \par History
    1445              : !>      none
    1446              : !> \author CJM
    1447              : ! **************************************************************************************************
    1448        10668 :    SUBROUTINE get_nhc_energies(nhc, nhc_pot, nhc_kin, para_env, array_kin, array_pot)
    1449              :       TYPE(lnhc_parameters_type), POINTER                :: nhc
    1450              :       REAL(KIND=dp), INTENT(OUT)                         :: nhc_pot, nhc_kin
    1451              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1452              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: array_kin, array_pot
    1453              : 
    1454              :       INTEGER                                            :: imap, l, n, number
    1455              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: akin, vpot
    1456              : 
    1457        10668 :       number = nhc%glob_num_nhc
    1458        32004 :       ALLOCATE (akin(number))
    1459        32004 :       ALLOCATE (vpot(number))
    1460       774122 :       akin = 0.0_dp
    1461       774122 :       vpot = 0.0_dp
    1462       395929 :       DO n = 1, nhc%loc_num_nhc
    1463       385261 :          imap = nhc%map_info%index(n)
    1464      1796878 :          DO l = 1, nhc%nhc_len
    1465      1400949 :             akin(imap) = akin(imap) + 0.5_dp*nhc%nvt(l, n)%mass*nhc%nvt(l, n)%v**2
    1466      1786210 :             vpot(imap) = vpot(imap) + nhc%nvt(l, n)%nkt*nhc%nvt(l, n)%eta
    1467              :          END DO
    1468              :       END DO
    1469              : 
    1470              :       ! Handle the thermostat distribution
    1471        10668 :       IF (nhc%map_info%dis_type == do_thermo_no_communication) THEN
    1472         3726 :          CALL para_env%sum(akin)
    1473         3726 :          CALL para_env%sum(vpot)
    1474         6942 :       ELSE IF (nhc%map_info%dis_type == do_thermo_communication) THEN
    1475         4958 :          CALL communication_thermo_low1(akin, number, para_env)
    1476         4958 :          CALL communication_thermo_low1(vpot, number, para_env)
    1477              :       END IF
    1478       774122 :       nhc_kin = SUM(akin)
    1479       774122 :       nhc_pot = SUM(vpot)
    1480              : 
    1481              :       ! Possibly give back kinetic or potential energy arrays
    1482        10668 :       IF (PRESENT(array_pot)) THEN
    1483          274 :          IF (ASSOCIATED(array_pot)) THEN
    1484            0 :             CPASSERT(SIZE(array_pot) == number)
    1485              :          ELSE
    1486          822 :             ALLOCATE (array_pot(number))
    1487              :          END IF
    1488        35794 :          array_pot = vpot
    1489              :       END IF
    1490        10668 :       IF (PRESENT(array_kin)) THEN
    1491          274 :          IF (ASSOCIATED(array_kin)) THEN
    1492            0 :             CPASSERT(SIZE(array_kin) == number)
    1493              :          ELSE
    1494          822 :             ALLOCATE (array_kin(number))
    1495              :          END IF
    1496        35794 :          array_kin = akin
    1497              :       END IF
    1498        10668 :       DEALLOCATE (akin)
    1499        10668 :       DEALLOCATE (vpot)
    1500        10668 :    END SUBROUTINE get_nhc_energies
    1501              : 
    1502              : ! **************************************************************************************************
    1503              : !> \brief Calculates kinetic energy and potential energy
    1504              : !>      of the csvr  and gle thermostats
    1505              : !> \param map_info ...
    1506              : !> \param loc_num ...
    1507              : !> \param glob_num ...
    1508              : !> \param thermo_energy ...
    1509              : !> \param thermostat_kin ...
    1510              : !> \param para_env ...
    1511              : !> \param array_pot ...
    1512              : !> \param array_kin ...
    1513              : !> \par History generalized MI [07.2009]
    1514              : !> \author Teodoro Laino [tlaino] - 10.2007 - University of Zurich
    1515              : ! **************************************************************************************************
    1516         4528 :    SUBROUTINE get_kin_energies(map_info, loc_num, glob_num, thermo_energy, thermostat_kin, &
    1517              :                                para_env, array_pot, array_kin)
    1518              : 
    1519              :       TYPE(map_info_type), POINTER                       :: map_info
    1520              :       INTEGER, INTENT(IN)                                :: loc_num, glob_num
    1521              :       REAL(dp), DIMENSION(:), INTENT(IN)                 :: thermo_energy
    1522              :       REAL(KIND=dp), INTENT(OUT)                         :: thermostat_kin
    1523              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1524              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: array_pot, array_kin
    1525              : 
    1526              :       INTEGER                                            :: imap, n, number
    1527              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: akin
    1528              : 
    1529         4528 :       number = glob_num
    1530        13584 :       ALLOCATE (akin(number))
    1531       278678 :       akin = 0.0_dp
    1532       143360 :       DO n = 1, loc_num
    1533       138832 :          imap = map_info%index(n)
    1534       143360 :          akin(imap) = thermo_energy(n)
    1535              :       END DO
    1536              : 
    1537              :       ! Handle the thermostat distribution
    1538         4528 :       IF (map_info%dis_type == do_thermo_no_communication) THEN
    1539         1306 :          CALL para_env%sum(akin)
    1540         3222 :       ELSE IF (map_info%dis_type == do_thermo_communication) THEN
    1541         2534 :          CALL communication_thermo_low1(akin, number, para_env)
    1542              :       END IF
    1543       278678 :       thermostat_kin = SUM(akin)
    1544              : 
    1545              :       ! Possibly give back kinetic or potential energy arrays
    1546         4528 :       IF (PRESENT(array_pot)) THEN
    1547           22 :          IF (ASSOCIATED(array_pot)) THEN
    1548            0 :             CPASSERT(SIZE(array_pot) == number)
    1549              :          ELSE
    1550           66 :             ALLOCATE (array_pot(number))
    1551              :          END IF
    1552           66 :          array_pot = 0.0_dp
    1553              :       END IF
    1554         4528 :       IF (PRESENT(array_kin)) THEN
    1555          440 :          IF (ASSOCIATED(array_kin)) THEN
    1556          418 :             CPASSERT(SIZE(array_kin) == number)
    1557              :          ELSE
    1558           66 :             ALLOCATE (array_kin(number))
    1559              :          END IF
    1560        22856 :          array_kin = akin
    1561              :       END IF
    1562         4528 :       DEALLOCATE (akin)
    1563         4528 :    END SUBROUTINE get_kin_energies
    1564              : 
    1565              : ! **************************************************************************************************
    1566              : !> \brief Calculates the temperatures of the regions when a thermostat is
    1567              : !>        applied
    1568              : !> \param map_info ...
    1569              : !> \param loc_num ...
    1570              : !> \param glob_num ...
    1571              : !> \param nkt ...
    1572              : !> \param dof ...
    1573              : !> \param para_env ...
    1574              : !> \param temp_tot ...
    1575              : !> \param array_temp ...
    1576              : !> \par History generalized MI [07.2009]
    1577              : !> \author Teodoro Laino [tlaino] - 10.2007 - University of Zurich
    1578              : ! **************************************************************************************************
    1579          274 :    SUBROUTINE get_temperatures(map_info, loc_num, glob_num, nkt, dof, para_env, &
    1580              :                                temp_tot, array_temp)
    1581              :       TYPE(map_info_type), POINTER                       :: map_info
    1582              :       INTEGER, INTENT(IN)                                :: loc_num, glob_num
    1583              :       REAL(dp), DIMENSION(:), INTENT(IN)                 :: nkt, dof
    1584              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1585              :       REAL(KIND=dp), INTENT(OUT)                         :: temp_tot
    1586              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: array_temp
    1587              : 
    1588              :       INTEGER                                            :: i, imap, imap2, n, number
    1589              :       REAL(KIND=dp)                                      :: fdeg_of_free
    1590              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: akin, deg_of_free
    1591              : 
    1592          274 :       number = glob_num
    1593          822 :       ALLOCATE (akin(number))
    1594          822 :       ALLOCATE (deg_of_free(number))
    1595        35816 :       akin = 0.0_dp
    1596        35816 :       deg_of_free = 0.0_dp
    1597        18120 :       DO n = 1, loc_num
    1598        17846 :          imap = map_info%index(n)
    1599        17846 :          imap2 = map_info%map_index(n)
    1600        17846 :          IF (nkt(n) == 0.0_dp) CYCLE
    1601        17846 :          deg_of_free(imap) = REAL(dof(n), KIND=dp)
    1602        18120 :          akin(imap) = map_info%s_kin(imap2)
    1603              :       END DO
    1604              : 
    1605              :       ! Handle the thermostat distribution
    1606          274 :       IF (map_info%dis_type == do_thermo_no_communication) THEN
    1607          146 :          CALL para_env%sum(akin)
    1608          146 :          CALL para_env%sum(deg_of_free)
    1609          128 :       ELSE IF (map_info%dis_type == do_thermo_communication) THEN
    1610           22 :          CALL communication_thermo_low1(akin, number, para_env)
    1611           22 :          CALL communication_thermo_low1(deg_of_free, number, para_env)
    1612              :       END IF
    1613        35816 :       temp_tot = SUM(akin)
    1614        35816 :       fdeg_of_free = SUM(deg_of_free)
    1615              : 
    1616          274 :       temp_tot = temp_tot/fdeg_of_free
    1617          274 :       temp_tot = cp_unit_from_cp2k(temp_tot, "K_temp")
    1618              :       ! Possibly give back temperatures of the full set of regions
    1619          274 :       IF (PRESENT(array_temp)) THEN
    1620          274 :          IF (ASSOCIATED(array_temp)) THEN
    1621            0 :             CPASSERT(SIZE(array_temp) == number)
    1622              :          ELSE
    1623          822 :             ALLOCATE (array_temp(number))
    1624              :          END IF
    1625        35816 :          DO i = 1, number
    1626        35542 :             array_temp(i) = akin(i)/deg_of_free(i)
    1627        35816 :             array_temp(i) = cp_unit_from_cp2k(array_temp(i), "K_temp")
    1628              :          END DO
    1629              :       END IF
    1630          274 :       DEALLOCATE (akin)
    1631          274 :       DEALLOCATE (deg_of_free)
    1632          274 :    END SUBROUTINE get_temperatures
    1633              : 
    1634              : ! **************************************************************************************************
    1635              : !> \brief Calculates energy associated with a thermostat
    1636              : !> \param thermostat ...
    1637              : !> \param thermostat_pot ...
    1638              : !> \param thermostat_kin ...
    1639              : !> \param para_env ...
    1640              : !> \param array_pot ...
    1641              : !> \param array_kin ...
    1642              : !> \author Teodoro Laino [tlaino] - 10.2007 - University of Zurich
    1643              : ! **************************************************************************************************
    1644        57049 :    SUBROUTINE get_thermostat_energies(thermostat, thermostat_pot, thermostat_kin, para_env, &
    1645              :                                       array_pot, array_kin)
    1646              :       TYPE(thermostat_type), POINTER                     :: thermostat
    1647              :       REAL(KIND=dp), INTENT(OUT)                         :: thermostat_pot, thermostat_kin
    1648              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1649              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: array_pot, array_kin
    1650              : 
    1651              :       INTEGER                                            :: i
    1652        57049 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: thermo_energy
    1653              : 
    1654        57049 :       thermostat_pot = 0.0_dp
    1655        57049 :       thermostat_kin = 0.0_dp
    1656        57049 :       IF (ASSOCIATED(thermostat)) THEN
    1657        14464 :          IF (thermostat%type_of_thermostat == do_thermo_nose) THEN
    1658              :             ! Energy associated with the Nose-Hoover thermostat
    1659        10338 :             CPASSERT(ASSOCIATED(thermostat%nhc))
    1660              :             CALL get_nhc_energies(thermostat%nhc, thermostat_pot, thermostat_kin, para_env, &
    1661        10338 :                                   array_pot, array_kin)
    1662         4126 :          ELSE IF (thermostat%type_of_thermostat == do_thermo_csvr) THEN
    1663              :             ! Energy associated with the CSVR thermostat
    1664         3702 :             CPASSERT(ASSOCIATED(thermostat%csvr))
    1665        11106 :             ALLOCATE (thermo_energy(thermostat%csvr%loc_num_csvr))
    1666        65100 :             DO i = 1, thermostat%csvr%loc_num_csvr
    1667        65100 :                thermo_energy(i) = thermostat%csvr%nvt(i)%thermostat_energy
    1668              :             END DO
    1669              :             CALL get_kin_energies(thermostat%csvr%map_info, thermostat%csvr%loc_num_csvr, &
    1670              :                                   thermostat%csvr%glob_num_csvr, thermo_energy, &
    1671         3702 :                                   thermostat_kin, para_env, array_pot, array_kin)
    1672         3702 :             DEALLOCATE (thermo_energy)
    1673              : 
    1674          424 :          ELSE IF (thermostat%type_of_thermostat == do_thermo_gle) THEN
    1675              :             ! Energy associated with the GLE thermostat
    1676          408 :             CPASSERT(ASSOCIATED(thermostat%gle))
    1677         1224 :             ALLOCATE (thermo_energy(thermostat%gle%loc_num_gle))
    1678        66504 :             DO i = 1, thermostat%gle%loc_num_gle
    1679        66504 :                thermo_energy(i) = thermostat%gle%nvt(i)%thermostat_energy
    1680              :             END DO
    1681              :             CALL get_kin_energies(thermostat%gle%map_info, thermostat%gle%loc_num_gle, &
    1682              :                                   thermostat%gle%glob_num_gle, thermo_energy, &
    1683          408 :                                   thermostat_kin, para_env, array_pot, array_kin)
    1684          408 :             DEALLOCATE (thermo_energy)
    1685              : 
    1686              :             ![NB] nothing to do for Ad-Langevin?
    1687              : 
    1688              :          END IF
    1689              :       END IF
    1690              : 
    1691        57049 :    END SUBROUTINE get_thermostat_energies
    1692              : 
    1693              : ! **************************************************************************************************
    1694              : !> \brief Calculates the temperatures for each region associated to a thermostat
    1695              : !> \param thermostat ...
    1696              : !> \param tot_temperature ...
    1697              : !> \param para_env ...
    1698              : !> \param array_temp ...
    1699              : !> \author Teodoro Laino [tlaino] - 02.2008 - University of Zurich
    1700              : ! **************************************************************************************************
    1701          274 :    SUBROUTINE get_region_temperatures(thermostat, tot_temperature, para_env, array_temp)
    1702              :       TYPE(thermostat_type), POINTER                     :: thermostat
    1703              :       REAL(KIND=dp), INTENT(OUT)                         :: tot_temperature
    1704              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1705              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: array_temp
    1706              : 
    1707              :       INTEGER                                            :: i
    1708          274 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: dof, nkt
    1709              : 
    1710          274 :       IF (ASSOCIATED(thermostat)) THEN
    1711          274 :          IF (thermostat%type_of_thermostat == do_thermo_nose) THEN
    1712              :             ! Energy associated with the Nose-Hoover thermostat
    1713          252 :             CPASSERT(ASSOCIATED(thermostat%nhc))
    1714          756 :             ALLOCATE (nkt(thermostat%nhc%loc_num_nhc))
    1715          756 :             ALLOCATE (dof(thermostat%nhc%loc_num_nhc))
    1716        18054 :             DO i = 1, thermostat%nhc%loc_num_nhc
    1717        17802 :                nkt(i) = thermostat%nhc%nvt(1, i)%nkt
    1718        18054 :                dof(i) = REAL(thermostat%nhc%nvt(1, i)%degrees_of_freedom, KIND=dp)
    1719              :             END DO
    1720              :             CALL get_temperatures(thermostat%nhc%map_info, thermostat%nhc%loc_num_nhc, &
    1721          252 :                                   thermostat%nhc%glob_num_nhc, nkt, dof, para_env, tot_temperature, array_temp)
    1722          252 :             DEALLOCATE (nkt)
    1723          252 :             DEALLOCATE (dof)
    1724           22 :          ELSE IF (thermostat%type_of_thermostat == do_thermo_csvr) THEN
    1725              :             ! Energy associated with the CSVR thermostat
    1726           22 :             CPASSERT(ASSOCIATED(thermostat%csvr))
    1727              : 
    1728           66 :             ALLOCATE (nkt(thermostat%csvr%loc_num_csvr))
    1729           66 :             ALLOCATE (dof(thermostat%csvr%loc_num_csvr))
    1730           66 :             DO i = 1, thermostat%csvr%loc_num_csvr
    1731           44 :                nkt(i) = thermostat%csvr%nvt(i)%nkt
    1732           66 :                dof(i) = REAL(thermostat%csvr%nvt(i)%degrees_of_freedom, KIND=dp)
    1733              :             END DO
    1734              :             CALL get_temperatures(thermostat%csvr%map_info, thermostat%csvr%loc_num_csvr, &
    1735           22 :                                   thermostat%csvr%glob_num_csvr, nkt, dof, para_env, tot_temperature, array_temp)
    1736           22 :             DEALLOCATE (nkt)
    1737           22 :             DEALLOCATE (dof)
    1738            0 :          ELSE IF (thermostat%type_of_thermostat == do_thermo_al) THEN
    1739              :             ! Energy associated with the AD_LANGEVIN thermostat
    1740            0 :             CPASSERT(ASSOCIATED(thermostat%al))
    1741              : 
    1742            0 :             ALLOCATE (nkt(thermostat%al%loc_num_al))
    1743            0 :             ALLOCATE (dof(thermostat%al%loc_num_al))
    1744            0 :             DO i = 1, thermostat%al%loc_num_al
    1745            0 :                nkt(i) = thermostat%al%nvt(i)%nkt
    1746            0 :                dof(i) = REAL(thermostat%al%nvt(i)%degrees_of_freedom, KIND=dp)
    1747              :             END DO
    1748              :             CALL get_temperatures(thermostat%al%map_info, thermostat%al%loc_num_al, &
    1749            0 :                                   thermostat%al%glob_num_al, nkt, dof, para_env, tot_temperature, array_temp)
    1750            0 :             DEALLOCATE (nkt)
    1751            0 :             DEALLOCATE (dof)
    1752            0 :          ELSE IF (thermostat%type_of_thermostat == do_thermo_gle) THEN
    1753              :             ! Energy associated with the GLE thermostat
    1754            0 :             CPASSERT(ASSOCIATED(thermostat%gle))
    1755              : 
    1756            0 :             ALLOCATE (nkt(thermostat%gle%loc_num_gle))
    1757            0 :             ALLOCATE (dof(thermostat%gle%loc_num_gle))
    1758            0 :             DO i = 1, thermostat%gle%loc_num_gle
    1759            0 :                nkt(i) = thermostat%gle%nvt(i)%nkt
    1760            0 :                dof(i) = REAL(thermostat%gle%nvt(i)%degrees_of_freedom, KIND=dp)
    1761              :             END DO
    1762              :             CALL get_temperatures(thermostat%gle%map_info, thermostat%gle%loc_num_gle, &
    1763            0 :                                   thermostat%gle%glob_num_gle, nkt, dof, para_env, tot_temperature, array_temp)
    1764            0 :             DEALLOCATE (nkt)
    1765            0 :             DEALLOCATE (dof)
    1766              :          END IF
    1767              :       END IF
    1768              : 
    1769          274 :    END SUBROUTINE get_region_temperatures
    1770              : 
    1771              : ! **************************************************************************************************
    1772              : !> \brief Prints status of all thermostats during an MD run
    1773              : !> \param thermostats ...
    1774              : !> \param para_env ...
    1775              : !> \param my_pos ...
    1776              : !> \param my_act ...
    1777              : !> \param itimes ...
    1778              : !> \param time ...
    1779              : !> \author Teodoro Laino [tlaino] - 02.2008 - University of Zurich
    1780              : ! **************************************************************************************************
    1781        43875 :    SUBROUTINE print_thermostats_status(thermostats, para_env, my_pos, my_act, itimes, time)
    1782              :       TYPE(thermostats_type), POINTER                    :: thermostats
    1783              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1784              :       CHARACTER(LEN=default_string_length)               :: my_pos, my_act
    1785              :       INTEGER, INTENT(IN)                                :: itimes
    1786              :       REAL(KIND=dp), INTENT(IN)                          :: time
    1787              : 
    1788        43875 :       IF (ASSOCIATED(thermostats)) THEN
    1789        10478 :          IF (ASSOCIATED(thermostats%thermostat_part)) THEN
    1790        10144 :             CALL print_thermostat_status(thermostats%thermostat_part, para_env, my_pos, my_act, itimes, time)
    1791              :          END IF
    1792        10478 :          IF (ASSOCIATED(thermostats%thermostat_shell)) THEN
    1793          830 :             CALL print_thermostat_status(thermostats%thermostat_shell, para_env, my_pos, my_act, itimes, time)
    1794              :          END IF
    1795        10478 :          IF (ASSOCIATED(thermostats%thermostat_coef)) THEN
    1796            0 :             CALL print_thermostat_status(thermostats%thermostat_coef, para_env, my_pos, my_act, itimes, time)
    1797              :          END IF
    1798        10478 :          IF (ASSOCIATED(thermostats%thermostat_baro)) THEN
    1799         2302 :             CALL print_thermostat_status(thermostats%thermostat_baro, para_env, my_pos, my_act, itimes, time)
    1800              :          END IF
    1801              :       END IF
    1802        43875 :    END SUBROUTINE print_thermostats_status
    1803              : 
    1804              : ! **************************************************************************************************
    1805              : !> \brief Prints status of a specific thermostat
    1806              : !> \param thermostat ...
    1807              : !> \param para_env ...
    1808              : !> \param my_pos ...
    1809              : !> \param my_act ...
    1810              : !> \param itimes ...
    1811              : !> \param time ...
    1812              : !> \author Teodoro Laino [tlaino] - 02.2008 - University of Zurich
    1813              : ! **************************************************************************************************
    1814        13276 :    SUBROUTINE print_thermostat_status(thermostat, para_env, my_pos, my_act, itimes, time)
    1815              :       TYPE(thermostat_type), POINTER                     :: thermostat
    1816              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1817              :       CHARACTER(LEN=default_string_length)               :: my_pos, my_act
    1818              :       INTEGER, INTENT(IN)                                :: itimes
    1819              :       REAL(KIND=dp), INTENT(IN)                          :: time
    1820              : 
    1821              :       INTEGER                                            :: i, unit
    1822              :       LOGICAL                                            :: new_file
    1823              :       REAL(KIND=dp)                                      :: thermo_kin, thermo_pot, tot_temperature
    1824        13276 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: array_kin, array_pot, array_temp
    1825              :       TYPE(cp_logger_type), POINTER                      :: logger
    1826              :       TYPE(section_vals_type), POINTER                   :: print_key
    1827              : 
    1828        13276 :       NULLIFY (logger, print_key, array_pot, array_kin, array_temp)
    1829        26552 :       logger => cp_get_default_logger()
    1830              : 
    1831        13276 :       IF (ASSOCIATED(thermostat)) THEN
    1832              :          ! Print Energies
    1833        13276 :          print_key => section_vals_get_subs_vals(thermostat%section, "PRINT%ENERGY")
    1834        13276 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    1835          296 :             CALL get_thermostat_energies(thermostat, thermo_pot, thermo_kin, para_env, array_pot, array_kin)
    1836              :             unit = cp_print_key_unit_nr(logger, thermostat%section, "PRINT%ENERGY", &
    1837              :                                         extension="."//TRIM(thermostat%label)//".tener", file_position=my_pos, &
    1838          296 :                                         file_action=my_act, is_new_file=new_file)
    1839          296 :             IF (unit > 0) THEN
    1840          148 :                IF (new_file) THEN
    1841           13 :                   WRITE (unit, '(A)') "# Thermostat Potential and Kinetic Energies - Total and per Region"
    1842           13 :                   WRITE (unit, '("#",3X,A,2X,A,13X,A,10X,A)') "Step Nr.", "Time[fs]", "Kin.[a.u.]", "Pot.[a.u.]"
    1843              :                END IF
    1844          148 :                WRITE (UNIT=unit, FMT="(I8, F12.3,6X,2F20.10)") itimes, time*femtoseconds, thermo_kin, thermo_pot
    1845          148 :                WRITE (unit, '(A,4F20.10)') "# KINETIC ENERGY REGIONS: ", array_kin(1:MIN(4, SIZE(array_kin)))
    1846         4499 :                DO i = 5, SIZE(array_kin), 4
    1847         4499 :                   WRITE (UNIT=unit, FMT='("#",25X,4F20.10)') array_kin(i:MIN(i + 3, SIZE(array_kin)))
    1848              :                END DO
    1849          148 :                WRITE (unit, '(A,4F20.10)') "# POTENT. ENERGY REGIONS: ", array_pot(1:MIN(4, SIZE(array_pot)))
    1850         4499 :                DO i = 5, SIZE(array_pot), 4
    1851         4499 :                   WRITE (UNIT=unit, FMT='("#",25X,4F20.10)') array_pot(i:MIN(i + 3, SIZE(array_pot)))
    1852              :                END DO
    1853          148 :                CALL m_flush(unit)
    1854              :             END IF
    1855          296 :             DEALLOCATE (array_kin)
    1856          296 :             DEALLOCATE (array_pot)
    1857          296 :             CALL cp_print_key_finished_output(unit, logger, thermostat%section, "PRINT%ENERGY")
    1858              :          END IF
    1859              :          ! Print Temperatures of the regions
    1860        13276 :          print_key => section_vals_get_subs_vals(thermostat%section, "PRINT%TEMPERATURE")
    1861        13276 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
    1862          274 :             CALL get_region_temperatures(thermostat, tot_temperature, para_env, array_temp)
    1863              :             unit = cp_print_key_unit_nr(logger, thermostat%section, "PRINT%TEMPERATURE", &
    1864              :                                         extension="."//TRIM(thermostat%label)//".temp", file_position=my_pos, &
    1865          274 :                                         file_action=my_act, is_new_file=new_file)
    1866          274 :             IF (unit > 0) THEN
    1867          137 :                IF (new_file) THEN
    1868           12 :                   WRITE (unit, '(A)') "# Temperature Total and per Region"
    1869           12 :                   WRITE (unit, '("#",3X,A,2X,A,10X,A)') "Step Nr.", "Time[fs]", "Temp.[K]"
    1870              :                END IF
    1871          137 :                WRITE (UNIT=unit, FMT="(I8, F12.3,3X,F20.10)") itimes, time*femtoseconds, tot_temperature
    1872          137 :                WRITE (unit, '(A,I10)') "# TEMPERATURE REGIONS: ", SIZE(array_temp)
    1873         4625 :                DO i = 1, SIZE(array_temp), 4
    1874         4625 :                   WRITE (UNIT=unit, FMT='("#",22X,4F20.10)') array_temp(i:MIN(i + 3, SIZE(array_temp)))
    1875              :                END DO
    1876          137 :                CALL m_flush(unit)
    1877              :             END IF
    1878          274 :             DEALLOCATE (array_temp)
    1879          274 :             CALL cp_print_key_finished_output(unit, logger, thermostat%section, "PRINT%TEMPERATURE")
    1880              :          END IF
    1881              :       END IF
    1882        13276 :    END SUBROUTINE print_thermostat_status
    1883              : 
    1884              : ! **************************************************************************************************
    1885              : !> \brief Handles the communication for thermostats (1D array)
    1886              : !> \param array ...
    1887              : !> \param number ...
    1888              : !> \param para_env ...
    1889              : !> \author Teodoro Laino [tlaino] - University of Zurich 11.2007
    1890              : ! **************************************************************************************************
    1891        12494 :    SUBROUTINE communication_thermo_low1(array, number, para_env)
    1892              :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: array
    1893              :       INTEGER, INTENT(IN)                                :: number
    1894              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1895              : 
    1896              :       INTEGER                                            :: i, icheck, ncheck
    1897        12494 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: work, work2
    1898              : 
    1899        37482 :       ALLOCATE (work(para_env%num_pe))
    1900        26020 :       DO i = 1, number
    1901        40578 :          work = 0.0_dp
    1902        13526 :          work(para_env%mepos + 1) = array(i)
    1903        67630 :          CALL para_env%sum(work)
    1904        40578 :          ncheck = COUNT(work /= 0.0_dp)
    1905        13526 :          array(i) = 0.0_dp
    1906        26020 :          IF (ncheck /= 0) THEN
    1907        38202 :             ALLOCATE (work2(ncheck))
    1908        12734 :             ncheck = 0
    1909        38202 :             DO icheck = 1, para_env%num_pe
    1910        38202 :                IF (work(icheck) /= 0.0_dp) THEN
    1911        25060 :                   ncheck = ncheck + 1
    1912        25060 :                   work2(ncheck) = work(icheck)
    1913              :                END IF
    1914              :             END DO
    1915        12734 :             CPASSERT(ncheck == SIZE(work2))
    1916        37794 :             CPASSERT(ALL(work2 == work2(1)))
    1917              : 
    1918        12734 :             array(i) = work2(1)
    1919        12734 :             DEALLOCATE (work2)
    1920              :          END IF
    1921              :       END DO
    1922        12494 :       DEALLOCATE (work)
    1923        12494 :    END SUBROUTINE communication_thermo_low1
    1924              : 
    1925              : ! **************************************************************************************************
    1926              : !> \brief Handles the communication for thermostats (2D array)
    1927              : !> \param array ...
    1928              : !> \param number1 ...
    1929              : !> \param number2 ...
    1930              : !> \param para_env ...
    1931              : !> \author Teodoro Laino [tlaino] - University of Zurich 11.2007
    1932              : ! **************************************************************************************************
    1933          250 :    SUBROUTINE communication_thermo_low2(array, number1, number2, para_env)
    1934              :       INTEGER, DIMENSION(:, :), INTENT(INOUT)            :: array
    1935              :       INTEGER, INTENT(IN)                                :: number1, number2
    1936              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1937              : 
    1938              :       INTEGER                                            :: i, icheck, j, ncheck
    1939          250 :       INTEGER, DIMENSION(:, :), POINTER                  :: work, work2
    1940              : 
    1941         1000 :       ALLOCATE (work(number1, para_env%num_pe))
    1942          606 :       DO i = 1, number2
    1943       309364 :          work = 0
    1944       154504 :          work(:, para_env%mepos + 1) = array(:, i)
    1945       618372 :          CALL para_env%sum(work)
    1946          356 :          ncheck = 0
    1947         1068 :          DO j = 1, para_env%num_pe
    1948        23584 :             IF (ANY(work(:, j) /= 0)) THEN
    1949          660 :                ncheck = ncheck + 1
    1950              :             END IF
    1951              :          END DO
    1952       154504 :          array(:, i) = 0
    1953          606 :          IF (ncheck /= 0) THEN
    1954         1424 :             ALLOCATE (work2(number1, ncheck))
    1955          356 :             ncheck = 0
    1956         1068 :             DO icheck = 1, para_env%num_pe
    1957        23584 :                IF (ANY(work(:, icheck) /= 0)) THEN
    1958          660 :                   ncheck = ncheck + 1
    1959       572880 :                   work2(:, ncheck) = work(:, icheck)
    1960              :                END IF
    1961              :             END DO
    1962          356 :             CPASSERT(ncheck == SIZE(work2, 2))
    1963         1016 :             DO j = 1, ncheck
    1964       286796 :                CPASSERT(ALL(work2(:, j) == work2(:, 1)))
    1965              :             END DO
    1966       154504 :             array(:, i) = work2(:, 1)
    1967          356 :             DEALLOCATE (work2)
    1968              :          END IF
    1969              :       END DO
    1970          250 :       DEALLOCATE (work)
    1971          250 :    END SUBROUTINE communication_thermo_low2
    1972              : 
    1973              : END MODULE thermostat_utils
        

Generated by: LCOV version 2.0-1