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