(git:34ef472)
qmmm_force.F
Go to the documentation of this file.
1 !--------------------------------------------------------------------------------------------------!
2 ! CP2K: A general program to perform molecular dynamics simulations !
3 ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 ! !
5 ! SPDX-License-Identifier: GPL-2.0-or-later !
6 !--------------------------------------------------------------------------------------------------!
7 
8 ! **************************************************************************************************
9 !> \brief Calculates QM/MM energy and forces
10 !> \par History
11 !> 2015 Factored out of force_env_methods.F
12 !> \author Ole Schuett
13 ! **************************************************************************************************
14 MODULE qmmm_force
15  USE cell_types, ONLY: cell_type
18  cp_logger_type
20  cp_p_file,&
25  get_results,&
26  put_results
27  USE cp_result_types, ONLY: cp_result_type
28  USE cp_subsys_types, ONLY: cp_subsys_get,&
29  cp_subsys_type
30  USE fist_energy_types, ONLY: fist_energy_type
34  section_vals_type
35  USE kinds, ONLY: default_string_length,&
36  dp
37  USE particle_types, ONLY: particle_type
38  USE physcon, ONLY: debye
40  USE qmmm_gpw_forces, ONLY: qmmm_forces
45  USE qmmm_types, ONLY: qmmm_env_type
46  USE qmmm_types_low, ONLY: qmmm_links_type
47  USE qmmm_util, ONLY: apply_qmmm_translate,&
49  USE qs_energy_types, ONLY: qs_energy_type
53 #include "./base/base_uses.f90"
54 
55  IMPLICIT NONE
56 
57  PRIVATE
58 
59  CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qmmm_force'
60 
61  PUBLIC :: qmmm_calc_energy_force
62 
63 CONTAINS
64 
65 ! **************************************************************************************************
66 !> \brief calculates the qm/mm energy and forces
67 !> \param qmmm_env ...
68 !> \param calc_force if also the forces should be calculated
69 !> \param consistent_energies ...
70 !> \param linres ...
71 !> \par History
72 !> 05.2004 created [fawzi]
73 !> \author Fawzi Mohamed
74 ! **************************************************************************************************
75  SUBROUTINE qmmm_calc_energy_force(qmmm_env, calc_force, consistent_energies, linres)
76  TYPE(qmmm_env_type), POINTER :: qmmm_env
77  LOGICAL, INTENT(IN) :: calc_force, consistent_energies, linres
78 
79  CHARACTER(LEN=default_string_length) :: description, iter
80  INTEGER :: ip, j, nres, output_unit
81  INTEGER, DIMENSION(:), POINTER :: qm_atom_index
82  LOGICAL :: check, qmmm_added_chrg, qmmm_link, &
83  qmmm_link_imomm
84  REAL(kind=dp) :: energy_mm, energy_qm
85  REAL(kind=dp), DIMENSION(3) :: dip_mm, dip_qm, dip_qmmm, max_coord, &
86  min_coord
87  TYPE(cell_type), POINTER :: mm_cell, qm_cell
88  TYPE(cp_logger_type), POINTER :: logger
89  TYPE(cp_result_type), POINTER :: results_mm, results_qm, results_qmmm
90  TYPE(cp_subsys_type), POINTER :: subsys, subsys_mm, subsys_qm
91  TYPE(fist_energy_type), POINTER :: fist_energy
92  TYPE(particle_type), DIMENSION(:), POINTER :: particles_mm, particles_qm
93  TYPE(qmmm_links_type), POINTER :: qmmm_links
94  TYPE(qs_energy_type), POINTER :: qs_energy
95  TYPE(section_vals_type), POINTER :: force_env_section, print_key
96 
97  min_coord = huge(0.0_dp)
98  max_coord = -huge(0.0_dp)
99  qmmm_link = .false.
100  qmmm_link_imomm = .false.
101  qmmm_added_chrg = .false.
102  logger => cp_get_default_logger()
103  output_unit = cp_logger_get_default_io_unit(logger)
104  NULLIFY (subsys_mm, subsys_qm, subsys, qm_atom_index, particles_mm, particles_qm, qm_cell, mm_cell)
105  NULLIFY (force_env_section, print_key, results_qmmm, results_qm, results_mm)
106 
107  CALL get_qs_env(qmmm_env%qs_env, input=force_env_section)
108  print_key => section_vals_get_subs_vals(force_env_section, "QMMM%PRINT%DIPOLE")
109 
110  cpassert(ASSOCIATED(qmmm_env))
111 
112  CALL apply_qmmm_translate(qmmm_env)
113 
114  CALL fist_env_get(qmmm_env%fist_env, cell=mm_cell, subsys=subsys_mm)
115  CALL get_qs_env(qmmm_env%qs_env, cell=qm_cell, cp_subsys=subsys_qm)
116  qm_atom_index => qmmm_env%qm%qm_atom_index
117  qmmm_link = qmmm_env%qm%qmmm_link
118  qmmm_links => qmmm_env%qm%qmmm_links
119  qmmm_added_chrg = (qmmm_env%qm%move_mm_charges .OR. qmmm_env%qm%add_mm_charges)
120  IF (qmmm_link) THEN
121  cpassert(ASSOCIATED(qmmm_links))
122  IF (ASSOCIATED(qmmm_links%imomm)) qmmm_link_imomm = (SIZE(qmmm_links%imomm) /= 0)
123  END IF
124  cpassert(ASSOCIATED(qm_atom_index))
125 
126  particles_mm => subsys_mm%particles%els
127  particles_qm => subsys_qm%particles%els
128 
129  DO j = 1, 3
130  IF (qm_cell%perd(j) == 1) cycle
131  DO ip = 1, SIZE(particles_qm)
132  check = (dot_product(qm_cell%h_inv(j, :), particles_qm(ip)%r) >= 0.0) .AND. &
133  (dot_product(qm_cell%h_inv(j, :), particles_qm(ip)%r) <= 1.0)
134  IF (output_unit > 0 .AND. .NOT. check) THEN
135  WRITE (unit=output_unit, fmt='("ip, j, pos, lat_pos ",2I6,6F12.5)') ip, j, &
136  particles_qm(ip)%r, dot_product(qm_cell%h_inv(j, :), particles_qm(ip)%r)
137  END IF
138  IF (.NOT. check) &
139  CALL cp_abort(__location__, &
140  "QM/MM QM atoms must be fully contained in the same image of the QM box "// &
141  "- No wrapping of coordinates is allowed! ")
142  END DO
143  END DO
144 
145  ! If present QM/MM links (just IMOMM) correct the position of the qm-link atom
146  IF (qmmm_link_imomm) CALL qmmm_link_imomm_coord(qmmm_links, particles_qm, qm_atom_index)
147 
148  ! If add charges get their position NOW!
149  IF (qmmm_added_chrg) CALL qmmm_added_chrg_coord(qmmm_env%qm, particles_mm)
150 
151  ! Initialize ks_qmmm_env
152  CALL ks_qmmm_env_rebuild(qs_env=qmmm_env%qs_env, qmmm_env=qmmm_env%qm)
153 
154  ! Compute the short range QM/MM Electrostatic Potential
155  CALL qmmm_el_coupling(qs_env=qmmm_env%qs_env, &
156  qmmm_env=qmmm_env%qm, &
157  mm_particles=particles_mm, &
158  mm_cell=mm_cell)
159 
160  ! Fist
161  CALL fist_calc_energy_force(qmmm_env%fist_env)
162 
163  ! Print Out information on fist energy calculation...
164  CALL fist_env_get(qmmm_env%fist_env, thermo=fist_energy)
165  energy_mm = fist_energy%pot
166  CALL cp_subsys_get(subsys_mm, results=results_mm)
167 
168  ! QS
169  CALL qs_calc_energy_force(qmmm_env%qs_env, calc_force, consistent_energies, linres)
170 
171  ! QM/MM Interaction Potential forces
172  CALL qmmm_forces(qmmm_env%qs_env, &
173  qmmm_env%qm, particles_mm, &
174  mm_cell=mm_cell, &
175  calc_force=calc_force)
176 
177  ! Forces of quadratic wall on QM atoms
178  CALL apply_qmmm_walls(qmmm_env)
179 
180  ! Print Out information on QS energy calculation...
181  CALL get_qs_env(qmmm_env%qs_env, energy=qs_energy)
182  energy_qm = qs_energy%total
183  CALL cp_subsys_get(subsys_qm, results=results_qm)
184 
185  !TODO: is really results_qm == results_qmmm ???
186  CALL cp_subsys_get(subsys_qm, results=results_qmmm)
187 
188  IF (calc_force) THEN
189  ! If present QM/MM links (just IMOMM) correct the position of the qm-link atom
190  IF (qmmm_link_imomm) CALL qmmm_link_imomm_forces(qmmm_links, particles_qm, qm_atom_index)
191  particles_mm => subsys_mm%particles%els
192  DO ip = 1, SIZE(qm_atom_index)
193  particles_mm(qm_atom_index(ip))%f = particles_mm(qm_atom_index(ip))%f + particles_qm(ip)%f
194  END DO
195  ! If add charges get rid of their derivatives right NOW!
196  IF (qmmm_added_chrg) CALL qmmm_added_chrg_forces(qmmm_env%qm, particles_mm)
197  END IF
198 
199  ! Handle some output
200  output_unit = cp_print_key_unit_nr(logger, force_env_section, "QMMM%PRINT%DERIVATIVES", &
201  extension=".Log")
202  IF (output_unit > 0) THEN
203  WRITE (unit=output_unit, fmt='(/1X,A,F15.9)') "Energy after QMMM calculation: ", energy_qm
204  IF (calc_force) THEN
205  WRITE (unit=output_unit, fmt='(/1X,A)') "Derivatives on all atoms after QMMM calculation: "
206  DO ip = 1, SIZE(particles_mm)
207  WRITE (unit=output_unit, fmt='(1X,3F15.9)') particles_mm(ip)%f
208  END DO
209  END IF
210  END IF
211  CALL cp_print_key_finished_output(output_unit, logger, force_env_section, &
212  "QMMM%PRINT%DERIVATIVES")
213 
214  ! Dipole
215  print_key => section_vals_get_subs_vals(force_env_section, "QMMM%PRINT%DIPOLE")
216  IF (btest(cp_print_key_should_output(logger%iter_info, print_key), &
217  cp_p_file)) THEN
218  description = '[DIPOLE]'
219  CALL get_results(results=results_qm, description=description, n_rep=nres)
220  cpassert(nres <= 1)
221  CALL get_results(results=results_mm, description=description, n_rep=nres)
222  cpassert(nres <= 1)
223  CALL get_results(results=results_qm, description=description, values=dip_qm)
224  CALL get_results(results=results_mm, description=description, values=dip_mm)
225  dip_qmmm = dip_qm + dip_mm
226  CALL cp_results_erase(results=results_qmmm, description=description)
227  CALL put_results(results=results_qmmm, description=description, values=dip_qmmm)
228 
229  output_unit = cp_print_key_unit_nr(logger, force_env_section, "QMMM%PRINT%DIPOLE", &
230  extension=".Dipole")
231  IF (output_unit > 0) THEN
232  WRITE (unit=output_unit, fmt="(A)") "QMMM TOTAL DIPOLE"
233  WRITE (unit=output_unit, fmt="(A,T31,A,T88,A)") &
234  "# iter_level", "dipole(x,y,z)[atomic units]", &
235  "dipole(x,y,z)[debye]"
236  iter = cp_iter_string(logger%iter_info)
237  WRITE (unit=output_unit, fmt="(a,6(es18.8))") &
238  iter(1:15), dip_qmmm, dip_qmmm*debye
239  END IF
240  END IF
241 
242  END SUBROUTINE qmmm_calc_energy_force
243 
244 END MODULE qmmm_force
Handles all functions related to the CELL.
Definition: cell_types.F:15
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
character(len=default_string_length) function, public cp_iter_string(iter_info, print_key, for_file)
returns the iteration string, a string that is useful to create unique filenames (once you trim it)
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
integer, parameter, public cp_p_file
integer function, public cp_print_key_should_output(iteration_info, basis_section, print_key_path, used_print_key, first_time)
returns what should be done with the given property if btest(res,cp_p_store) then the property should...
set of type/routines to handle the storage of results in force_envs
subroutine, public cp_results_erase(results, description, nval)
erase a part of result_list
set of type/routines to handle the storage of results in force_envs
types that represent a subsys, i.e. a part of the system
subroutine, public cp_subsys_get(subsys, ref_count, atomic_kinds, atomic_kind_set, particles, particle_set, local_particles, molecules, molecule_set, molecule_kinds, molecule_kind_set, local_molecules, para_env, colvar_p, shell_particles, core_particles, gci, multipoles, natom, nparticle, ncore, nshell, nkind, atprop, virial, results, cell)
returns information about various attributes of the given subsys
subroutine, public fist_env_get(fist_env, atomic_kind_set, particle_set, ewald_pw, local_particles, local_molecules, molecule_kind_set, molecule_set, cell, cell_ref, ewald_env, fist_nonbond_env, thermo, para_env, subsys, qmmm, qmmm_env, input, shell_model, shell_model_ad, shell_particle_set, core_particle_set, multipoles, results, exclusions, efield)
Purpose: Get the FIST environment.
subroutine, public fist_calc_energy_force(fist_env, debug)
Calculates the total potential energy, total force, and the total pressure tensor from the potentials...
Definition: fist_force.F:112
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
Defines the basic variable types.
Definition: kinds.F:23
integer, parameter, public dp
Definition: kinds.F:34
integer, parameter, public default_string_length
Definition: kinds.F:57
Define the data structure for the particle information.
Definition of physical constants:
Definition: physcon.F:68
real(kind=dp), parameter, public debye
Definition: physcon.F:201
Calculates QM/MM energy and forces.
Definition: qmmm_force.F:14
subroutine, public qmmm_calc_energy_force(qmmm_env, calc_force, consistent_energies, linres)
calculates the qm/mm energy and forces
Definition: qmmm_force.F:76
A collection of methods to treat the QM/MM electrostatic coupling.
subroutine, public qmmm_el_coupling(qs_env, qmmm_env, mm_particles, mm_cell)
Main Driver to compute the QM/MM Electrostatic Coupling.
Routines to compute energy and forces in a QM/MM calculation.
subroutine, public qmmm_forces(qs_env, qmmm_env, mm_particles, calc_force, mm_cell)
General driver to Compute the contribution to the forces due to the QM/MM potential.
Basic container type for QM/MM.
Definition: qmmm_types.F:12
subroutine, public apply_qmmm_walls(qmmm_env)
Apply QM quadratic walls in order to avoid QM atoms escaping from the QM Box.
Definition: qmmm_util.F:62
subroutine, public apply_qmmm_translate(qmmm_env)
Apply translation to the full system in order to center the QM system into the QM box.
Definition: qmmm_util.F:373
Perform a QUICKSTEP wavefunction optimization (single point)
Definition: qs_energy.F:14
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_RI_aux_kp, matrix_s, matrix_s_RI_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, ecoul_1c, rho0_s_rs, rho0_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, WannierCentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, rhs)
Get the QUICKSTEP environment.
Quickstep force driver routine.
Definition: qs_force.F:12
subroutine, public qs_calc_energy_force(qs_env, calc_force, consistent_energies, linres)
...
Definition: qs_force.F:107
subroutine, public ks_qmmm_env_rebuild(qs_env, qmmm_env)
Initialize the ks_qmmm_env.