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