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