LCOV - code coverage report
Current view: top level - src - qs_linres_module.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 92.6 % 256 237
Test Date: 2026-07-25 06:35:44 Functions: 100.0 % 8 8

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Contains the setup for  the calculation of properties by linear response
      10              : !>      by the application of second order density functional perturbation theory.
      11              : !>      The knowledge of the ground state energy, density and wavefunctions is assumed.
      12              : !>      Uses the self consistent approach.
      13              : !>      Properties that can be calculated : none
      14              : !> \par History
      15              : !>       created 06-2005 [MI]
      16              : !> \author MI
      17              : ! **************************************************************************************************
      18              : MODULE qs_linres_module
      19              :    USE bibliography,                    ONLY: Ditler2021,&
      20              :                                               Ditler2022,&
      21              :                                               Weber2009,&
      22              :                                               cite_reference
      23              :    USE cp_control_types,                ONLY: dft_control_type
      24              :    USE cp_dbcsr_api,                    ONLY: dbcsr_p_type
      25              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      26              :                                               cp_logger_type
      27              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      28              :                                               cp_print_key_unit_nr
      29              :    USE force_env_types,                 ONLY: force_env_get,&
      30              :                                               force_env_type,&
      31              :                                               use_qmmm,&
      32              :                                               use_qs_force
      33              :    USE input_constants,                 ONLY: lr_current,&
      34              :                                               lr_none,&
      35              :                                               ot_precond_full_all,&
      36              :                                               ot_precond_full_kinetic,&
      37              :                                               ot_precond_full_single,&
      38              :                                               ot_precond_full_single_inverse,&
      39              :                                               ot_precond_none,&
      40              :                                               ot_precond_s_inverse
      41              :    USE input_section_types,             ONLY: section_vals_get,&
      42              :                                               section_vals_get_subs_vals,&
      43              :                                               section_vals_type,&
      44              :                                               section_vals_val_get
      45              :    USE kinds,                           ONLY: dp
      46              :    USE qs_dcdr,                         ONLY: apt_dR,&
      47              :                                               apt_dR_localization,&
      48              :                                               dcdr_build_op_dR,&
      49              :                                               dcdr_response_dR,&
      50              :                                               prepare_per_atom
      51              :    USE qs_dcdr_utils,                   ONLY: dcdr_env_cleanup,&
      52              :                                               dcdr_env_init,&
      53              :                                               dcdr_print
      54              :    USE qs_density_matrices,             ONLY: calculate_density_matrix
      55              :    USE qs_environment_types,            ONLY: get_qs_env,&
      56              :                                               qs_environment_type,&
      57              :                                               set_qs_env
      58              :    USE qs_linres_current,               ONLY: current_build_chi,&
      59              :                                               current_build_current
      60              :    USE qs_linres_current_utils,         ONLY: current_env_cleanup,&
      61              :                                               current_env_init,&
      62              :                                               current_response
      63              :    USE qs_linres_epr_nablavks,          ONLY: epr_nablavks
      64              :    USE qs_linres_epr_ownutils,          ONLY: epr_g_print,&
      65              :                                               epr_g_so,&
      66              :                                               epr_g_soo,&
      67              :                                               epr_g_zke,&
      68              :                                               epr_ind_magnetic_field
      69              :    USE qs_linres_epr_utils,             ONLY: epr_env_cleanup,&
      70              :                                               epr_env_init
      71              :    USE qs_linres_issc_utils,            ONLY: issc_env_cleanup,&
      72              :                                               issc_env_init,&
      73              :                                               issc_issc,&
      74              :                                               issc_print,&
      75              :                                               issc_response
      76              :    USE qs_linres_methods,               ONLY: linres_localize
      77              :    USE qs_linres_nmr_shift,             ONLY: nmr_shift,&
      78              :                                               nmr_shift_print
      79              :    USE qs_linres_nmr_utils,             ONLY: nmr_env_cleanup,&
      80              :                                               nmr_env_init
      81              :    USE qs_linres_op,                    ONLY: current_operators,&
      82              :                                               issc_operators,&
      83              :                                               polar_operators,&
      84              :                                               polar_operators_local,&
      85              :                                               polar_operators_local_wannier
      86              :    USE qs_linres_polar_utils,           ONLY: polar_env_init,&
      87              :                                               polar_polar,&
      88              :                                               polar_print,&
      89              :                                               polar_response
      90              :    USE qs_linres_types,                 ONLY: &
      91              :         current_env_type, dcdr_env_type, epr_env_type, get_polar_env, issc_env_type, &
      92              :         linres_control_type, nmr_env_type, polar_env_type, vcd_env_type
      93              :    USE qs_mfp,                          ONLY: mfp_aat,&
      94              :                                               mfp_build_operator_gauge_dependent,&
      95              :                                               mfp_build_operator_gauge_independent,&
      96              :                                               mfp_response
      97              :    USE qs_mo_types,                     ONLY: mo_set_type
      98              :    USE qs_p_env_methods,                ONLY: p_env_create,&
      99              :                                               p_env_psi0_changed
     100              :    USE qs_p_env_types,                  ONLY: p_env_release,&
     101              :                                               qs_p_env_type
     102              :    USE qs_rho_methods,                  ONLY: qs_rho_update_rho
     103              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
     104              :                                               qs_rho_type
     105              :    USE qs_vcd,                          ONLY: aat_dV,&
     106              :                                               apt_dV,&
     107              :                                               prepare_per_atom_vcd,&
     108              :                                               vcd_build_op_dV,&
     109              :                                               vcd_response_dV
     110              :    USE qs_vcd_utils,                    ONLY: vcd_env_cleanup,&
     111              :                                               vcd_env_init,&
     112              :                                               vcd_print
     113              : #include "./base/base_uses.f90"
     114              : 
     115              :    IMPLICIT NONE
     116              : 
     117              :    PRIVATE
     118              :    PUBLIC :: linres_calculation, linres_calculation_low
     119              : 
     120              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_linres_module'
     121              : 
     122              : CONTAINS
     123              : ! *****************************************************************************
     124              : !> \brief Calculates the derivatives of the MO coefficients dC/dV^lambda_beta
     125              : !>         wrt to nuclear velocities. The derivative is indexed by `beta`, the
     126              : !>         electric dipole operator by `alpha`.
     127              : !>        Calculates the APT and AAT in velocity form
     128              : !>               P^lambda_alpha,beta = d< mu_alpha >/dV^lambda_beta
     129              : !>               M^lambda_alpha,beta = d< m_alpha >/dV^lambda_beta
     130              : !> \param qs_env ...
     131              : !> \param p_env ...
     132              : !> \author Edward Ditler
     133              : ! **************************************************************************************************
     134            2 :    SUBROUTINE vcd_linres(qs_env, p_env)
     135              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     136              :       TYPE(qs_p_env_type)                                :: p_env
     137              : 
     138              :       INTEGER                                            :: beta, i, latom
     139              :       LOGICAL                                            :: mfp_is_done, mfp_repeat
     140           60 :       TYPE(vcd_env_type)                                 :: vcd_env
     141              : 
     142            2 :       CALL cite_reference(Ditler2022)
     143              : 
     144              :       ! We need the position perturbation for the velocity perturbation operator
     145            2 :       CALL vcd_env_init(vcd_env, qs_env)
     146              : 
     147            2 :       mfp_repeat = vcd_env%distributed_origin
     148            2 :       mfp_is_done = .FALSE.
     149              : 
     150            2 :       qs_env%linres_control%linres_restart = .TRUE.
     151              : 
     152              :       ! Iterate over the list of atoms for which we want to calculate the APTs/AATs
     153              :       !  default is all atoms.
     154            8 :       DO latom = 1, SIZE(vcd_env%dcdr_env%list_of_atoms)
     155            6 :          vcd_env%dcdr_env%lambda = vcd_env%dcdr_env%list_of_atoms(latom)
     156              : 
     157            6 :          CALL prepare_per_atom(vcd_env%dcdr_env, qs_env)
     158            6 :          CALL prepare_per_atom_vcd(vcd_env, qs_env)
     159              : 
     160           24 :          DO beta = 1, 3                   ! in every direction
     161              : 
     162           18 :             vcd_env%dcdr_env%beta = beta
     163           18 :             vcd_env%dcdr_env%deltaR(vcd_env%dcdr_env%beta, vcd_env%dcdr_env%lambda) = 1._dp
     164              : 
     165              :             ! Since we do the heavy lifting anyways, we might also calculate the length form APTs here
     166           18 :             CALL dcdr_build_op_dR(vcd_env%dcdr_env, qs_env)
     167           18 :             CALL dcdr_response_dR(vcd_env%dcdr_env, p_env, qs_env)
     168           18 :             CALL apt_dR(qs_env, vcd_env%dcdr_env)
     169              : 
     170              :             ! And with the position perturbation ready, we can calculate the NVP
     171           18 :             CALL vcd_build_op_dV(vcd_env, qs_env)
     172           18 :             CALL vcd_response_dV(vcd_env, p_env, qs_env)
     173              : 
     174           18 :             CALL apt_dV(vcd_env, qs_env)
     175           18 :             CALL aat_dV(vcd_env, qs_env)
     176              : 
     177           24 :             IF (vcd_env%do_mfp) THEN
     178              :                ! Since we came so far, we might as well calculate the MFP AATs
     179              :                ! If we use a distributed origin we need to compute the MFP response again for each
     180              :                !   atom, because the reference point changes.
     181            0 :                IF (.NOT. mfp_is_done .OR. mfp_repeat) THEN
     182            0 :                   DO i = 1, 3
     183            0 :                      IF (vcd_env%origin_dependent_op_mfp) THEN
     184            0 :                         CPWARN("Using the origin dependent MFP operator")
     185            0 :                         CALL mfp_build_operator_gauge_dependent(vcd_env, qs_env, i)
     186              :                      ELSE
     187            0 :                         CALL mfp_build_operator_gauge_independent(vcd_env, qs_env, i)
     188              :                      END IF
     189            0 :                      CALL mfp_response(vcd_env, p_env, qs_env, i)
     190              :                   END DO
     191              :                   mfp_is_done = .TRUE.
     192              :                END IF
     193              : 
     194            0 :                CALL mfp_aat(vcd_env, qs_env)
     195              :             END IF
     196              :          END DO ! beta
     197              : 
     198              :          vcd_env%dcdr_env%apt_total_dcdr(:, :, vcd_env%dcdr_env%lambda) = &
     199              :             vcd_env%dcdr_env%apt_el_dcdr(:, :, vcd_env%dcdr_env%lambda) &
     200           78 :             + vcd_env%dcdr_env%apt_nuc_dcdr(:, :, vcd_env%dcdr_env%lambda)
     201              : 
     202              :          vcd_env%apt_total_nvpt(:, :, vcd_env%dcdr_env%lambda) = &
     203           78 :             vcd_env%apt_el_nvpt(:, :, vcd_env%dcdr_env%lambda) + vcd_env%apt_nuc_nvpt(:, :, vcd_env%dcdr_env%lambda)
     204              : 
     205            8 :          IF (vcd_env%do_mfp) THEN
     206            0 :             vcd_env%aat_atom_mfp(:, :, vcd_env%dcdr_env%lambda) = vcd_env%aat_atom_mfp(:, :, vcd_env%dcdr_env%lambda)*4._dp
     207              :          END IF
     208              : 
     209              :       END DO !lambda
     210              : 
     211            2 :       CALL vcd_print(vcd_env, qs_env)
     212            2 :       CALL vcd_env_cleanup(qs_env, vcd_env)
     213              : 
     214            2 :    END SUBROUTINE vcd_linres
     215              : 
     216              : ! **************************************************************************************************
     217              : !> \brief Calculates the derivatives of the MO coefficients dC/dR^lambda_beta
     218              : !>         wrt to nuclear coordinates. The derivative is index by `beta`, the
     219              : !>         electric dipole operator by `alpha`.
     220              : !>        Also calculates the APT
     221              : !>               P^lambda_alpha,beta = d< mu_alpha >/dR^lambda_beta
     222              : !>        and calculates the sum rules for the APT elements.
     223              : !> \param qs_env ...
     224              : !> \param p_env ...
     225              : ! **************************************************************************************************
     226           22 :    SUBROUTINE dcdr_linres(qs_env, p_env)
     227              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     228              :       TYPE(qs_p_env_type)                                :: p_env
     229              : 
     230              :       INTEGER                                            :: beta, latom
     231          308 :       TYPE(dcdr_env_type)                                :: dcdr_env
     232              :       TYPE(polar_env_type), POINTER                      :: polar_env
     233              : 
     234           22 :       CALL cite_reference(Ditler2021)
     235           22 :       CALL dcdr_env_init(dcdr_env, qs_env)
     236              : 
     237           22 :       IF (.NOT. dcdr_env%z_matrix_method) THEN
     238              : 
     239           72 :          DO latom = 1, SIZE(dcdr_env%list_of_atoms)
     240           54 :             dcdr_env%lambda = dcdr_env%list_of_atoms(latom)
     241           54 :             CALL prepare_per_atom(dcdr_env, qs_env)
     242              : 
     243          216 :             DO beta = 1, 3                   ! in every direction
     244          162 :                dcdr_env%beta = beta
     245          162 :                dcdr_env%deltaR(dcdr_env%beta, dcdr_env%lambda) = 1._dp
     246              : 
     247          162 :                CALL dcdr_build_op_dR(dcdr_env, qs_env)
     248          162 :                CALL dcdr_response_dR(dcdr_env, p_env, qs_env)
     249              : 
     250          216 :                IF (.NOT. dcdr_env%localized_psi0) THEN
     251          126 :                   CALL apt_dR(qs_env, dcdr_env)
     252              :                ELSE IF (dcdr_env%localized_psi0) THEN
     253           36 :                   CALL apt_dR_localization(qs_env, dcdr_env)
     254              :                END IF
     255              : 
     256              :             END DO !beta
     257              : 
     258              :             dcdr_env%apt_total_dcdr(:, :, dcdr_env%lambda) = &
     259          720 :                dcdr_env%apt_el_dcdr(:, :, dcdr_env%lambda) + dcdr_env%apt_nuc_dcdr(:, :, dcdr_env%lambda)
     260              :          END DO !lambda
     261              : 
     262              :       ELSE
     263              : 
     264            4 :          CALL polar_env_init(qs_env)
     265            4 :          CALL get_qs_env(qs_env=qs_env, polar_env=polar_env)
     266            4 :          CALL get_polar_env(polar_env=polar_env)
     267              : 
     268            4 :          IF (.NOT. dcdr_env%localized_psi0) THEN
     269            4 :             CALL polar_operators_local(qs_env)
     270              :          ELSE
     271            0 :             CALL polar_operators_local_wannier(qs_env, dcdr_env)
     272              :          END IF
     273              : 
     274            4 :          polar_env%do_periodic = .FALSE.
     275            4 :          CALL polar_response(p_env, qs_env)
     276              : 
     277           16 :          DO latom = 1, SIZE(dcdr_env%list_of_atoms)
     278           12 :             dcdr_env%lambda = dcdr_env%list_of_atoms(latom)
     279           12 :             CALL prepare_per_atom(dcdr_env, qs_env)
     280              : 
     281           48 :             DO beta = 1, 3                   ! in every direction
     282           36 :                dcdr_env%beta = beta
     283           36 :                dcdr_env%deltaR(dcdr_env%beta, dcdr_env%lambda) = 1._dp
     284              : 
     285           36 :                CALL dcdr_build_op_dR(dcdr_env, qs_env)
     286           48 :                IF (.NOT. dcdr_env%localized_psi0) THEN
     287           36 :                   CALL apt_dR(qs_env, dcdr_env)
     288              :                ELSE
     289            0 :                   CALL apt_dR_localization(qs_env, dcdr_env)
     290              :                END IF
     291              :             END DO !beta
     292              : 
     293              :             dcdr_env%apt_total_dcdr(:, :, dcdr_env%lambda) = &
     294          160 :                dcdr_env%apt_el_dcdr(:, :, dcdr_env%lambda) + dcdr_env%apt_nuc_dcdr(:, :, dcdr_env%lambda)
     295              :          END DO !lambda
     296              : 
     297              :       END IF
     298              : 
     299           22 :       CALL dcdr_print(dcdr_env, qs_env)
     300           22 :       CALL dcdr_env_cleanup(qs_env, dcdr_env)
     301           22 :    END SUBROUTINE dcdr_linres
     302              : 
     303              : ! **************************************************************************************************
     304              : !> \brief Driver for the linear response calculatios
     305              : !> \param force_env ...
     306              : !> \par History
     307              : !>      06.2005 created [MI]
     308              : !> \author MI
     309              : ! **************************************************************************************************
     310          188 :    SUBROUTINE linres_calculation(force_env)
     311              : 
     312              :       TYPE(force_env_type), POINTER                      :: force_env
     313              : 
     314              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'linres_calculation'
     315              : 
     316              :       INTEGER                                            :: handle
     317              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     318              : 
     319          188 :       CALL timeset(routineN, handle)
     320              : 
     321          188 :       NULLIFY (qs_env)
     322              : 
     323          188 :       CPASSERT(ASSOCIATED(force_env))
     324          188 :       CPASSERT(force_env%ref_count > 0)
     325              : 
     326          370 :       SELECT CASE (force_env%in_use)
     327              :       CASE (use_qs_force)
     328          182 :          CALL force_env_get(force_env, qs_env=qs_env)
     329              :       CASE (use_qmmm)
     330            6 :          qs_env => force_env%qmmm_env%qs_env
     331              :       CASE DEFAULT
     332          188 :          CPABORT("Does not recognize this force_env")
     333              :       END SELECT
     334              : 
     335          188 :       qs_env%linres_run = .TRUE.
     336              : 
     337          188 :       CALL linres_calculation_low(qs_env)
     338              : 
     339          188 :       CALL timestop(handle)
     340              : 
     341          188 :    END SUBROUTINE linres_calculation
     342              : 
     343              : ! **************************************************************************************************
     344              : !> \brief Linear response can be called as run type or as post scf calculation
     345              : !>      Initialize the perturbation environment
     346              : !>      Define which properties is to be calculated
     347              : !>      Start up the optimization of the response density and wfn
     348              : !> \param qs_env ...
     349              : !> \par History
     350              : !>      06.2005 created [MI]
     351              : !>      02.2013 added polarizability section [SL]
     352              : !> \author MI
     353              : ! **************************************************************************************************
     354        27151 :    SUBROUTINE linres_calculation_low(qs_env)
     355              : 
     356              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     357              : 
     358              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'linres_calculation_low'
     359              : 
     360              :       INTEGER                                            :: every_n_step, handle, iounit
     361              :       LOGICAL                                            :: dcdr_present, do_apt_fd, epr_present, &
     362              :                                                             issc_present, lr_calculation, &
     363              :                                                             nmr_present, polar_present, vcd_present
     364              :       TYPE(cp_logger_type), POINTER                      :: logger
     365              :       TYPE(dft_control_type), POINTER                    :: dft_control
     366              :       TYPE(linres_control_type), POINTER                 :: linres_control
     367              :       TYPE(qs_p_env_type)                                :: p_env
     368              :       TYPE(section_vals_type), POINTER                   :: lr_section, prop_section
     369              : 
     370        27151 :       CALL timeset(routineN, handle)
     371              : 
     372              :       lr_calculation = .FALSE.
     373              :       nmr_present = .FALSE.
     374              :       epr_present = .FALSE.
     375              :       issc_present = .FALSE.
     376              :       polar_present = .FALSE.
     377              :       dcdr_present = .FALSE.
     378              :       do_apt_fd = .FALSE.
     379              : 
     380        27151 :       NULLIFY (dft_control, linres_control, logger, prop_section, lr_section)
     381              : 
     382        27151 :       lr_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%LINRES")
     383        27151 :       CALL section_vals_get(lr_section, explicit=lr_calculation)
     384              : 
     385        27151 :       CALL section_vals_val_get(lr_section, "DCDR%APT_FD", explicit=do_apt_fd)
     386        27151 :       IF (do_apt_fd) THEN
     387           14 :          CALL timestop(handle)
     388           14 :          RETURN
     389              :       END IF
     390              : 
     391        27137 :       logger => cp_get_default_logger()
     392              : 
     393        27137 :       CALL section_vals_val_get(lr_section, "EVERY_N_STEP", i_val=every_n_step)
     394              : 
     395        27137 :       IF (lr_calculation .AND. MODULO(qs_env%sim_step, every_n_step) == 0) THEN
     396          336 :          CALL linres_init(lr_section, p_env, qs_env)
     397              :          iounit = cp_print_key_unit_nr(logger, lr_section, "PRINT%PROGRAM_RUN_INFO", &
     398          336 :                                        extension=".linresLog")
     399              :          CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, &
     400          336 :                          linres_control=linres_control)
     401              : 
     402              :          ! The type of perturbation has not been defined yet
     403          336 :          linres_control%property = lr_none
     404              : 
     405              :          ! We do NMR or EPR, then compute the current response
     406          336 :          prop_section => section_vals_get_subs_vals(lr_section, "NMR")
     407          336 :          CALL section_vals_get(prop_section, explicit=nmr_present)
     408          336 :          prop_section => section_vals_get_subs_vals(lr_section, "EPR")
     409          336 :          CALL section_vals_get(prop_section, explicit=epr_present)
     410              : 
     411          336 :          IF (nmr_present .OR. epr_present) THEN
     412              :             CALL nmr_epr_linres(linres_control, qs_env, p_env, dft_control, &
     413          174 :                                 nmr_present, epr_present, iounit)
     414              :          END IF
     415              : 
     416              :          ! We do the indirect spin-spin coupling calculation
     417          336 :          prop_section => section_vals_get_subs_vals(lr_section, "SPINSPIN")
     418          336 :          CALL section_vals_get(prop_section, explicit=issc_present)
     419              : 
     420          336 :          IF (issc_present) THEN
     421           12 :             CALL issc_linres(linres_control, qs_env, p_env, dft_control)
     422              :          END IF
     423              : 
     424              :          ! We do the polarizability calculation
     425          336 :          prop_section => section_vals_get_subs_vals(lr_section, "POLAR")
     426          336 :          CALL section_vals_get(prop_section, explicit=polar_present)
     427          336 :          IF (polar_present) THEN
     428          126 :             CALL polar_linres(qs_env, p_env)
     429              :          END IF
     430              : 
     431              :          ! Nuclear Position Perturbation
     432          336 :          prop_section => section_vals_get_subs_vals(lr_section, "dcdr")
     433          336 :          CALL section_vals_get(prop_section, explicit=dcdr_present)
     434              : 
     435          336 :          IF (dcdr_present) THEN
     436           22 :             CALL dcdr_linres(qs_env, p_env)
     437              :          END IF
     438              : 
     439              :          ! VCD
     440          336 :          prop_section => section_vals_get_subs_vals(lr_section, "VCD")
     441          336 :          CALL section_vals_get(prop_section, explicit=vcd_present)
     442              : 
     443          336 :          IF (vcd_present) THEN
     444            2 :             CALL vcd_linres(qs_env, p_env)
     445              :          END IF
     446              : 
     447              :          ! Other possible LR calculations can be introduced here
     448              : 
     449          336 :          CALL p_env_release(p_env)
     450              : 
     451          336 :          IF (iounit > 0) THEN
     452              :             WRITE (UNIT=iounit, FMT="(/,T2,A,/,T25,A,/,T2,A,/)") &
     453          168 :                REPEAT("=", 79), &
     454          168 :                "ENDED LINRES CALCULATION", &
     455          336 :                REPEAT("=", 79)
     456              :          END IF
     457              :          CALL cp_print_key_finished_output(iounit, logger, lr_section, &
     458          336 :                                            "PRINT%PROGRAM_RUN_INFO")
     459              :       END IF
     460              : 
     461        27137 :       CALL timestop(handle)
     462              : 
     463       135755 :    END SUBROUTINE linres_calculation_low
     464              : 
     465              : ! **************************************************************************************************
     466              : !> \brief Initialize some general settings like the p_env
     467              : !>      Localize the psi0 if required
     468              : !> \param lr_section ...
     469              : !> \param p_env ...
     470              : !> \param qs_env ...
     471              : !> \par History
     472              : !>      06.2005 created [MI]
     473              : !> \author MI
     474              : !> \note
     475              : !>      - The localization should probably be always for all the occupied states
     476              : ! **************************************************************************************************
     477         2016 :    SUBROUTINE linres_init(lr_section, p_env, qs_env)
     478              : 
     479              :       TYPE(section_vals_type), POINTER                   :: lr_section
     480              :       TYPE(qs_p_env_type), INTENT(OUT)                   :: p_env
     481              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     482              : 
     483              :       INTEGER                                            :: iounit, ispin
     484              :       LOGICAL                                            :: do_it
     485              :       TYPE(cp_logger_type), POINTER                      :: logger
     486          336 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, rho_ao
     487              :       TYPE(dft_control_type), POINTER                    :: dft_control
     488              :       TYPE(linres_control_type), POINTER                 :: linres_control
     489          336 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     490              :       TYPE(qs_rho_type), POINTER                         :: rho
     491              :       TYPE(section_vals_type), POINTER                   :: loc_section
     492              : 
     493          336 :       NULLIFY (logger)
     494          336 :       logger => cp_get_default_logger()
     495              :       iounit = cp_print_key_unit_nr(logger, lr_section, "PRINT%PROGRAM_RUN_INFO", &
     496          336 :                                     extension=".linresLog")
     497          336 :       NULLIFY (dft_control, linres_control, loc_section, rho, mos, matrix_ks, rho_ao)
     498              : 
     499          336 :       ALLOCATE (linres_control)
     500          336 :       CALL set_qs_env(qs_env=qs_env, linres_control=linres_control)
     501              :       CALL get_qs_env(qs_env=qs_env, &
     502          336 :                       dft_control=dft_control, matrix_ks=matrix_ks, mos=mos, rho=rho)
     503          336 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
     504              : 
     505              :       ! Localized Psi0 are required when the position operator has to be defined (nmr)
     506          336 :       loc_section => section_vals_get_subs_vals(lr_section, "LOCALIZE")
     507              :       CALL section_vals_val_get(loc_section, "_SECTION_PARAMETERS_", &
     508          336 :                                 l_val=linres_control%localized_psi0)
     509          336 :       IF (linres_control%localized_psi0) THEN
     510          190 :          IF (iounit > 0) THEN
     511              :             WRITE (UNIT=iounit, FMT="(/,T3,A,A)") &
     512           95 :                "Localization of ground state orbitals", &
     513          190 :                " before starting linear response calculation"
     514              :          END IF
     515              : 
     516          190 :          CALL linres_localize(qs_env, linres_control, dft_control%nspins)
     517              : 
     518          458 :          DO ispin = 1, dft_control%nspins
     519          458 :             CALL calculate_density_matrix(mos(ispin), rho_ao(ispin)%matrix)
     520              :          END DO
     521              :          ! ** update qs_env%rho
     522          190 :          CALL qs_rho_update_rho(rho, qs_env=qs_env)
     523              :       END IF
     524              : 
     525          336 :       CALL section_vals_val_get(lr_section, "RESTART", l_val=linres_control%linres_restart)
     526          336 :       CALL section_vals_val_get(lr_section, "MAX_ITER", i_val=linres_control%max_iter)
     527          336 :       CALL section_vals_val_get(lr_section, "EPS", r_val=linres_control%eps)
     528          336 :       CALL section_vals_val_get(lr_section, "EPS_FILTER", r_val=linres_control%eps_filter)
     529          336 :       CALL section_vals_val_get(lr_section, "RESTART_EVERY", i_val=linres_control%restart_every)
     530          336 :       CALL section_vals_val_get(lr_section, "PRECONDITIONER", i_val=linres_control%preconditioner_type)
     531          336 :       CALL section_vals_val_get(lr_section, "ENERGY_GAP", r_val=linres_control%energy_gap)
     532              : 
     533          336 :       IF (iounit > 0) THEN
     534              :          WRITE (UNIT=iounit, FMT="(/,T2,A,/,T25,A,/,T2,A,/)") &
     535          168 :             REPEAT("=", 79), &
     536          168 :             "START LINRES CALCULATION", &
     537          336 :             REPEAT("=", 79)
     538              : 
     539              :          WRITE (UNIT=iounit, FMT="(T2,A)") &
     540          168 :             "LINRES| Properties to be calculated:"
     541          168 :          CALL section_vals_val_get(lr_section, "NMR%_SECTION_PARAMETERS_", l_val=do_it)
     542          168 :          IF (do_it) WRITE (UNIT=iounit, FMT="(T62,A)") "NMR Chemical Shift"
     543          168 :          CALL section_vals_val_get(lr_section, "EPR%_SECTION_PARAMETERS_", l_val=do_it)
     544          168 :          IF (do_it) WRITE (UNIT=iounit, FMT="(T68,A)") "EPR g Tensor"
     545          168 :          CALL section_vals_val_get(lr_section, "SPINSPIN%_SECTION_PARAMETERS_", l_val=do_it)
     546          168 :          IF (do_it) WRITE (UNIT=iounit, FMT="(T43,A)") "Indirect spin-spin coupling constants"
     547          168 :          CALL section_vals_val_get(lr_section, "POLAR%_SECTION_PARAMETERS_", l_val=do_it)
     548          168 :          IF (do_it) WRITE (UNIT=iounit, FMT="(T57,A)") "Electric Polarizability"
     549              : 
     550          168 :          IF (linres_control%localized_psi0) WRITE (UNIT=iounit, FMT="(T2,A,T65,A)") &
     551           95 :             "LINRES|", " LOCALIZED PSI0"
     552              : 
     553              :          WRITE (UNIT=iounit, FMT="(T2,A,T60,A)") &
     554          168 :             "LINRES| Optimization algorithm", " Conjugate Gradients"
     555              : 
     556          169 :          SELECT CASE (linres_control%preconditioner_type)
     557              :          CASE (ot_precond_none)
     558              :             WRITE (UNIT=iounit, FMT="(T2,A,T60,A)") &
     559            1 :                "LINRES| Preconditioner", "                NONE"
     560              :          CASE (ot_precond_full_single)
     561              :             WRITE (UNIT=iounit, FMT="(T2,A,T60,A)") &
     562            2 :                "LINRES| Preconditioner", "         FULL_SINGLE"
     563              :          CASE (ot_precond_full_kinetic)
     564              :             WRITE (UNIT=iounit, FMT="(T2,A,T60,A)") &
     565            3 :                "LINRES| Preconditioner", "        FULL_KINETIC"
     566              :          CASE (ot_precond_s_inverse)
     567              :             WRITE (UNIT=iounit, FMT="(T2,A,T60,A)") &
     568           12 :                "LINRES| Preconditioner", "      FULL_S_INVERSE"
     569              :          CASE (ot_precond_full_single_inverse)
     570              :             WRITE (UNIT=iounit, FMT="(T2,A,T60,A)") &
     571           32 :                "LINRES| Preconditioner", " FULL_SINGLE_INVERSE"
     572              :          CASE (ot_precond_full_all)
     573              :             WRITE (UNIT=iounit, FMT="(T2,A,T60,A)") &
     574          118 :                "LINRES| Preconditioner", "            FULL_ALL"
     575              :          CASE DEFAULT
     576          168 :             CPABORT("Preconditioner NYI")
     577              :          END SELECT
     578              : 
     579              :          WRITE (UNIT=iounit, FMT="(T2,A,T72,ES8.1)") &
     580          168 :             "LINRES| EPS", linres_control%eps
     581              :          WRITE (UNIT=iounit, FMT="(T2,A,T72,I8)") &
     582          168 :             "LINRES| MAX_ITER", linres_control%max_iter
     583              :       END IF
     584              : 
     585              :       !------------------!
     586              :       ! create the p_env !
     587              :       !------------------!
     588          336 :       CALL p_env_create(p_env, qs_env, orthogonal_orbitals=.TRUE., linres_control=linres_control)
     589              : 
     590              :       ! update the m_epsilon matrix
     591          336 :       CALL p_env_psi0_changed(p_env, qs_env)
     592              : 
     593          336 :       p_env%new_preconditioner = .TRUE.
     594              :       CALL cp_print_key_finished_output(iounit, logger, lr_section, &
     595          336 :                                         "PRINT%PROGRAM_RUN_INFO")
     596              : 
     597          336 :    END SUBROUTINE linres_init
     598              : 
     599              : ! **************************************************************************************************
     600              : !> \brief ...
     601              : !> \param linres_control ...
     602              : !> \param qs_env ...
     603              : !> \param p_env ...
     604              : !> \param dft_control ...
     605              : !> \param nmr_present ...
     606              : !> \param epr_present ...
     607              : !> \param iounit ...
     608              : ! **************************************************************************************************
     609          174 :    SUBROUTINE nmr_epr_linres(linres_control, qs_env, p_env, dft_control, nmr_present, epr_present, iounit)
     610              : 
     611              :       TYPE(linres_control_type), POINTER                 :: linres_control
     612              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     613              :       TYPE(qs_p_env_type)                                :: p_env
     614              :       TYPE(dft_control_type), POINTER                    :: dft_control
     615              :       LOGICAL                                            :: nmr_present, epr_present
     616              :       INTEGER                                            :: iounit
     617              : 
     618              :       INTEGER                                            :: iB
     619              :       LOGICAL                                            :: do_qmmm
     620              :       TYPE(current_env_type)                             :: current_env
     621              :       TYPE(epr_env_type)                                 :: epr_env
     622              :       TYPE(nmr_env_type)                                 :: nmr_env
     623              : 
     624          174 :       linres_control%property = lr_current
     625              : 
     626          174 :       CALL cite_reference(Weber2009)
     627              : 
     628          174 :       IF (.NOT. linres_control%localized_psi0) THEN
     629              :          CALL cp_abort(__LOCATION__, &
     630              :                        "Are you sure that you want to calculate the chemical "// &
     631            0 :                        "shift without localized psi0?")
     632              :          CALL linres_localize(qs_env, linres_control, &
     633            0 :                               dft_control%nspins, centers_only=.TRUE.)
     634              :       END IF
     635          174 :       IF (dft_control%nspins /= 2 .AND. epr_present) THEN
     636            0 :          CPABORT("LSD is needed to perform a g tensor calculation!")
     637              :       END IF
     638              :       !
     639              :       !Initialize the current environment
     640          174 :       do_qmmm = .FALSE.
     641          174 :       IF (qs_env%qmmm) do_qmmm = .TRUE.
     642          174 :       current_env%do_qmmm = do_qmmm
     643              :       !current_env%prop='nmr'
     644          174 :       CALL current_env_init(current_env, qs_env)
     645          174 :       CALL current_operators(current_env, qs_env)
     646          174 :       CALL current_response(current_env, p_env, qs_env)
     647              :       !
     648          174 :       IF (current_env%all_pert_op_done) THEN
     649              :          !Initialize the nmr environment
     650          174 :          IF (nmr_present) THEN
     651          160 :             CALL nmr_env_init(nmr_env, qs_env)
     652              :          END IF
     653              :          !
     654              :          !Initialize the epr environment
     655          174 :          IF (epr_present) THEN
     656           14 :             CALL epr_env_init(epr_env, qs_env)
     657           14 :             CALL epr_g_zke(epr_env, qs_env)
     658           14 :             CALL epr_nablavks(epr_env, qs_env)
     659              :          END IF
     660              :          !
     661              :          ! Build the rs_gauge if needed
     662              :          !CALL current_set_gauge(current_env,qs_env)
     663              :          !
     664              :          ! Loop over field direction
     665          696 :          DO iB = 1, 3
     666              :             !
     667              :             ! Build current response and succeptibility
     668          522 :             CALL current_build_current(current_env, qs_env, iB)
     669          522 :             CALL current_build_chi(current_env, qs_env, iB)
     670              :             !
     671              :             ! Compute NMR shift
     672          522 :             IF (nmr_present) THEN
     673          480 :                CALL nmr_shift(nmr_env, current_env, qs_env, iB)
     674              :             END IF
     675              :             !
     676              :             ! Compute EPR
     677          696 :             IF (epr_present) THEN
     678           42 :                CALL epr_ind_magnetic_field(epr_env, current_env, qs_env, iB)
     679           42 :                CALL epr_g_so(epr_env, current_env, qs_env, iB)
     680           42 :                CALL epr_g_soo(epr_env, current_env, qs_env, iB)
     681              :             END IF
     682              :          END DO
     683              :          !
     684              :          ! Finalized the nmr environment
     685          174 :          IF (nmr_present) THEN
     686          160 :             CALL nmr_shift_print(nmr_env, current_env, qs_env)
     687          160 :             CALL nmr_env_cleanup(nmr_env)
     688              :          END IF
     689              :          !
     690              :          ! Finalized the epr environment
     691          174 :          IF (epr_present) THEN
     692           14 :             CALL epr_g_print(epr_env, qs_env)
     693           14 :             CALL epr_env_cleanup(epr_env)
     694              :          END IF
     695              :          !
     696              :       ELSE
     697            0 :          IF (iounit > 0) THEN
     698              :             WRITE (iounit, "(T10,A,/T20,A,/)") &
     699            0 :                "CURRENT: Not all responses to perturbation operators could be calculated.", &
     700            0 :                " Hence: NO nmr and NO epr possible."
     701              :          END IF
     702              :       END IF
     703              :       ! Finalized the current environment
     704          174 :       CALL current_env_cleanup(current_env)
     705              : 
     706        12702 :    END SUBROUTINE nmr_epr_linres
     707              : 
     708              : ! **************************************************************************************************
     709              : !> \brief ...
     710              : !> \param linres_control ...
     711              : !> \param qs_env ...
     712              : !> \param p_env ...
     713              : !> \param dft_control ...
     714              : ! **************************************************************************************************
     715           12 :    SUBROUTINE issc_linres(linres_control, qs_env, p_env, dft_control)
     716              : 
     717              :       TYPE(linres_control_type), POINTER                 :: linres_control
     718              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     719              :       TYPE(qs_p_env_type)                                :: p_env
     720              :       TYPE(dft_control_type), POINTER                    :: dft_control
     721              : 
     722              :       INTEGER                                            :: iatom
     723              :       LOGICAL                                            :: do_qmmm
     724              :       TYPE(current_env_type)                             :: current_env
     725              :       TYPE(issc_env_type)                                :: issc_env
     726              : 
     727           12 :       linres_control%property = lr_current
     728           12 :       IF (.NOT. linres_control%localized_psi0) THEN
     729              :          CALL cp_abort(__LOCATION__, &
     730              :                        "Are you sure that you want to calculate the chemical "// &
     731            0 :                        "shift without localized psi0?")
     732              :          CALL linres_localize(qs_env, linres_control, &
     733            0 :                               dft_control%nspins, centers_only=.TRUE.)
     734              :       END IF
     735              :       !
     736              :       !Initialize the current environment
     737              :       do_qmmm = .FALSE.
     738              :       IF (qs_env%qmmm) do_qmmm = .TRUE.
     739           12 :       current_env%do_qmmm = do_qmmm
     740              :       !current_env%prop='issc'
     741              :       !CALL current_env_init(current_env,qs_env)
     742              :       !CALL current_response(current_env,p_env,qs_env)
     743              :       !
     744              :       !Initialize the issc environment
     745           12 :       CALL issc_env_init(issc_env, qs_env)
     746              :       !
     747              :       ! Loop over atoms
     748           56 :       DO iatom = 1, issc_env%issc_natms
     749           44 :          CALL issc_operators(issc_env, qs_env, iatom)
     750           44 :          CALL issc_response(issc_env, p_env, qs_env)
     751           56 :          CALL issc_issc(issc_env, qs_env, iatom)
     752              :       END DO
     753              :       !
     754              :       ! Finalized the issc environment
     755           12 :       CALL issc_print(issc_env, qs_env)
     756           12 :       CALL issc_env_cleanup(issc_env)
     757              : 
     758          888 :    END SUBROUTINE issc_linres
     759              : 
     760              : ! **************************************************************************************************
     761              : !> \brief ...
     762              : !> \param qs_env ...
     763              : !> \param p_env ...
     764              : !> \par History
     765              : !>      06.2018 polar_env integrated into qs_env (MK)
     766              : ! **************************************************************************************************
     767          126 :    SUBROUTINE polar_linres(qs_env, p_env)
     768              : 
     769              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     770              :       TYPE(qs_p_env_type)                                :: p_env
     771              : 
     772          126 :       CALL polar_env_init(qs_env)
     773          126 :       CALL polar_operators(qs_env)
     774          126 :       CALL polar_response(p_env, qs_env)
     775          126 :       CALL polar_polar(qs_env)
     776          126 :       CALL polar_print(qs_env)
     777              : 
     778          126 :    END SUBROUTINE polar_linres
     779              : 
     780              : END MODULE qs_linres_module
        

Generated by: LCOV version 2.0-1