LCOV - code coverage report
Current view: top level - src/motion/thermostat - thermostat_mapping.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:42dac4a) Lines: 54.4 % 557 303
Test Date: 2025-07-25 12:55:17 Functions: 62.5 % 8 5

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \author Teodoro Laino [tlaino] - 10.2007 - University of Zurich
      10              : ! **************************************************************************************************
      11              : MODULE thermostat_mapping
      12              : 
      13              :    USE cell_types,                      ONLY: use_perd_x,&
      14              :                                               use_perd_xy,&
      15              :                                               use_perd_xyz,&
      16              :                                               use_perd_xz,&
      17              :                                               use_perd_y,&
      18              :                                               use_perd_yz,&
      19              :                                               use_perd_z
      20              :    USE distribution_1d_types,           ONLY: distribution_1d_type
      21              :    USE extended_system_types,           ONLY: map_info_type
      22              :    USE input_constants,                 ONLY: do_region_defined,&
      23              :                                               do_region_global,&
      24              :                                               do_region_massive,&
      25              :                                               do_region_molecule,&
      26              :                                               do_thermo_communication,&
      27              :                                               do_thermo_no_communication
      28              :    USE kinds,                           ONLY: dp
      29              :    USE memory_utilities,                ONLY: reallocate
      30              :    USE message_passing,                 ONLY: mp_para_env_type
      31              :    USE molecule_kind_types,             ONLY: colvar_constraint_type,&
      32              :                                               fixd_constraint_type,&
      33              :                                               g3x3_constraint_type,&
      34              :                                               g4x6_constraint_type,&
      35              :                                               get_molecule_kind,&
      36              :                                               molecule_kind_type
      37              :    USE molecule_types,                  ONLY: get_molecule,&
      38              :                                               global_constraint_type,&
      39              :                                               molecule_type
      40              :    USE simpar_types,                    ONLY: simpar_type
      41              :    USE util,                            ONLY: locate,&
      42              :                                               sort
      43              : #include "../../base/base_uses.f90"
      44              : 
      45              :    IMPLICIT NONE
      46              : 
      47              :    PUBLIC :: thermostat_mapping_region, &
      48              :              adiabatic_mapping_region, &
      49              :              init_baro_map_info
      50              : 
      51              :    PRIVATE
      52              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'thermostat_mapping'
      53              : 
      54              : CONTAINS
      55              : ! **************************************************************************************************
      56              : !> \brief Main general setup for adiabatic thermostat regions (Nose only)
      57              : !> \param map_info ...
      58              : !> \param deg_of_freedom ...
      59              : !> \param massive_atom_list ...
      60              : !> \param molecule_kind_set ...
      61              : !> \param local_molecules ...
      62              : !> \param molecule_set ...
      63              : !> \param para_env ...
      64              : !> \param natoms_local ...
      65              : !> \param simpar ...
      66              : !> \param number ...
      67              : !> \param region ...
      68              : !> \param gci ...
      69              : !> \param shell ...
      70              : !> \param map_loc_thermo_gen ...
      71              : !> \param sum_of_thermostats ...
      72              : !> \author CJM - PNNL
      73              : ! **************************************************************************************************
      74            0 :    SUBROUTINE adiabatic_mapping_region(map_info, deg_of_freedom, massive_atom_list, &
      75              :                                        molecule_kind_set, local_molecules, molecule_set, para_env, natoms_local, simpar, &
      76              :                                        number, region, gci, shell, map_loc_thermo_gen, sum_of_thermostats)
      77              : 
      78              :       TYPE(map_info_type), POINTER                       :: map_info
      79              :       INTEGER, DIMENSION(:), POINTER                     :: deg_of_freedom, massive_atom_list
      80              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
      81              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
      82              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
      83              :       TYPE(mp_para_env_type), POINTER                    :: para_env
      84              :       INTEGER, INTENT(OUT)                               :: natoms_local
      85              :       TYPE(simpar_type), POINTER                         :: simpar
      86              :       INTEGER, INTENT(INOUT)                             :: number
      87              :       INTEGER, INTENT(IN)                                :: region
      88              :       TYPE(global_constraint_type), POINTER              :: gci
      89              :       LOGICAL, INTENT(IN)                                :: shell
      90              :       INTEGER, DIMENSION(:), POINTER                     :: map_loc_thermo_gen
      91              :       INTEGER, INTENT(INOUT)                             :: sum_of_thermostats
      92              : 
      93              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'adiabatic_mapping_region'
      94              : 
      95              :       INTEGER                                            :: handle, nkind, nmol_local, nsize, &
      96              :                                                             number_of_thermostats
      97            0 :       INTEGER, DIMENSION(:), POINTER                     :: const_mol, tot_const
      98            0 :       INTEGER, DIMENSION(:, :), POINTER                  :: point
      99              : 
     100            0 :       CALL timeset(routineN, handle)
     101              : 
     102            0 :       NULLIFY (const_mol, tot_const, point)
     103            0 :       CPASSERT(.NOT. ASSOCIATED(deg_of_freedom))
     104            0 :       CPASSERT(.NOT. ASSOCIATED(massive_atom_list))
     105              : 
     106            0 :       nkind = SIZE(molecule_kind_set)
     107              :       CALL adiabatic_region_evaluate(map_info%dis_type, natoms_local, nmol_local, &
     108              :                                      const_mol, tot_const, point, local_molecules, molecule_kind_set, molecule_set, &
     109            0 :                                      simpar, shell)
     110              : 
     111              :       ! Now we can allocate the target array s_kin and p_kin..
     112            0 :       SELECT CASE (region)
     113              :       CASE (do_region_global, do_region_molecule, do_region_massive)
     114            0 :          nsize = number
     115              :       CASE DEFAULT
     116              :          ! STOP PROGRAM
     117              :       END SELECT
     118            0 :       ALLOCATE (map_info%s_kin(nsize))
     119            0 :       ALLOCATE (map_info%v_scale(nsize))
     120            0 :       ALLOCATE (map_info%p_kin(3, natoms_local))
     121            0 :       ALLOCATE (map_info%p_scale(3, natoms_local))
     122              : ! nullify thermostat pointers
     123              :       ! Allocate index array to 1
     124            0 :       ALLOCATE (map_info%index(1))
     125            0 :       ALLOCATE (map_info%map_index(1))
     126            0 :       ALLOCATE (deg_of_freedom(1))
     127              : 
     128              :       CALL massive_list_generate(molecule_set, molecule_kind_set, &
     129            0 :                                  local_molecules, para_env, massive_atom_list, region, shell)
     130              : 
     131              :       CALL adiabatic_mapping_region_low(region, map_info, nkind, point, &
     132              :                                         deg_of_freedom, local_molecules, const_mol, massive_atom_list, &
     133              :                                         tot_const, molecule_set, number_of_thermostats, shell, gci, &
     134            0 :                                         map_loc_thermo_gen)
     135              : 
     136            0 :       number = number_of_thermostats
     137            0 :       sum_of_thermostats = number
     138            0 :       CALL para_env%sum(sum_of_thermostats)
     139              : 
     140              : !    check = (number==number_of_thermostats)
     141              : !    CPPrecondition(check,cp_fatal_level,routineP,failure)
     142            0 :       DEALLOCATE (const_mol)
     143            0 :       DEALLOCATE (tot_const)
     144            0 :       DEALLOCATE (point)
     145              : 
     146            0 :       CALL timestop(handle)
     147              : 
     148            0 :    END SUBROUTINE adiabatic_mapping_region
     149              : 
     150              : ! **************************************************************************************************
     151              : !> \brief Performs the real mapping for the thermostat region
     152              : !> \param region ...
     153              : !> \param map_info ...
     154              : !> \param nkind ...
     155              : !> \param point ...
     156              : !> \param deg_of_freedom ...
     157              : !> \param local_molecules ...
     158              : !> \param const_mol ...
     159              : !> \param massive_atom_list ...
     160              : !> \param tot_const ...
     161              : !> \param molecule_set ...
     162              : !> \param ntherm ...
     163              : !> \param shell ...
     164              : !> \param gci ...
     165              : !> \param map_loc_thermo_gen ...
     166              : !> \author Teodoro Laino [tlaino] - University of Zurich - 10.2007
     167              : ! **************************************************************************************************
     168            0 :    SUBROUTINE adiabatic_mapping_region_low(region, map_info, nkind, point, &
     169              :                                            deg_of_freedom, local_molecules, const_mol, massive_atom_list, tot_const, &
     170              :                                            molecule_set, ntherm, shell, gci, map_loc_thermo_gen)
     171              : 
     172              :       INTEGER, INTENT(IN)                                :: region
     173              :       TYPE(map_info_type), POINTER                       :: map_info
     174              :       INTEGER                                            :: nkind
     175              :       INTEGER, DIMENSION(:, :), POINTER                  :: point
     176              :       INTEGER, DIMENSION(:), POINTER                     :: deg_of_freedom
     177              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
     178              :       INTEGER, DIMENSION(:), POINTER                     :: const_mol, massive_atom_list, tot_const
     179              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
     180              :       INTEGER, INTENT(OUT)                               :: ntherm
     181              :       LOGICAL, INTENT(IN)                                :: shell
     182              :       TYPE(global_constraint_type), POINTER              :: gci
     183              :       INTEGER, DIMENSION(:), POINTER                     :: map_loc_thermo_gen
     184              : 
     185              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'adiabatic_mapping_region_low'
     186              : 
     187              :       INTEGER :: first_atom, first_shell, glob_therm_num, handle, icount, ielement, ii, ikind, &
     188              :          imol, imol_local, ipart, jj, k, kk, last_atom, last_shell, nglob_cns, nmol_local, number
     189              :       LOGICAL                                            :: check, global_constraints, &
     190              :                                                             have_thermostat
     191              :       REAL(dp), SAVE, TARGET                             :: unity
     192              :       TYPE(molecule_type), POINTER                       :: molecule
     193              : 
     194            0 :       CALL timeset(routineN, handle)
     195            0 :       unity = 1.0_dp
     196            0 :       global_constraints = ASSOCIATED(gci)
     197            0 :       deg_of_freedom = 0
     198            0 :       icount = 0
     199            0 :       number = 0
     200            0 :       ntherm = 0
     201            0 :       nglob_cns = 0
     202            0 :       IF (global_constraints) nglob_cns = gci%ntot - gci%nrestraint
     203            0 :       IF (region == do_region_global) THEN
     204              :          ! Global Region
     205            0 :          check = (map_info%dis_type == do_thermo_communication)
     206            0 :          CPASSERT(check)
     207            0 :          DO ikind = 1, nkind
     208            0 :             DO jj = point(1, ikind), point(2, ikind)
     209            0 :                IF (map_loc_thermo_gen(jj) /= HUGE(0)) THEN
     210            0 :                   DO ii = 1, 3
     211            0 :                      map_info%p_kin(ii, jj)%point => map_info%s_kin(1)
     212            0 :                      map_info%p_scale(ii, jj)%point => map_info%v_scale(1)
     213              :                   END DO
     214              :                ELSE
     215            0 :                   DO ii = 1, 3
     216            0 :                      NULLIFY (map_info%p_kin(ii, jj)%point)
     217            0 :                      map_info%p_scale(ii, jj)%point => unity
     218              :                   END DO
     219              :                END IF
     220              :             END DO
     221            0 :             deg_of_freedom(1) = deg_of_freedom(1) + tot_const(ikind)
     222            0 :             map_info%index(1) = 1
     223            0 :             map_info%map_index(1) = 1
     224            0 :             number = 1
     225              :          END DO
     226            0 :          deg_of_freedom(1) = deg_of_freedom(1) + nglob_cns
     227            0 :       ELSE IF (region == do_region_molecule) THEN
     228              :          ! Molecular Region
     229            0 :          IF (map_info%dis_type == do_thermo_no_communication) THEN
     230              :             ! This is the standard case..
     231            0 :             DO ikind = 1, nkind
     232            0 :                nmol_local = local_molecules%n_el(ikind)
     233            0 :                DO imol_local = 1, nmol_local
     234            0 :                   imol = local_molecules%list(ikind)%array(imol_local)
     235            0 :                   number = number + 1
     236            0 :                   have_thermostat = .TRUE.
     237              : ! determine if the local molecule belongs to a thermostat
     238            0 :                   DO kk = point(1, number), point(2, number)
     239              :                      !  WRITE ( *, * ) 'kk', size(map_loc_thermo_gen), kk, map_loc_thermo_gen ( kk )
     240            0 :                      IF (map_loc_thermo_gen(kk) == HUGE(0)) THEN
     241              :                         have_thermostat = .FALSE.
     242              :                         EXIT
     243              :                      END IF
     244              :                   END DO
     245              : ! If molecule has a thermostat, then map
     246            0 :                   IF (have_thermostat) THEN
     247              : ! glob_therm_num is the global thermostat number attached to the local molecule
     248              : ! We can test to make sure all atoms in the local molecule belong to the same
     249              : ! global thermostat as a way to detect errors.
     250            0 :                      glob_therm_num = map_loc_thermo_gen(point(1, number))
     251            0 :                      ntherm = ntherm + 1
     252            0 :                      CALL reallocate(map_info%index, 1, ntherm)
     253            0 :                      CALL reallocate(map_info%map_index, 1, ntherm)
     254            0 :                      CALL reallocate(deg_of_freedom, 1, ntherm)
     255            0 :                      map_info%index(ntherm) = glob_therm_num
     256            0 :                      map_info%map_index(ntherm) = ntherm
     257            0 :                      deg_of_freedom(ntherm) = const_mol(number)
     258            0 :                      DO kk = point(1, number), point(2, number)
     259            0 :                         DO jj = 1, 3
     260            0 :                            map_info%p_kin(jj, kk)%point => map_info%s_kin(ntherm)
     261            0 :                            map_info%p_scale(jj, kk)%point => map_info%v_scale(ntherm)
     262              :                         END DO
     263              :                      END DO
     264              : ! If molecule has no thermostat, then nullify pointers to that atom
     265              :                   ELSE
     266            0 :                      DO kk = point(1, number), point(2, number)
     267            0 :                         DO jj = 1, 3
     268            0 :                            NULLIFY (map_info%p_kin(jj, kk)%point)
     269            0 :                            map_info%p_scale(jj, kk)%point => unity
     270              :                         END DO
     271              :                      END DO
     272              :                   END IF
     273              :                END DO
     274              :             END DO
     275            0 :          ELSE IF (map_info%dis_type == do_thermo_communication) THEN
     276              :             ! This case is quite rare and happens only when we have one molecular
     277              :             ! kind and one molecule..
     278            0 :             CPASSERT(nkind == 1)
     279            0 :             number = number + 1
     280            0 :             ntherm = ntherm + 1
     281            0 :             map_info%index(ntherm) = ntherm
     282            0 :             map_info%map_index(ntherm) = ntherm
     283            0 :             deg_of_freedom(ntherm) = deg_of_freedom(ntherm) + tot_const(nkind)
     284            0 :             DO kk = point(1, nkind), point(2, nkind)
     285            0 :                IF (map_loc_thermo_gen(kk) /= HUGE(0)) THEN
     286            0 :                   DO jj = 1, 3
     287            0 :                      map_info%p_kin(jj, kk)%point => map_info%s_kin(ntherm)
     288            0 :                      map_info%p_scale(jj, kk)%point => map_info%v_scale(ntherm)
     289              :                   END DO
     290              :                ELSE
     291              :                END IF
     292            0 :                DO jj = 1, 3
     293            0 :                   NULLIFY (map_info%p_kin(jj, kk)%point)
     294            0 :                   map_info%p_scale(jj, kk)%point => unity
     295              :                END DO
     296              :             END DO
     297              :          ELSE
     298            0 :             CPABORT("")
     299              :          END IF
     300            0 :          IF (nglob_cns /= 0) THEN
     301            0 :             CPABORT("Molecular thermostats with global constraints are impossible!")
     302              :          END IF
     303            0 :       ELSE IF (region == do_region_massive) THEN
     304              :          ! Massive Region
     305            0 :          check = (map_info%dis_type == do_thermo_no_communication)
     306            0 :          CPASSERT(check)
     307            0 :          DO ikind = 1, nkind
     308            0 :             nmol_local = local_molecules%n_el(ikind)
     309            0 :             DO imol_local = 1, nmol_local
     310            0 :                icount = icount + 1
     311            0 :                imol = local_molecules%list(ikind)%array(imol_local)
     312            0 :                molecule => molecule_set(imol)
     313              :                CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom, &
     314            0 :                                  first_shell=first_shell, last_shell=last_shell)
     315            0 :                IF (shell) THEN
     316            0 :                   first_atom = first_shell
     317            0 :                   last_atom = last_shell
     318              :                ELSE
     319            0 :                   IF ((tot_const(icount) > 0) .OR. (nglob_cns /= 0)) THEN
     320            0 :                      CPABORT("Massive thermostats with constraints are impossible!")
     321              :                   END IF
     322              :                END IF
     323            0 :                k = 0
     324              : 
     325            0 :                have_thermostat = .TRUE.
     326            0 :                DO ii = point(1, icount), point(2, icount)
     327            0 :                   IF (map_loc_thermo_gen(ii) /= 1) THEN
     328              :                      have_thermostat = .FALSE.
     329              :                      EXIT
     330              :                   END IF
     331              :                END DO
     332              : 
     333            0 :                IF (have_thermostat) THEN
     334            0 :                   DO ii = point(1, icount), point(2, icount)
     335            0 :                      ipart = first_atom + k
     336            0 :                      ielement = locate(massive_atom_list, ipart)
     337            0 :                      k = k + 1
     338            0 :                      DO jj = 1, 3
     339            0 :                         ntherm = ntherm + 1
     340            0 :                         CALL reallocate(map_info%index, 1, ntherm)
     341            0 :                         CALL reallocate(map_info%map_index, 1, ntherm)
     342            0 :                         map_info%index(ntherm) = (ielement - 1)*3 + jj
     343            0 :                         map_info%map_index(ntherm) = ntherm
     344            0 :                         map_info%p_kin(jj, ii)%point => map_info%s_kin(ntherm)
     345            0 :                         map_info%p_scale(jj, ii)%point => map_info%v_scale(ntherm)
     346              :                      END DO
     347              :                   END DO
     348              :                ELSE
     349            0 :                   DO ii = point(1, icount), point(2, icount)
     350            0 :                      DO jj = 1, 3
     351            0 :                         NULLIFY (map_info%p_kin(jj, ii)%point)
     352            0 :                         map_info%p_scale(jj, ii)%point => unity
     353              :                      END DO
     354              :                   END DO
     355              :                END IF
     356            0 :                IF (first_atom + k - 1 /= last_atom) THEN
     357            0 :                   CPABORT("Inconsistent mapping of particles")
     358              :                END IF
     359              :             END DO
     360              :          END DO
     361              :       ELSE
     362            0 :          CPABORT("Invalid region!")
     363              :       END IF
     364              : 
     365            0 :       CALL timestop(handle)
     366              : 
     367            0 :    END SUBROUTINE adiabatic_mapping_region_low
     368              : 
     369              : ! **************************************************************************************************
     370              : !> \brief creates the mapping between the system and the thermostats
     371              : !> \param dis_type ...
     372              : !> \param natoms_local ...
     373              : !> \param nmol_local ...
     374              : !> \param const_mol ...
     375              : !> \param tot_const ...
     376              : !> \param point ...
     377              : !> \param local_molecules ...
     378              : !> \param molecule_kind_set ...
     379              : !> \param molecule_set ...
     380              : !> \param simpar ...
     381              : !> \param shell ...
     382              : !> \author Teodoro Laino [tlaino] - 10.2007 - University of Zurich
     383              : ! **************************************************************************************************
     384            0 :    SUBROUTINE adiabatic_region_evaluate(dis_type, natoms_local, nmol_local, const_mol, &
     385              :                                         tot_const, point, local_molecules, molecule_kind_set, molecule_set, simpar, shell)
     386              :       INTEGER, INTENT(IN)                                :: dis_type
     387              :       INTEGER, INTENT(OUT)                               :: natoms_local, nmol_local
     388              :       INTEGER, DIMENSION(:), POINTER                     :: const_mol, tot_const
     389              :       INTEGER, DIMENSION(:, :), POINTER                  :: point
     390              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
     391              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
     392              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
     393              :       TYPE(simpar_type), POINTER                         :: simpar
     394              :       LOGICAL, INTENT(IN)                                :: shell
     395              : 
     396              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'adiabatic_region_evaluate'
     397              : 
     398              :       INTEGER :: atm_offset, first_atom, handle, icount, ikind, ilist, imol, imol_local, katom, &
     399              :          last_atom, natom, nc, nfixd, nkind, nmol_per_kind, nmolecule, nshell
     400            0 :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
     401              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     402              :       TYPE(molecule_type), POINTER                       :: molecule
     403              : 
     404            0 :       CALL timeset(routineN, handle)
     405              : 
     406            0 :       natoms_local = 0
     407            0 :       nmol_local = 0
     408            0 :       nkind = SIZE(molecule_kind_set)
     409            0 :       NULLIFY (fixd_list, molecule_kind, molecule)
     410              :       ! Compute the TOTAL number of molecules and atoms on THIS PROC and
     411              :       ! TOTAL number of molecules of IKIND on THIS PROC
     412            0 :       DO ikind = 1, nkind
     413            0 :          molecule_kind => molecule_kind_set(ikind)
     414            0 :          CALL get_molecule_kind(molecule_kind, natom=natom, nshell=nshell)
     415            0 :          IF (shell) THEN
     416            0 :             IF (nshell /= 0) THEN
     417            0 :                natoms_local = natoms_local + nshell*local_molecules%n_el(ikind)
     418            0 :                nmol_local = nmol_local + local_molecules%n_el(ikind)
     419              :             END IF
     420              :          ELSE
     421            0 :             natoms_local = natoms_local + natom*local_molecules%n_el(ikind)
     422            0 :             nmol_local = nmol_local + local_molecules%n_el(ikind)
     423              :          END IF
     424              :       END DO
     425              : 
     426            0 :       CPASSERT(.NOT. ASSOCIATED(const_mol))
     427            0 :       CPASSERT(.NOT. ASSOCIATED(tot_const))
     428            0 :       CPASSERT(.NOT. ASSOCIATED(point))
     429            0 :       IF (dis_type == do_thermo_no_communication) THEN
     430            0 :          ALLOCATE (const_mol(nmol_local))
     431            0 :          ALLOCATE (tot_const(nmol_local))
     432            0 :          ALLOCATE (point(2, nmol_local))
     433              : 
     434            0 :          point(:, :) = 0
     435              :          atm_offset = 0
     436              :          icount = 0
     437            0 :          DO ikind = 1, nkind
     438            0 :             nmol_per_kind = local_molecules%n_el(ikind)
     439            0 :             molecule_kind => molecule_kind_set(ikind)
     440              :             CALL get_molecule_kind(molecule_kind, nconstraint=nc, natom=natom, &
     441            0 :                                    fixd_list=fixd_list, nshell=nshell)
     442            0 :             IF (shell) natom = nshell
     443            0 :             DO imol_local = 1, nmol_per_kind
     444            0 :                icount = icount + 1
     445            0 :                point(1, icount) = atm_offset + 1
     446            0 :                point(2, icount) = atm_offset + natom
     447            0 :                IF (.NOT. shell) THEN
     448              :                   ! nc keeps track of all constraints but not fixed ones..
     449              :                   ! Let's identify fixed atoms for this molecule
     450            0 :                   nfixd = 0
     451            0 :                   imol = local_molecules%list(ikind)%array(imol_local)
     452            0 :                   molecule => molecule_set(imol)
     453            0 :                   CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     454            0 :                   IF (ASSOCIATED(fixd_list)) THEN
     455            0 :                      DO katom = first_atom, last_atom
     456            0 :                         DO ilist = 1, SIZE(fixd_list)
     457            0 :                            IF ((katom == fixd_list(ilist)%fixd) .AND. &
     458            0 :                                (.NOT. fixd_list(ilist)%restraint%active)) THEN
     459            0 :                               SELECT CASE (fixd_list(ilist)%itype)
     460              :                               CASE (use_perd_x, use_perd_y, use_perd_z)
     461            0 :                                  nfixd = nfixd + 1
     462              :                               CASE (use_perd_xy, use_perd_xz, use_perd_yz)
     463            0 :                                  nfixd = nfixd + 2
     464              :                               CASE (use_perd_xyz)
     465            0 :                                  nfixd = nfixd + 3
     466              :                               END SELECT
     467              :                            END IF
     468              :                         END DO
     469              :                      END DO
     470              :                   END IF
     471            0 :                   const_mol(icount) = nc + nfixd
     472            0 :                   tot_const(icount) = const_mol(icount)
     473              :                END IF
     474            0 :                atm_offset = point(2, icount)
     475              :             END DO
     476              :          END DO
     477            0 :       ELSE IF (dis_type == do_thermo_communication) THEN
     478            0 :          ALLOCATE (const_mol(nkind))
     479            0 :          ALLOCATE (tot_const(nkind))
     480            0 :          ALLOCATE (point(2, nkind))
     481            0 :          point(:, :) = 0
     482              :          atm_offset = 0
     483              :          ! nc keeps track of all constraints but not fixed ones..
     484            0 :          DO ikind = 1, nkind
     485            0 :             nmol_per_kind = local_molecules%n_el(ikind)
     486            0 :             molecule_kind => molecule_kind_set(ikind)
     487              :             CALL get_molecule_kind(molecule_kind, nconstraint=nc, natom=natom, &
     488            0 :                                    nmolecule=nmolecule, nconstraint_fixd=nfixd, nshell=nshell)
     489            0 :             IF (shell) natom = nshell
     490            0 :             IF (.NOT. shell) THEN
     491            0 :                const_mol(ikind) = nc
     492              :                ! Let's consider the fixed atoms only for the total number of constraints
     493              :                ! in case we are in REPLICATED/INTERACTING thermostats
     494            0 :                tot_const(ikind) = const_mol(ikind)*nmolecule + nfixd
     495              :             END IF
     496            0 :             point(1, ikind) = atm_offset + 1
     497            0 :             point(2, ikind) = atm_offset + natom*nmol_per_kind
     498            0 :             atm_offset = point(2, ikind)
     499              :          END DO
     500              :       END IF
     501            0 :       IF ((.NOT. simpar%constraint) .OR. shell) THEN
     502            0 :          const_mol = 0
     503            0 :          tot_const = 0
     504              :       END IF
     505              : 
     506            0 :       CALL timestop(handle)
     507              : 
     508            0 :    END SUBROUTINE adiabatic_region_evaluate
     509              : 
     510              : ! **************************************************************************************************
     511              : !> \brief Main general setup thermostat regions (thermostat independent)
     512              : !> \param map_info ...
     513              : !> \param deg_of_freedom ...
     514              : !> \param massive_atom_list ...
     515              : !> \param molecule_kind_set ...
     516              : !> \param local_molecules ...
     517              : !> \param molecule_set ...
     518              : !> \param para_env ...
     519              : !> \param natoms_local ...
     520              : !> \param simpar ...
     521              : !> \param number ...
     522              : !> \param region ...
     523              : !> \param gci ...
     524              : !> \param shell ...
     525              : !> \param map_loc_thermo_gen ...
     526              : !> \param sum_of_thermostats ...
     527              : !> \author Teodoro Laino [tlaino] - University of Zurich - 10.2007
     528              : ! **************************************************************************************************
     529          574 :    SUBROUTINE thermostat_mapping_region(map_info, deg_of_freedom, massive_atom_list, &
     530              :                                         molecule_kind_set, local_molecules, molecule_set, para_env, natoms_local, simpar, &
     531              :                                         number, region, gci, shell, map_loc_thermo_gen, sum_of_thermostats)
     532              : 
     533              :       TYPE(map_info_type), POINTER                       :: map_info
     534              :       INTEGER, DIMENSION(:), POINTER                     :: deg_of_freedom, massive_atom_list
     535              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
     536              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
     537              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
     538              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     539              :       INTEGER, INTENT(OUT)                               :: natoms_local
     540              :       TYPE(simpar_type), POINTER                         :: simpar
     541              :       INTEGER, INTENT(IN)                                :: number, region
     542              :       TYPE(global_constraint_type), POINTER              :: gci
     543              :       LOGICAL, INTENT(IN)                                :: shell
     544              :       INTEGER, DIMENSION(:), POINTER                     :: map_loc_thermo_gen
     545              :       INTEGER, INTENT(IN)                                :: sum_of_thermostats
     546              : 
     547              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'thermostat_mapping_region'
     548              : 
     549              :       INTEGER                                            :: handle, nkind, nmol_local, nsize, &
     550              :                                                             number_of_thermostats
     551          574 :       INTEGER, DIMENSION(:), POINTER                     :: const_mol, tot_const
     552          574 :       INTEGER, DIMENSION(:, :), POINTER                  :: point
     553              :       LOGICAL                                            :: check
     554              : 
     555          574 :       CALL timeset(routineN, handle)
     556              : 
     557          574 :       NULLIFY (const_mol, tot_const, point)
     558          574 :       CPASSERT(.NOT. ASSOCIATED(deg_of_freedom))
     559          574 :       CPASSERT(.NOT. ASSOCIATED(massive_atom_list))
     560              : 
     561          574 :       nkind = SIZE(molecule_kind_set)
     562              :       CALL mapping_region_evaluate(map_info%dis_type, natoms_local, nmol_local, &
     563              :                                    const_mol, tot_const, point, local_molecules, molecule_kind_set, molecule_set, &
     564          574 :                                    region, simpar, shell, map_loc_thermo_gen, sum_of_thermostats, para_env)
     565              : 
     566              :       ! Now we can allocate the target array s_kin and p_kin..
     567         1116 :       SELECT CASE (region)
     568              :       CASE (do_region_global, do_region_molecule, do_region_massive)
     569          542 :          nsize = number
     570              :       CASE (do_region_defined)
     571          574 :          nsize = sum_of_thermostats
     572              :       END SELECT
     573         1722 :       ALLOCATE (map_info%s_kin(nsize))
     574         1722 :       ALLOCATE (map_info%v_scale(nsize))
     575       343736 :       ALLOCATE (map_info%p_kin(3, natoms_local))
     576       343726 :       ALLOCATE (map_info%p_scale(3, natoms_local))
     577              :       ! Allocate index array
     578         1722 :       ALLOCATE (map_info%index(number))
     579         1722 :       ALLOCATE (map_info%map_index(number))
     580         1722 :       ALLOCATE (deg_of_freedom(number))
     581              : 
     582              :       CALL massive_list_generate(molecule_set, molecule_kind_set, &
     583          574 :                                  local_molecules, para_env, massive_atom_list, region, shell)
     584              : 
     585              :       CALL thermostat_mapping_region_low(region, map_info, nkind, point, &
     586              :                                          deg_of_freedom, local_molecules, const_mol, massive_atom_list, &
     587              :                                          tot_const, molecule_set, number_of_thermostats, shell, gci, &
     588          574 :                                          map_loc_thermo_gen)
     589              : 
     590          574 :       check = (number == number_of_thermostats)
     591          574 :       CPASSERT(check)
     592          574 :       DEALLOCATE (const_mol)
     593          574 :       DEALLOCATE (tot_const)
     594          574 :       DEALLOCATE (point)
     595              : 
     596          574 :       CALL timestop(handle)
     597              : 
     598         1722 :    END SUBROUTINE thermostat_mapping_region
     599              : 
     600              : ! **************************************************************************************************
     601              : !> \brief Performs the real mapping for the thermostat region
     602              : !> \param region ...
     603              : !> \param map_info ...
     604              : !> \param nkind ...
     605              : !> \param point ...
     606              : !> \param deg_of_freedom ...
     607              : !> \param local_molecules ...
     608              : !> \param const_mol ...
     609              : !> \param massive_atom_list ...
     610              : !> \param tot_const ...
     611              : !> \param molecule_set ...
     612              : !> \param number ...
     613              : !> \param shell ...
     614              : !> \param gci ...
     615              : !> \param map_loc_thermo_gen ...
     616              : !> \author Teodoro Laino [tlaino] - University of Zurich - 10.2007
     617              : ! **************************************************************************************************
     618          574 :    SUBROUTINE thermostat_mapping_region_low(region, map_info, nkind, point, &
     619              :                                             deg_of_freedom, local_molecules, const_mol, massive_atom_list, tot_const, &
     620              :                                             molecule_set, number, shell, gci, map_loc_thermo_gen)
     621              : 
     622              :       INTEGER, INTENT(IN)                                :: region
     623              :       TYPE(map_info_type), POINTER                       :: map_info
     624              :       INTEGER                                            :: nkind
     625              :       INTEGER, DIMENSION(:, :), POINTER                  :: point
     626              :       INTEGER, DIMENSION(:), POINTER                     :: deg_of_freedom
     627              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
     628              :       INTEGER, DIMENSION(:), POINTER                     :: const_mol, massive_atom_list, tot_const
     629              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
     630              :       INTEGER, INTENT(OUT)                               :: number
     631              :       LOGICAL, INTENT(IN)                                :: shell
     632              :       TYPE(global_constraint_type), POINTER              :: gci
     633              :       INTEGER, DIMENSION(:), POINTER                     :: map_loc_thermo_gen
     634              : 
     635              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'thermostat_mapping_region_low'
     636              : 
     637              :       INTEGER :: first_atom, first_shell, handle, i, icount, ielement, ii, ikind, imap, imol, &
     638              :          imol_local, ipart, itmp, jj, k, kk, last_atom, last_shell, nglob_cns, nmol_local
     639          574 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: tmp, wrk
     640              :       LOGICAL                                            :: check, global_constraints
     641              :       TYPE(molecule_type), POINTER                       :: molecule
     642              : 
     643          574 :       CALL timeset(routineN, handle)
     644              : 
     645          574 :       global_constraints = ASSOCIATED(gci)
     646        77944 :       deg_of_freedom = 0
     647          574 :       icount = 0
     648          574 :       number = 0
     649          574 :       nglob_cns = 0
     650          574 :       IF (global_constraints) nglob_cns = gci%ntot - gci%nrestraint
     651          574 :       IF (region == do_region_global) THEN
     652              :          ! Global Region
     653          274 :          check = (map_info%dis_type == do_thermo_communication)
     654          274 :          CPASSERT(check)
     655        15238 :          DO ikind = 1, nkind
     656        39463 :             DO jj = point(1, ikind), point(2, ikind)
     657       112960 :                DO ii = 1, 3
     658        73497 :                   map_info%p_kin(ii, jj)%point => map_info%s_kin(1)
     659        97996 :                   map_info%p_scale(ii, jj)%point => map_info%v_scale(1)
     660              :                END DO
     661              :             END DO
     662        14964 :             deg_of_freedom(1) = deg_of_freedom(1) + tot_const(ikind)
     663        14964 :             map_info%index(1) = 1
     664        14964 :             map_info%map_index(1) = 1
     665        15238 :             number = 1
     666              :          END DO
     667          274 :          deg_of_freedom(1) = deg_of_freedom(1) + nglob_cns
     668          300 :       ELSE IF (region == do_region_defined) THEN
     669              :          ! User defined Region to thermostat
     670           32 :          check = (map_info%dis_type == do_thermo_communication)
     671           32 :          CPASSERT(check)
     672              :          ! Lets' identify the matching of the local thermostat w.r.t. the global one
     673           32 :          itmp = SIZE(map_loc_thermo_gen)
     674           96 :          ALLOCATE (tmp(itmp))
     675           64 :          ALLOCATE (wrk(itmp))
     676        22001 :          tmp(:) = map_loc_thermo_gen
     677           32 :          CALL sort(tmp, itmp, wrk)
     678           32 :          number = 1
     679           32 :          map_info%index(number) = tmp(1)
     680           32 :          map_info%map_index(number) = tmp(1)
     681           32 :          deg_of_freedom(number) = tot_const(tmp(1))
     682        21969 :          DO i = 2, itmp
     683        21969 :             IF (tmp(i) /= tmp(i - 1)) THEN
     684           40 :                number = number + 1
     685           40 :                map_info%index(number) = tmp(i)
     686           40 :                map_info%map_index(number) = tmp(i)
     687           40 :                deg_of_freedom(number) = tot_const(tmp(i))
     688              :             END IF
     689              :          END DO
     690           32 :          DEALLOCATE (tmp)
     691           32 :          DEALLOCATE (wrk)
     692        22001 :          DO jj = 1, SIZE(map_loc_thermo_gen)
     693        87908 :             DO ii = 1, 3
     694        65907 :                imap = map_loc_thermo_gen(jj)
     695        65907 :                map_info%p_kin(ii, jj)%point => map_info%s_kin(imap)
     696        87876 :                map_info%p_scale(ii, jj)%point => map_info%v_scale(imap)
     697              :             END DO
     698              :          END DO
     699           32 :          IF (nglob_cns /= 0) THEN
     700              :             CALL cp_abort(__LOCATION__, &
     701            0 :                           "User Defined thermostats with global constraints not implemented!")
     702              :          END IF
     703          268 :       ELSE IF (region == do_region_molecule) THEN
     704              :          ! Molecular Region
     705          136 :          IF (map_info%dis_type == do_thermo_no_communication) THEN
     706              :             ! This is the standard case..
     707         6044 :             DO ikind = 1, nkind
     708         5912 :                nmol_local = local_molecules%n_el(ikind)
     709        13008 :                DO imol_local = 1, nmol_local
     710         6964 :                   imol = local_molecules%list(ikind)%array(imol_local)
     711         6964 :                   number = number + 1
     712         6964 :                   map_info%index(number) = imol
     713         6964 :                   map_info%map_index(number) = number
     714         6964 :                   deg_of_freedom(number) = const_mol(number)
     715        28554 :                   DO kk = point(1, number), point(2, number)
     716        69676 :                      DO jj = 1, 3
     717        47034 :                         map_info%p_kin(jj, kk)%point => map_info%s_kin(number)
     718        62712 :                         map_info%p_scale(jj, kk)%point => map_info%v_scale(number)
     719              :                      END DO
     720              :                   END DO
     721              :                END DO
     722              :             END DO
     723            4 :          ELSE IF (map_info%dis_type == do_thermo_communication) THEN
     724              :             ! This case is quite rare and happens only when we have one molecular
     725              :             ! kind and one molecule..
     726            4 :             CPASSERT(nkind == 1)
     727            4 :             number = number + 1
     728            4 :             map_info%index(number) = number
     729            4 :             map_info%map_index(number) = number
     730            4 :             deg_of_freedom(number) = deg_of_freedom(number) + tot_const(nkind)
     731           12 :             DO kk = point(1, nkind), point(2, nkind)
     732           36 :                DO jj = 1, 3
     733           24 :                   map_info%p_kin(jj, kk)%point => map_info%s_kin(number)
     734           32 :                   map_info%p_scale(jj, kk)%point => map_info%v_scale(number)
     735              :                END DO
     736              :             END DO
     737              :          ELSE
     738            0 :             CPABORT("")
     739              :          END IF
     740          136 :          IF (nglob_cns /= 0) THEN
     741            0 :             CPABORT("Molecular thermostats with global constraints are impossible!")
     742              :          END IF
     743          132 :       ELSE IF (region == do_region_massive) THEN
     744              :          ! Massive Region
     745          132 :          check = (map_info%dis_type == do_thermo_no_communication)
     746          132 :          CPASSERT(check)
     747         8882 :          DO ikind = 1, nkind
     748         8750 :             nmol_local = local_molecules%n_el(ikind)
     749        16128 :             DO imol_local = 1, nmol_local
     750         7246 :                icount = icount + 1
     751         7246 :                imol = local_molecules%list(ikind)%array(imol_local)
     752         7246 :                molecule => molecule_set(imol)
     753              :                CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom, &
     754         7246 :                                  first_shell=first_shell, last_shell=last_shell)
     755         7246 :                IF (shell) THEN
     756          904 :                   first_atom = first_shell
     757          904 :                   last_atom = last_shell
     758              :                ELSE
     759         6342 :                   IF ((tot_const(icount) > 0) .OR. (nglob_cns /= 0)) THEN
     760            0 :                      CPABORT("Massive thermostats with constraints are impossible!")
     761              :                   END IF
     762              :                END IF
     763         7246 :                k = 0
     764        30598 :                DO ii = point(1, icount), point(2, icount)
     765        23352 :                   ipart = first_atom + k
     766        23352 :                   ielement = locate(massive_atom_list, ipart)
     767        23352 :                   k = k + 1
     768       100654 :                   DO jj = 1, 3
     769        70056 :                      number = number + 1
     770        70056 :                      map_info%index(number) = (ielement - 1)*3 + jj
     771        70056 :                      map_info%map_index(number) = number
     772        70056 :                      map_info%p_kin(jj, ii)%point => map_info%s_kin(number)
     773        93408 :                      map_info%p_scale(jj, ii)%point => map_info%v_scale(number)
     774              :                   END DO
     775              :                END DO
     776        15996 :                IF (first_atom + k - 1 /= last_atom) THEN
     777            0 :                   CPABORT("Inconsistent mapping of particles")
     778              :                END IF
     779              :             END DO
     780              :          END DO
     781              :       ELSE
     782            0 :          CPABORT("Invalid region!")
     783              :       END IF
     784              : 
     785          574 :       CALL timestop(handle)
     786              : 
     787          574 :    END SUBROUTINE thermostat_mapping_region_low
     788              : 
     789              : ! **************************************************************************************************
     790              : !> \brief creates the mapping between the system and the thermostats
     791              : !> \param dis_type ...
     792              : !> \param natoms_local ...
     793              : !> \param nmol_local ...
     794              : !> \param const_mol ...
     795              : !> \param tot_const ...
     796              : !> \param point ...
     797              : !> \param local_molecules ...
     798              : !> \param molecule_kind_set ...
     799              : !> \param molecule_set ...
     800              : !> \param region ...
     801              : !> \param simpar ...
     802              : !> \param shell ...
     803              : !> \param map_loc_thermo_gen ...
     804              : !> \param sum_of_thermostats ...
     805              : !> \param para_env ...
     806              : !> \author Teodoro Laino [tlaino] - 10.2007 - University of Zurich
     807              : ! **************************************************************************************************
     808          574 :    SUBROUTINE mapping_region_evaluate(dis_type, natoms_local, nmol_local, const_mol, &
     809              :                                       tot_const, point, local_molecules, molecule_kind_set, molecule_set, region, &
     810              :                                       simpar, shell, map_loc_thermo_gen, sum_of_thermostats, para_env)
     811              :       INTEGER, INTENT(IN)                                :: dis_type
     812              :       INTEGER, INTENT(OUT)                               :: natoms_local, nmol_local
     813              :       INTEGER, DIMENSION(:), POINTER                     :: const_mol, tot_const
     814              :       INTEGER, DIMENSION(:, :), POINTER                  :: point
     815              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
     816              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
     817              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
     818              :       INTEGER, INTENT(IN)                                :: region
     819              :       TYPE(simpar_type), POINTER                         :: simpar
     820              :       LOGICAL, INTENT(IN)                                :: shell
     821              :       INTEGER, DIMENSION(:), POINTER                     :: map_loc_thermo_gen
     822              :       INTEGER, INTENT(IN)                                :: sum_of_thermostats
     823              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     824              : 
     825              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'mapping_region_evaluate'
     826              : 
     827              :       INTEGER :: atm_offset, first_atom, handle, i, iatm, icount, id_region, ikind, ilist, imol, &
     828              :          imol_local, j, jatm, katom, last_atom, natom, nc, nfixd, nkind, nmol_per_kind, nmolecule, &
     829              :          nshell
     830              :       TYPE(colvar_constraint_type), DIMENSION(:), &
     831          574 :          POINTER                                         :: colv_list
     832          574 :       TYPE(fixd_constraint_type), DIMENSION(:), POINTER  :: fixd_list
     833          574 :       TYPE(g3x3_constraint_type), DIMENSION(:), POINTER  :: g3x3_list
     834          574 :       TYPE(g4x6_constraint_type), DIMENSION(:), POINTER  :: g4x6_list
     835              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     836              :       TYPE(molecule_type), POINTER                       :: molecule
     837              : 
     838          574 :       CALL timeset(routineN, handle)
     839              : 
     840          574 :       natoms_local = 0
     841          574 :       nmol_local = 0
     842          574 :       nkind = SIZE(molecule_kind_set)
     843          574 :       NULLIFY (fixd_list, molecule_kind, molecule, colv_list, g3x3_list, g4x6_list)
     844              :       ! Compute the TOTAL number of molecules and atoms on THIS PROC and
     845              :       ! TOTAL number of molecules of IKIND on THIS PROC
     846        30270 :       DO ikind = 1, nkind
     847        29696 :          molecule_kind => molecule_kind_set(ikind)
     848        29696 :          CALL get_molecule_kind(molecule_kind, natom=natom, nshell=nshell)
     849        30270 :          IF (shell) THEN
     850           82 :             IF (nshell /= 0) THEN
     851           82 :                natoms_local = natoms_local + nshell*local_molecules%n_el(ikind)
     852           82 :                nmol_local = nmol_local + local_molecules%n_el(ikind)
     853              :             END IF
     854              :          ELSE
     855        29614 :             natoms_local = natoms_local + natom*local_molecules%n_el(ikind)
     856        29614 :             nmol_local = nmol_local + local_molecules%n_el(ikind)
     857              :          END IF
     858              :       END DO
     859              : 
     860          574 :       CPASSERT(.NOT. ASSOCIATED(const_mol))
     861          574 :       CPASSERT(.NOT. ASSOCIATED(tot_const))
     862          574 :       CPASSERT(.NOT. ASSOCIATED(point))
     863          574 :       IF (dis_type == do_thermo_no_communication) THEN
     864          792 :          ALLOCATE (const_mol(nmol_local))
     865          792 :          ALLOCATE (tot_const(nmol_local))
     866          792 :          ALLOCATE (point(2, nmol_local))
     867              : 
     868        42894 :          point(:, :) = 0
     869              :          atm_offset = 0
     870              :          icount = 0
     871        14926 :          DO ikind = 1, nkind
     872        14662 :             nmol_per_kind = local_molecules%n_el(ikind)
     873        14662 :             molecule_kind => molecule_kind_set(ikind)
     874              :             CALL get_molecule_kind(molecule_kind, nconstraint=nc, natom=natom, &
     875        14662 :                                    fixd_list=fixd_list, nshell=nshell)
     876        14662 :             IF (shell) natom = nshell
     877        43798 :             DO imol_local = 1, nmol_per_kind
     878        14210 :                icount = icount + 1
     879        14210 :                point(1, icount) = atm_offset + 1
     880        14210 :                point(2, icount) = atm_offset + natom
     881        14210 :                IF (.NOT. shell) THEN
     882              :                   ! nc keeps track of all constraints but not fixed ones..
     883              :                   ! Let's identify fixed atoms for this molecule
     884        13018 :                   nfixd = 0
     885        13018 :                   imol = local_molecules%list(ikind)%array(imol_local)
     886        13018 :                   molecule => molecule_set(imol)
     887        13018 :                   CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
     888        13018 :                   IF (ASSOCIATED(fixd_list)) THEN
     889         1766 :                      DO katom = first_atom, last_atom
     890       282600 :                         DO ilist = 1, SIZE(fixd_list)
     891       280834 :                            IF ((katom == fixd_list(ilist)%fixd) .AND. &
     892         1395 :                                (.NOT. fixd_list(ilist)%restraint%active)) THEN
     893         1904 :                               SELECT CASE (fixd_list(ilist)%itype)
     894              :                               CASE (use_perd_x, use_perd_y, use_perd_z)
     895          768 :                                  nfixd = nfixd + 1
     896              :                               CASE (use_perd_xy, use_perd_xz, use_perd_yz)
     897          256 :                                  nfixd = nfixd + 2
     898              :                               CASE (use_perd_xyz)
     899         1136 :                                  nfixd = nfixd + 3
     900              :                               END SELECT
     901              :                            END IF
     902              :                         END DO
     903              :                      END DO
     904              :                   END IF
     905        13018 :                   const_mol(icount) = nc + nfixd
     906        13018 :                   tot_const(icount) = const_mol(icount)
     907              :                END IF
     908        28872 :                atm_offset = point(2, icount)
     909              :             END DO
     910              :          END DO
     911          310 :       ELSE IF (dis_type == do_thermo_communication) THEN
     912          310 :          IF (region == do_region_defined) THEN
     913              :             ! Setup of the arbitrary region
     914           96 :             ALLOCATE (tot_const(sum_of_thermostats))
     915           32 :             ALLOCATE (point(2, 0))
     916           32 :             ALLOCATE (const_mol(0))
     917           32 :             atm_offset = 0
     918          116 :             tot_const = 0
     919           32 :             const_mol = 0
     920           32 :             point = 0
     921           98 :             DO ikind = 1, nkind
     922           66 :                nmol_per_kind = local_molecules%n_el(ikind)
     923           66 :                molecule_kind => molecule_kind_set(ikind)
     924              :                CALL get_molecule_kind(molecule_kind, nconstraint=nc, natom=natom, &
     925              :                                       fixd_list=fixd_list, colv_list=colv_list, g3x3_list=g3x3_list, &
     926           66 :                                       g4x6_list=g4x6_list, nshell=nshell)
     927           66 :                IF (shell) natom = nshell
     928         7450 :                DO imol_local = 1, nmol_per_kind
     929         7286 :                   IF (.NOT. shell) THEN
     930              :                      ! First if nc is not zero let's check if all atoms of a molecule
     931              :                      ! are in the same thermostatting region..
     932         7286 :                      imol = local_molecules%list(ikind)%array(imol_local)
     933         7286 :                      molecule => molecule_set(imol)
     934         7286 :                      id_region = map_loc_thermo_gen(atm_offset + 1)
     935        29178 :                      IF (ALL(map_loc_thermo_gen(atm_offset + 1:atm_offset + natom) == id_region)) THEN
     936              :                         ! All the atoms of a molecule are within the same thermostatting
     937              :                         ! region.. this is the easy case..
     938         7253 :                         tot_const(id_region) = tot_const(id_region) + nc
     939              :                      ELSE
     940              :                         ! If not let's check the single constraints defined for this molecule
     941              :                         ! and continue only when atoms involved in the constraint belong to
     942              :                         ! the same thermostatting region
     943           33 :                         IF (ASSOCIATED(colv_list)) THEN
     944           64 :                            DO i = 1, SIZE(colv_list)
     945           64 :                               IF (.NOT. colv_list(i)%restraint%active) THEN
     946           32 :                                  iatm = atm_offset + colv_list(i)%i_atoms(1)
     947           64 :                                  DO j = 2, SIZE(colv_list(i)%i_atoms)
     948           32 :                                     jatm = atm_offset + colv_list(i)%i_atoms(j)
     949           64 :                                     IF (map_loc_thermo_gen(iatm) /= map_loc_thermo_gen(jatm)) THEN
     950              :                                        CALL cp_abort(__LOCATION__, &
     951              :                                                      "User Defined Region: "// &
     952              :                                                      "A constraint (COLV) was defined between two thermostatting regions! "// &
     953            0 :                                                      "This is not allowed!")
     954              :                                     END IF
     955              :                                  END DO
     956           32 :                                  id_region = map_loc_thermo_gen(iatm)
     957           32 :                                  tot_const(id_region) = tot_const(id_region) + 1
     958              :                               END IF
     959              :                            END DO
     960              :                         END IF
     961           33 :                         IF (ASSOCIATED(g3x3_list)) THEN
     962            1 :                            DO i = 1, SIZE(g3x3_list)
     963            0 :                               IF (.NOT. g3x3_list(i)%restraint%active) THEN
     964            0 :                                  iatm = atm_offset + g3x3_list(i)%a
     965            0 :                                  jatm = atm_offset + g3x3_list(i)%b
     966            0 :                                  IF (map_loc_thermo_gen(iatm) /= map_loc_thermo_gen(jatm)) THEN
     967              :                                     CALL cp_abort(__LOCATION__, &
     968              :                                                   "User Defined Region: "// &
     969              :                                                   "A constraint (G3X3) was defined between two thermostatting regions! "// &
     970            0 :                                                   "This is not allowed!")
     971              :                                  END IF
     972            0 :                                  jatm = atm_offset + g3x3_list(i)%c
     973            0 :                                  IF (map_loc_thermo_gen(iatm) /= map_loc_thermo_gen(jatm)) THEN
     974              :                                     CALL cp_abort(__LOCATION__, &
     975              :                                                   "User Defined Region: "// &
     976              :                                                   "A constraint (G3X3) was defined between two thermostatting regions! "// &
     977            0 :                                                   "This is not allowed!")
     978              :                                  END IF
     979              :                               END IF
     980            0 :                               id_region = map_loc_thermo_gen(iatm)
     981            1 :                               tot_const(id_region) = tot_const(id_region) + 3
     982              :                            END DO
     983              :                         END IF
     984           33 :                         IF (ASSOCIATED(g4x6_list)) THEN
     985            0 :                            DO i = 1, SIZE(g4x6_list)
     986            0 :                               IF (.NOT. g4x6_list(i)%restraint%active) THEN
     987            0 :                                  iatm = atm_offset + g4x6_list(i)%a
     988            0 :                                  jatm = atm_offset + g4x6_list(i)%b
     989            0 :                                  IF (map_loc_thermo_gen(iatm) /= map_loc_thermo_gen(jatm)) THEN
     990              :                                     CALL cp_abort(__LOCATION__, &
     991              :                                                   " User Defined Region: "// &
     992              :                                                   "A constraint (G4X6) was defined between two thermostatting regions! "// &
     993            0 :                                                   "This is not allowed!")
     994              :                                  END IF
     995            0 :                                  jatm = atm_offset + g4x6_list(i)%c
     996            0 :                                  IF (map_loc_thermo_gen(iatm) /= map_loc_thermo_gen(jatm)) THEN
     997              :                                     CALL cp_abort(__LOCATION__, &
     998              :                                                   " User Defined Region: "// &
     999              :                                                   "A constraint (G4X6) was defined between two thermostatting regions! "// &
    1000            0 :                                                   "This is not allowed!")
    1001              :                                  END IF
    1002            0 :                                  jatm = atm_offset + g4x6_list(i)%d
    1003            0 :                                  IF (map_loc_thermo_gen(iatm) /= map_loc_thermo_gen(jatm)) THEN
    1004              :                                     CALL cp_abort(__LOCATION__, &
    1005              :                                                   " User Defined Region: "// &
    1006              :                                                   "A constraint (G4X6) was defined between two thermostatting regions! "// &
    1007            0 :                                                   "This is not allowed!")
    1008              :                                  END IF
    1009              :                               END IF
    1010            0 :                               id_region = map_loc_thermo_gen(iatm)
    1011            0 :                               tot_const(id_region) = tot_const(id_region) + 6
    1012              :                            END DO
    1013              :                         END IF
    1014              :                      END IF
    1015              :                      ! Here we handle possibly fixed atoms
    1016         7286 :                      IF (ASSOCIATED(fixd_list)) THEN
    1017            0 :                         CALL get_molecule(molecule, first_atom=first_atom, last_atom=last_atom)
    1018            0 :                         iatm = 0
    1019            0 :                         DO katom = first_atom, last_atom
    1020            0 :                            iatm = iatm + 1
    1021            0 :                            DO ilist = 1, SIZE(fixd_list)
    1022            0 :                               IF ((katom == fixd_list(ilist)%fixd) .AND. &
    1023            0 :                                   (.NOT. fixd_list(ilist)%restraint%active)) THEN
    1024            0 :                                  id_region = map_loc_thermo_gen(atm_offset + iatm)
    1025            0 :                                  SELECT CASE (fixd_list(ilist)%itype)
    1026              :                                  CASE (use_perd_x, use_perd_y, use_perd_z)
    1027            0 :                                     tot_const(id_region) = tot_const(id_region) + 1
    1028              :                                  CASE (use_perd_xy, use_perd_xz, use_perd_yz)
    1029            0 :                                     tot_const(id_region) = tot_const(id_region) + 2
    1030              :                                  CASE (use_perd_xyz)
    1031            0 :                                     tot_const(id_region) = tot_const(id_region) + 3
    1032              :                                  END SELECT
    1033              :                               END IF
    1034              :                            END DO
    1035              :                         END DO
    1036              :                      END IF
    1037              :                   END IF
    1038         7352 :                   atm_offset = atm_offset + natom
    1039              :                END DO
    1040              :             END DO
    1041          200 :             CALL para_env%sum(tot_const)
    1042              :          ELSE
    1043          834 :             ALLOCATE (const_mol(nkind))
    1044          834 :             ALLOCATE (tot_const(nkind))
    1045          834 :             ALLOCATE (point(2, nkind))
    1046        45182 :             point(:, :) = 0
    1047              :             atm_offset = 0
    1048              :             ! nc keeps track of all constraints but not fixed ones..
    1049        15246 :             DO ikind = 1, nkind
    1050        14968 :                nmol_per_kind = local_molecules%n_el(ikind)
    1051        14968 :                molecule_kind => molecule_kind_set(ikind)
    1052              :                CALL get_molecule_kind(molecule_kind, nconstraint=nc, natom=natom, &
    1053        14968 :                                       nmolecule=nmolecule, nconstraint_fixd=nfixd, nshell=nshell)
    1054        14968 :                IF (shell) natom = nshell
    1055        14968 :                IF (.NOT. shell) THEN
    1056        14944 :                   const_mol(ikind) = nc
    1057              :                   ! Let's consider the fixed atoms only for the total number of constraints
    1058              :                   ! in case we are in REPLICATED/INTERACTING thermostats
    1059        14944 :                   tot_const(ikind) = const_mol(ikind)*nmolecule + nfixd
    1060              :                END IF
    1061        14968 :                point(1, ikind) = atm_offset + 1
    1062        14968 :                point(2, ikind) = atm_offset + natom*nmol_per_kind
    1063        30214 :                atm_offset = point(2, ikind)
    1064              :             END DO
    1065              :          END IF
    1066              :       END IF
    1067          574 :       IF ((.NOT. simpar%constraint) .OR. shell) THEN
    1068        27451 :          const_mol = 0
    1069        27511 :          tot_const = 0
    1070              :       END IF
    1071              : 
    1072          574 :       CALL timestop(handle)
    1073              : 
    1074          574 :    END SUBROUTINE mapping_region_evaluate
    1075              : 
    1076              : ! **************************************************************************************************
    1077              : !> \brief ...
    1078              : !> \param molecule_set ...
    1079              : !> \param molecule_kind_set ...
    1080              : !> \param local_molecules ...
    1081              : !> \param para_env ...
    1082              : !> \param massive_atom_list ...
    1083              : !> \param region ...
    1084              : !> \param shell ...
    1085              : ! **************************************************************************************************
    1086          574 :    SUBROUTINE massive_list_generate(molecule_set, molecule_kind_set, &
    1087              :                                     local_molecules, para_env, massive_atom_list, region, shell)
    1088              : 
    1089              :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
    1090              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind_set(:)
    1091              :       TYPE(distribution_1d_type), POINTER                :: local_molecules
    1092              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1093              :       INTEGER, POINTER                                   :: massive_atom_list(:)
    1094              :       INTEGER, INTENT(IN)                                :: region
    1095              :       LOGICAL, INTENT(IN)                                :: shell
    1096              : 
    1097              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'massive_list_generate'
    1098              : 
    1099              :       INTEGER :: first_atom, first_shell, handle, i, ikind, imol, iproc, j, natom, ncount, nkind, &
    1100              :          nmol_per_kind, nshell, num_massive_atm, num_massive_atm_local, offset
    1101          574 :       INTEGER, DIMENSION(:), POINTER                     :: array_num_massive_atm, local_atm_list, &
    1102          574 :                                                             work
    1103              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
    1104              :       TYPE(molecule_type), POINTER                       :: molecule
    1105              : 
    1106          574 :       CALL timeset(routineN, handle)
    1107              : 
    1108          574 :       num_massive_atm_local = 0
    1109          574 :       NULLIFY (local_atm_list)
    1110          574 :       CALL reallocate(local_atm_list, 1, num_massive_atm_local)
    1111              : 
    1112          574 :       nkind = SIZE(molecule_kind_set)
    1113        30270 :       DO ikind = 1, nkind
    1114        29696 :          nmol_per_kind = local_molecules%n_el(ikind)
    1115        64646 :          DO imol = 1, nmol_per_kind
    1116        34376 :             i = local_molecules%list(ikind)%array(imol)
    1117        34376 :             molecule => molecule_set(i)
    1118        34376 :             molecule_kind => molecule%molecule_kind
    1119        34376 :             CALL get_molecule_kind(molecule_kind, natom=natom, nshell=nshell)
    1120        64072 :             IF (region == do_region_massive) THEN
    1121         7246 :                IF (shell) THEN
    1122          904 :                   natom = nshell
    1123              :                END IF
    1124         7246 :                num_massive_atm_local = num_massive_atm_local + natom
    1125         7246 :                CALL reallocate(local_atm_list, 1, num_massive_atm_local)
    1126         7246 :                CALL get_molecule(molecule, first_atom=first_atom, first_shell=first_shell)
    1127         7246 :                IF (shell) THEN
    1128          904 :                   first_atom = first_shell
    1129              :                END IF
    1130        30598 :                DO j = 1, natom
    1131        30598 :                   local_atm_list(num_massive_atm_local - natom + j) = first_atom - 1 + j
    1132              :                END DO
    1133              :             END IF
    1134              :          END DO
    1135              :       END DO
    1136              : 
    1137         1722 :       ALLOCATE (array_num_massive_atm(para_env%num_pe))
    1138         1722 :       CALL para_env%allgather(num_massive_atm_local, array_num_massive_atm)
    1139              : 
    1140         1722 :       num_massive_atm = SUM(array_num_massive_atm)
    1141         1280 :       ALLOCATE (massive_atom_list(num_massive_atm))
    1142              : 
    1143          574 :       offset = 0
    1144         1722 :       DO iproc = 1, para_env%num_pe
    1145         1148 :          ncount = array_num_massive_atm(iproc)
    1146         2560 :          ALLOCATE (work(ncount))
    1147         1148 :          IF (para_env%mepos == (iproc - 1)) THEN
    1148        23926 :             DO i = 1, ncount
    1149        23926 :                work(i) = local_atm_list(i)
    1150              :             END DO
    1151              :          ELSE
    1152        23926 :             work(:) = 0
    1153              :          END IF
    1154        94556 :          CALL para_env%bcast(work, iproc - 1)
    1155        47852 :          DO i = 1, ncount
    1156        47852 :             massive_atom_list(offset + i) = work(i)
    1157              :          END DO
    1158         1148 :          DEALLOCATE (work)
    1159         1722 :          offset = offset + array_num_massive_atm(iproc)
    1160              :       END DO
    1161              : 
    1162              :       ! Sort atom list
    1163          706 :       ALLOCATE (work(num_massive_atm))
    1164          574 :       CALL sort(massive_atom_list, num_massive_atm, work)
    1165          574 :       DEALLOCATE (work)
    1166              : 
    1167          574 :       DEALLOCATE (local_atm_list)
    1168          574 :       DEALLOCATE (array_num_massive_atm)
    1169              : 
    1170          574 :       CALL timestop(handle)
    1171              : 
    1172          574 :    END SUBROUTINE massive_list_generate
    1173              : 
    1174              : ! **************************************************************************************************
    1175              : !> \brief Initialize the map_info for barostat thermostat
    1176              : !> \param map_info ...
    1177              : !> \param ndeg ...
    1178              : !> \param num_thermo ...
    1179              : !> \author Teodoro Laino [tlaino] - 10.2007 - University of Zurich
    1180              : ! **************************************************************************************************
    1181          152 :    SUBROUTINE init_baro_map_info(map_info, ndeg, num_thermo)
    1182              : 
    1183              :       TYPE(map_info_type), POINTER                       :: map_info
    1184              :       INTEGER, INTENT(IN)                                :: ndeg, num_thermo
    1185              : 
    1186              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'init_baro_map_info'
    1187              : 
    1188              :       INTEGER                                            :: handle, i
    1189              : 
    1190          152 :       CALL timeset(routineN, handle)
    1191              : 
    1192          456 :       ALLOCATE (map_info%s_kin(num_thermo))
    1193          456 :       ALLOCATE (map_info%v_scale(num_thermo))
    1194         1496 :       ALLOCATE (map_info%p_kin(1, ndeg))
    1195         1496 :       ALLOCATE (map_info%p_scale(1, ndeg))
    1196              :       ! Allocate the index array
    1197          152 :       ALLOCATE (map_info%index(1))
    1198          152 :       ALLOCATE (map_info%map_index(1))
    1199              : 
    1200              :       ! Begin the mapping loop
    1201          672 :       DO i = 1, ndeg
    1202          520 :          map_info%p_kin(1, i)%point => map_info%s_kin(1)
    1203          672 :          map_info%p_scale(1, i)%point => map_info%v_scale(1)
    1204              :       END DO
    1205          152 :       map_info%index(1) = 1
    1206          152 :       map_info%map_index(1) = 1
    1207              : 
    1208          152 :       CALL timestop(handle)
    1209              : 
    1210          152 :    END SUBROUTINE init_baro_map_info
    1211              : 
    1212              : END MODULE thermostat_mapping
    1213              : 
        

Generated by: LCOV version 2.0-1