LCOV - code coverage report
Current view: top level - src - localized_moments.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:06f838d) Lines: 45.5 % 453 206
Test Date: 2026-06-05 07:04:50 Functions: 66.7 % 3 2

            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 Routines for the calculation of moments from Wannier functions
      10              : !> \author Lukas Schreder
      11              : ! **************************************************************************************************
      12              : MODULE localized_moments
      13              : 
      14              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      15              :                                               get_atomic_kind
      16              :    USE bibliography,                    ONLY: Schreder2021,&
      17              :                                               Schreder2024_1,&
      18              :                                               cite_reference
      19              :    USE cell_types,                      ONLY: cell_type,&
      20              :                                               pbc
      21              :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_gemm
      22              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      23              :                                               cp_cfm_get_element,&
      24              :                                               cp_cfm_release,&
      25              :                                               cp_cfm_type,&
      26              :                                               cp_fm_to_cfm
      27              :    USE cp_control_types,                ONLY: dft_control_type
      28              :    USE cp_dbcsr_api,                    ONLY: &
      29              :         dbcsr_copy, dbcsr_create, dbcsr_get_readonly_block_p, dbcsr_init_p, &
      30              :         dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, dbcsr_iterator_readonly_start, &
      31              :         dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, dbcsr_set, dbcsr_type, &
      32              :         dbcsr_type_antisymmetric, dbcsr_type_symmetric
      33              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      34              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      35              :                                               dbcsr_allocate_matrix_set,&
      36              :                                               dbcsr_deallocate_matrix_set
      37              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      38              :                                               cp_fm_struct_release,&
      39              :                                               cp_fm_struct_type
      40              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      41              :                                               cp_fm_get_info,&
      42              :                                               cp_fm_release,&
      43              :                                               cp_fm_set_all,&
      44              :                                               cp_fm_to_fm,&
      45              :                                               cp_fm_type
      46              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      47              :                                               cp_logger_type
      48              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      49              :                                               cp_print_key_unit_nr
      50              :    USE input_constants,                 ONLY: use_mom_ref_com
      51              :    USE input_section_types,             ONLY: section_vals_type
      52              :    USE kg_environment_types,            ONLY: kg_environment_type
      53              :    USE kinds,                           ONLY: default_string_length,&
      54              :                                               dp
      55              :    USE message_passing,                 ONLY: mp_para_env_type
      56              :    USE molecule_kind_types,             ONLY: get_molecule_kind,&
      57              :                                               molecule_kind_type
      58              :    USE molecule_types,                  ONLY: molecule_type
      59              :    USE moments_utils,                   ONLY: get_reference_point
      60              :    USE orbital_pointers,                ONLY: current_maxl,&
      61              :                                               indco
      62              :    USE particle_types,                  ONLY: particle_type
      63              :    USE qs_environment_types,            ONLY: get_qs_env,&
      64              :                                               qs_environment_type
      65              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      66              :                                               qs_kind_type
      67              :    USE qs_loc_types,                    ONLY: qs_loc_env_type
      68              :    USE qs_moments,                      ONLY: build_local_magmom_matrix,&
      69              :                                               build_local_moment_matrix,&
      70              :                                               build_local_moments_der_matrix,&
      71              :                                               calculate_commutator_nl_terms,&
      72              :                                               print_moments,&
      73              :                                               print_moments_nl,&
      74              :                                               set_label
      75              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      76              :    USE qs_operators_ao,                 ONLY: build_lin_mom_matrix
      77              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      78              :                                               qs_rho_type
      79              : #include "./base/base_uses.f90"
      80              : 
      81              :    IMPLICIT NONE
      82              : 
      83              :    PRIVATE
      84              : 
      85              : ! *** public subroutines ***
      86              : 
      87              :    PUBLIC :: calculate_kg_moments, &
      88              :              calculate_localized_moments
      89              : 
      90              : ! *** body ***
      91              : 
      92              : CONTAINS
      93              : 
      94              : ! **************************************************************************************************
      95              : !> \brief Calculates localized multipole moments per molecule in the Wannier MO basis
      96              : !> \param qs_env ...
      97              : !> \param qs_loc_env ...
      98              : !> \param mo_local ...
      99              : !> \param max_moment ...
     100              : !> \param magnetic ...
     101              : !> \param vel_reprs ...
     102              : !> \param com_nl ...
     103              : !> \param loc_print_section ...
     104              : ! **************************************************************************************************
     105           12 :    SUBROUTINE calculate_localized_moments(qs_env, qs_loc_env, mo_local, max_moment, magnetic, &
     106              :                                           vel_reprs, com_nl, loc_print_section)
     107              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     108              :       TYPE(qs_loc_env_type), INTENT(IN)                  :: qs_loc_env
     109              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: mo_local
     110              :       INTEGER, INTENT(IN)                                :: max_moment
     111              :       LOGICAL, INTENT(IN)                                :: magnetic, vel_reprs, com_nl
     112              :       TYPE(section_vals_type), POINTER                   :: loc_print_section
     113              : 
     114              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_localized_moments'
     115              : 
     116           12 :       CHARACTER(LEN=8), ALLOCATABLE, DIMENSION(:)        :: rlab
     117              :       CHARACTER(LEN=default_string_length)               :: mol_name
     118              :       INTEGER :: akind, first_atom, handle, i, iatom, idir, imo_im, imo_re, imol, iounit, iproc, &
     119              :          ispin, ix, iy, iz, l, last_atom, nao, natom, nm, nmols, nmom, ns, nspins, order, &
     120              :          rmom_vel_size
     121           12 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: states
     122              :       INTEGER, DIMENSION(2)                              :: nstates
     123              :       LOGICAL                                            :: do_rtp, floating, ghost
     124              :       REAL(dp)                                           :: charge, dd, im_part, re_part, zwfc
     125           12 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: mmom, nlcom_rrv, nlcom_rrv_vrr, &
     126           12 :                                                             nlcom_rv, nlcom_rvr, nlcom_rxrv, &
     127           12 :                                                             qupole_der, rmom_vel
     128           12 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: rmom
     129              :       REAL(dp), DIMENSION(3)                             :: rcc, ria
     130           12 :       REAL(dp), DIMENSION(:), POINTER                    :: ref_point
     131              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     132              :       TYPE(cell_type), POINTER                           :: cell
     133              :       TYPE(cp_cfm_type)                                  :: ov_cfm, v_cfm, vov_cfm
     134              :       TYPE(cp_fm_struct_type), POINTER                   :: o_struct, v_struct, vov_struct
     135              :       TYPE(cp_fm_type)                                   :: or_fm, vi_fm, vr_fm
     136              :       TYPE(cp_logger_type), POINTER                      :: logger
     137           12 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: magmom, matrix_s, moments, momentum
     138           12 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: moments_der
     139              :       TYPE(dft_control_type), POINTER                    :: dft_control
     140              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     141           12 :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
     142              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     143              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     144           12 :          POINTER                                         :: sab_orb
     145           12 :       TYPE(particle_type), POINTER                       :: particle_set(:)
     146           12 :       TYPE(qs_kind_type), POINTER                        :: qs_kind_set(:)
     147              : 
     148           12 :       CALL timeset(routineN, handle)
     149              : 
     150           12 :       CALL cite_reference(Schreder2021)
     151           12 :       IF (max_moment > 1 .OR. magnetic .OR. vel_reprs .OR. com_nl) THEN
     152           12 :          CALL cite_reference(Schreder2024_1)
     153              :       END IF
     154              : 
     155           12 :       logger => cp_get_default_logger()
     156              : 
     157           12 :       NULLIFY (cell, dft_control, matrix_s, molecule_set, qs_kind_set, sab_orb)
     158              :       CALL get_qs_env(qs_env, &
     159              :                       cell=cell, &
     160              :                       dft_control=dft_control, &
     161              :                       matrix_s=matrix_s, &
     162              :                       molecule_set=molecule_set, &
     163              :                       qs_kind_set=qs_kind_set, &
     164           12 :                       sab_orb=sab_orb)
     165           12 :       particle_set => qs_loc_env%particle_set
     166           12 :       para_env => qs_loc_env%para_env
     167              : 
     168           12 :       nspins = dft_control%nspins
     169           12 :       zwfc = 3.0_dp - REAL(nspins, KIND=dp)
     170              :       ! mo_local is sized nspins for SCF and 2*nspins for RTP (real, imag interleaved per spin)
     171           12 :       do_rtp = qs_env%run_rtp .OR. (SIZE(mo_local) == 2*nspins)
     172              : 
     173           12 :       nmom = MIN(max_moment, current_maxl)
     174              :       ! number of independent multipole components for orders 1..nmom
     175           12 :       nm = (6 + 11*nmom + 6*nmom**2 + nmom**3)/6 - 1
     176           12 :       nmols = SIZE(molecule_set)
     177              : 
     178              :       iounit = cp_print_key_unit_nr(logger, loc_print_section, "LOCALIZED_MOMENTS", &
     179           12 :                                     extension=".LocMom", middle_name="LOCALIZED_MOMENTS")
     180              : 
     181           72 :       ALLOCATE (rmom(nm + 1, 3), rlab(nm + 1))
     182           12 :       IF (magnetic) ALLOCATE (mmom(3))
     183           12 :       IF (vel_reprs) THEN
     184           12 :          IF (com_nl .AND. (nmom >= 2)) THEN
     185              :             rmom_vel_size = 21
     186              :          ELSE
     187           12 :             rmom_vel_size = MAX(nm, 9)
     188              :          END IF
     189           36 :          ALLOCATE (rmom_vel(rmom_vel_size))
     190              :       END IF
     191              : 
     192           48 :       DO imol = 1, nmols
     193           36 :          molecule_kind => molecule_set(imol)%molecule_kind
     194           36 :          first_atom = molecule_set(imol)%first_atom
     195           36 :          last_atom = molecule_set(imol)%last_atom
     196           36 :          CALL get_molecule_kind(molecule_kind=molecule_kind, natom=natom, name=mol_name)
     197           36 :          NULLIFY (ref_point)
     198              :          CALL get_reference_point(rcc, qs_env=qs_env, reference=use_mom_ref_com, &
     199              :                                   ref_point=ref_point, ifirst=first_atom, &
     200           36 :                                   ilast=last_atom)
     201              : 
     202           36 :          rmom = 0.0_dp
     203          180 :          rlab = ""
     204              : 
     205           36 :          NULLIFY (moments)
     206           36 :          CALL dbcsr_allocate_matrix_set(moments, nm)
     207          144 :          DO i = 1, nm
     208          108 :             ALLOCATE (moments(i)%matrix)
     209          108 :             IF (vel_reprs .AND. (nmom >= 2)) THEN
     210              :                CALL dbcsr_create(moments(i)%matrix, template=matrix_s(1)%matrix, &
     211            0 :                                  matrix_type=dbcsr_type_symmetric)
     212            0 :                CALL cp_dbcsr_alloc_block_from_nbl(moments(i)%matrix, sab_orb)
     213              :             ELSE
     214          108 :                CALL dbcsr_copy(moments(i)%matrix, matrix_s(1)%matrix, "Moments")
     215              :             END IF
     216          144 :             CALL dbcsr_set(moments(i)%matrix, 0.0_dp)
     217              :          END DO
     218           36 :          IF (vel_reprs .AND. (nmom >= 2)) THEN
     219            0 :             NULLIFY (moments_der)
     220            0 :             CALL dbcsr_allocate_matrix_set(moments_der, 3, 3)
     221            0 :             DO i = 1, 3
     222            0 :                DO idir = 1, 3
     223            0 :                   CALL dbcsr_init_p(moments_der(i, idir)%matrix)
     224              :                   CALL dbcsr_create(moments_der(i, idir)%matrix, template=matrix_s(1)%matrix, &
     225            0 :                                     matrix_type=dbcsr_type_antisymmetric)
     226            0 :                   CALL cp_dbcsr_alloc_block_from_nbl(moments_der(i, idir)%matrix, sab_orb)
     227            0 :                   CALL dbcsr_set(moments_der(i, idir)%matrix, 0.0_dp)
     228              :                END DO
     229              :             END DO
     230              :             CALL build_local_moments_der_matrix(qs_env, moments_der, 1, 2, ref_point=rcc, &
     231            0 :                                                 moments=moments)
     232              :          ELSE
     233           36 :             CALL build_local_moment_matrix(qs_env, moments, nmom, ref_point=rcc)
     234              :          END IF
     235              : 
     236           36 :          IF (magnetic) THEN
     237           36 :             NULLIFY (magmom)
     238           36 :             CALL dbcsr_allocate_matrix_set(magmom, 3)
     239          144 :             DO i = 1, 3
     240          108 :                CALL dbcsr_init_p(magmom(i)%matrix)
     241              :                CALL dbcsr_create(magmom(i)%matrix, template=matrix_s(1)%matrix, &
     242          108 :                                  matrix_type=dbcsr_type_antisymmetric)
     243          108 :                CALL cp_dbcsr_alloc_block_from_nbl(magmom(i)%matrix, sab_orb)
     244          144 :                CALL dbcsr_set(magmom(i)%matrix, 0.0_dp)
     245              :             END DO
     246           36 :             CALL build_local_magmom_matrix(qs_env, magmom, nmom, ref_point=rcc)
     247           36 :             mmom = 0.0_dp
     248              :          END IF
     249              : 
     250           36 :          IF (vel_reprs) THEN
     251           36 :             NULLIFY (momentum)
     252           36 :             CALL dbcsr_allocate_matrix_set(momentum, 3)
     253          144 :             DO i = 1, 3
     254          108 :                CALL dbcsr_init_p(momentum(i)%matrix)
     255              :                CALL dbcsr_create(momentum(i)%matrix, template=matrix_s(1)%matrix, &
     256          108 :                                  matrix_type=dbcsr_type_antisymmetric)
     257          108 :                CALL cp_dbcsr_alloc_block_from_nbl(momentum(i)%matrix, sab_orb)
     258          144 :                CALL dbcsr_set(momentum(i)%matrix, 0.0_dp)
     259              :             END DO
     260           36 :             CALL build_lin_mom_matrix(qs_env, momentum)
     261           36 :             rmom_vel = 0.0_dp
     262              :          END IF
     263              : 
     264           36 :          CALL cp_fm_get_info(mo_local(1), nrow_global=nao)
     265              :          CALL cp_fm_struct_create(o_struct, nrow_global=nao, ncol_global=nao, &
     266           36 :                                   template_fmstruct=mo_local(1)%matrix_struct)
     267           36 :          CALL cp_fm_create(or_fm, o_struct)
     268              : 
     269           72 :          DO ispin = 1, nspins
     270           36 :             IF (ASSOCIATED(molecule_set(imol)%lmi)) THEN
     271           18 :                nstates(1) = molecule_set(imol)%lmi(ispin)%nstates
     272              :             ELSE
     273           18 :                nstates(1) = 0
     274              :             END IF
     275           36 :             nstates(2) = para_env%mepos
     276           36 :             CALL para_env%maxloc(nstates)
     277           36 :             IF (nstates(1) == 0) CYCLE
     278           36 :             ns = nstates(1)
     279           36 :             iproc = nstates(2)
     280          108 :             ALLOCATE (states(ns))
     281           36 :             IF (iproc == para_env%mepos) THEN
     282          222 :                states(:) = molecule_set(imol)%lmi(ispin)%states(:)
     283              :             ELSE
     284           18 :                states(:) = 0
     285              :             END IF
     286           36 :             CALL para_env%bcast(states, iproc)
     287              : 
     288           36 :             IF (do_rtp) THEN
     289           24 :                imo_re = 2*ispin - 1
     290           24 :                imo_im = 2*ispin
     291              :             ELSE
     292              :                imo_re = ispin
     293              :                imo_im = 0
     294              :             END IF
     295              : 
     296              :             CALL cp_fm_struct_create(v_struct, nrow_global=nao, ncol_global=ns, &
     297           36 :                                      template_fmstruct=mo_local(imo_re)%matrix_struct)
     298              :             CALL cp_fm_struct_create(vov_struct, nrow_global=ns, ncol_global=ns, &
     299           36 :                                      template_fmstruct=mo_local(imo_re)%matrix_struct)
     300           36 :             CALL cp_fm_create(vr_fm, v_struct, name="vr")
     301           36 :             CALL cp_fm_set_all(vr_fm, 0.0_dp)
     302           36 :             IF (do_rtp) THEN
     303           24 :                CALL cp_fm_create(vi_fm, v_struct, name="vi")
     304           24 :                CALL cp_fm_set_all(vi_fm, 0.0_dp)
     305              :             END IF
     306           36 :             CALL cp_cfm_create(v_cfm, v_struct, name="v")
     307           36 :             CALL cp_cfm_create(ov_cfm, v_struct, name="ov")
     308           36 :             CALL cp_cfm_create(vov_cfm, vov_struct, name="vov")
     309           36 :             CALL cp_fm_struct_release(v_struct)
     310           36 :             CALL cp_fm_struct_release(vov_struct)
     311              : 
     312          444 :             DO i = 1, ns
     313          408 :                CALL cp_fm_to_fm(mo_local(imo_re), vr_fm, 1, states(i), i)
     314          444 :                IF (do_rtp) THEN
     315          272 :                   CALL cp_fm_to_fm(mo_local(imo_im), vi_fm, 1, states(i), i)
     316              :                END IF
     317              :             END DO
     318           36 :             IF (do_rtp) THEN
     319           24 :                CALL cp_fm_to_cfm(vr_fm, vi_fm, v_cfm)
     320           24 :                CALL cp_fm_release(vi_fm)
     321              :             ELSE
     322           12 :                CALL cp_fm_to_cfm(vr_fm, mtarget=v_cfm)
     323              :             END IF
     324           36 :             CALL cp_fm_release(vr_fm)
     325              : 
     326          144 :             DO i = 1, nm
     327              :                CALL trace_op_in_mo(moments(i)%matrix, or_fm, v_cfm, ov_cfm, vov_cfm, &
     328          108 :                                    o_struct, ns, nao, re_part, im_part)
     329          144 :                rmom(i + 1, 1) = rmom(i + 1, 1) + zwfc*re_part
     330              :             END DO
     331           36 :             rmom(1, 1) = rmom(1, 1) + zwfc*REAL(ns, KIND=dp)
     332              : 
     333           36 :             IF (magnetic) THEN
     334          144 :                DO i = 1, 3
     335              :                   CALL trace_op_in_mo(magmom(i)%matrix, or_fm, v_cfm, ov_cfm, vov_cfm, &
     336          108 :                                       o_struct, ns, nao, re_part, im_part)
     337          144 :                   mmom(i) = mmom(i) - zwfc*im_part
     338              :                END DO
     339              :             END IF
     340              : 
     341           36 :             IF (vel_reprs) THEN
     342           72 :                DO order = 1, nmom
     343           36 :                   SELECT CASE (order)
     344              :                   CASE (1)
     345          144 :                      DO i = 1, 3
     346              :                         CALL trace_op_in_mo(momentum(i)%matrix, or_fm, v_cfm, ov_cfm, vov_cfm, &
     347          108 :                                             o_struct, ns, nao, re_part, im_part)
     348          144 :                         rmom_vel(i) = rmom_vel(i) - zwfc*im_part
     349              :                      END DO
     350              :                   CASE (2)
     351            0 :                      ALLOCATE (qupole_der(9))
     352            0 :                      qupole_der = 0.0_dp
     353            0 :                      DO i = 1, 3
     354            0 :                         DO idir = 1, 3
     355              :                            CALL trace_op_in_mo(moments_der(i, idir)%matrix, or_fm, v_cfm, ov_cfm, &
     356            0 :                                                vov_cfm, o_struct, ns, nao, re_part, im_part)
     357              :                            qupole_der((i - 1)*3 + idir) = &
     358            0 :                               qupole_der((i - 1)*3 + idir) + zwfc*(re_part - im_part)
     359              :                         END DO
     360              :                      END DO
     361            0 :                      rmom_vel(4) = -2.0_dp*qupole_der(1) - rmom(1, 1)
     362            0 :                      rmom_vel(5) = -qupole_der(2) - qupole_der(4)
     363            0 :                      rmom_vel(6) = -qupole_der(3) - qupole_der(7)
     364            0 :                      rmom_vel(7) = -2.0_dp*qupole_der(5) - rmom(1, 1)
     365            0 :                      rmom_vel(8) = -qupole_der(6) - qupole_der(8)
     366            0 :                      rmom_vel(9) = -2.0_dp*qupole_der(9) - rmom(1, 1)
     367           36 :                      DEALLOCATE (qupole_der)
     368              :                   END SELECT
     369              :                END DO
     370              :             END IF
     371              : 
     372           36 :             CALL cp_cfm_release(v_cfm)
     373           36 :             CALL cp_cfm_release(ov_cfm)
     374           36 :             CALL cp_cfm_release(vov_cfm)
     375          144 :             DEALLOCATE (states)
     376              :          END DO
     377              : 
     378           36 :          CALL cp_fm_release(or_fm)
     379           36 :          CALL cp_fm_struct_release(o_struct)
     380              : 
     381           36 :          CALL para_env%sum(rmom(:, 1))
     382           36 :          IF (magnetic) CALL para_env%sum(mmom)
     383           36 :          IF (vel_reprs) CALL para_env%sum(rmom_vel)
     384              : 
     385          264 :          DO iatom = first_atom, first_atom + natom - 1
     386         1824 :             ria = pbc(particle_set(iatom)%r - rcc, cell) + rcc
     387          912 :             ria = ria - rcc
     388          228 :             atomic_kind => particle_set(iatom)%atomic_kind
     389          228 :             CALL get_atomic_kind(atomic_kind, kind_number=akind)
     390              :             CALL get_qs_kind(qs_kind_set(akind), ghost=ghost, floating=floating, &
     391          228 :                              core_charge=charge)
     392          228 :             IF (ghost .OR. floating) CYCLE
     393          228 :             rmom(1, 2) = rmom(1, 2) - charge
     394         1176 :             DO l = 1, nm
     395          684 :                ix = indco(1, l + 1)
     396          684 :                iy = indco(2, l + 1)
     397          684 :                iz = indco(3, l + 1)
     398          684 :                dd = 1.0_dp
     399          684 :                IF (ix > 0) dd = dd*ria(1)**ix
     400          684 :                IF (iy > 0) dd = dd*ria(2)**iy
     401          684 :                IF (iz > 0) dd = dd*ria(3)**iz
     402          684 :                rmom(l + 1, 2) = rmom(l + 1, 2) - charge*dd
     403          912 :                CALL set_label(rlab(l + 1), ix, iy, iz)
     404              :             END DO
     405              :          END DO
     406          576 :          rmom(:, :) = -rmom(:, :)
     407          180 :          rmom(:, 3) = rmom(:, 1) + rmom(:, 2)
     408              : 
     409           36 :          IF (com_nl) THEN
     410           36 :             IF ((nmom >= 1) .AND. vel_reprs) THEN
     411           36 :                ALLOCATE (nlcom_rv(3))
     412           36 :                nlcom_rv(:) = 0.0_dp
     413              :             END IF
     414           36 :             IF ((nmom >= 2) .AND. vel_reprs) THEN
     415            0 :                ALLOCATE (nlcom_rrv(6), nlcom_rvr(6), nlcom_rrv_vrr(6))
     416            0 :                nlcom_rrv(:) = 0.0_dp
     417            0 :                nlcom_rvr(:) = 0.0_dp
     418            0 :                nlcom_rrv_vrr(:) = 0.0_dp
     419              :             END IF
     420           36 :             IF (magnetic) THEN
     421           36 :                ALLOCATE (nlcom_rxrv(3))
     422           36 :                nlcom_rxrv(:) = 0.0_dp
     423              :             END IF
     424              :             CALL calculate_commutator_nl_terms(qs_env, nlcom_rv, nlcom_rxrv, nlcom_rrv, &
     425           36 :                                                nlcom_rvr, nlcom_rrv_vrr, rcc)
     426              :          END IF
     427              : 
     428           36 :          IF (iounit > 0) THEN
     429              :             WRITE (UNIT=iounit, FMT='(/,T3,A,I6,2X,A)') &
     430           18 :                "# Molecule:", imol, TRIM(mol_name)
     431           18 :             IF (magnetic .AND. vel_reprs) THEN
     432              :                CALL print_moments(iounit, nmom, rmom, rlab, rcc, cell, periodic=.FALSE., &
     433           18 :                                   mmom=mmom, rmom_vel=rmom_vel)
     434            0 :             ELSE IF (magnetic) THEN
     435              :                CALL print_moments(iounit, nmom, rmom, rlab, rcc, cell, periodic=.FALSE., &
     436            0 :                                   mmom=mmom)
     437            0 :             ELSE IF (vel_reprs) THEN
     438              :                CALL print_moments(iounit, nmom, rmom, rlab, rcc, cell, periodic=.FALSE., &
     439            0 :                                   rmom_vel=rmom_vel)
     440              :             ELSE
     441            0 :                CALL print_moments(iounit, nmom, rmom, rlab, rcc, cell, periodic=.FALSE.)
     442              :             END IF
     443              : 
     444           18 :             IF (com_nl) THEN
     445           72 :                IF (magnetic) mmom(:) = nlcom_rxrv(:)
     446           72 :                IF (vel_reprs .AND. (nmom >= 1)) rmom_vel(1:3) = nlcom_rv
     447           18 :                IF (vel_reprs .AND. (nmom >= 2)) THEN
     448            0 :                   rmom_vel(4:9) = nlcom_rrv
     449            0 :                   rmom_vel(10:15) = nlcom_rvr
     450            0 :                   rmom_vel(16:21) = nlcom_rrv_vrr
     451              :                END IF
     452           18 :                IF (magnetic .AND. vel_reprs) THEN
     453           18 :                   CALL print_moments_nl(iounit, nmom, rlab, mmom=mmom, rmom_vel=rmom_vel)
     454            0 :                ELSE IF (magnetic) THEN
     455            0 :                   CALL print_moments_nl(iounit, nmom, rlab, mmom=mmom)
     456            0 :                ELSE IF (vel_reprs) THEN
     457            0 :                   CALL print_moments_nl(iounit, nmom, rlab, rmom_vel=rmom_vel)
     458              :                END IF
     459              :             END IF
     460              :          END IF
     461              : 
     462           36 :          IF (com_nl) THEN
     463           36 :             IF ((nmom >= 1) .AND. vel_reprs) DEALLOCATE (nlcom_rv)
     464           36 :             IF ((nmom >= 2) .AND. vel_reprs) DEALLOCATE (nlcom_rrv, nlcom_rvr, nlcom_rrv_vrr)
     465           36 :             IF (magnetic) DEALLOCATE (nlcom_rxrv)
     466              :          END IF
     467           36 :          CALL dbcsr_deallocate_matrix_set(moments)
     468           36 :          IF (vel_reprs .AND. (nmom >= 2)) CALL dbcsr_deallocate_matrix_set(moments_der)
     469           36 :          IF (magnetic) CALL dbcsr_deallocate_matrix_set(magmom)
     470          156 :          IF (vel_reprs) CALL dbcsr_deallocate_matrix_set(momentum)
     471              :       END DO
     472              : 
     473           12 :       DEALLOCATE (rmom, rlab)
     474           12 :       IF (magnetic) DEALLOCATE (mmom)
     475           12 :       IF (vel_reprs) DEALLOCATE (rmom_vel)
     476              : 
     477           12 :       CALL cp_print_key_finished_output(iounit, logger, loc_print_section, "LOCALIZED_MOMENTS")
     478              : 
     479           12 :       CALL timestop(handle)
     480              : 
     481           24 :    END SUBROUTINE calculate_localized_moments
     482              : 
     483              : ! **************************************************************************************************
     484              : !> \brief Trace a real dbcsr operator against a complex MO matrix
     485              : !> \param op_dbcsr ...
     486              : !> \param or_fm ...
     487              : !> \param v_cfm ...
     488              : !> \param ov_cfm ...
     489              : !> \param vov_cfm ...
     490              : !> \param o_struct ...
     491              : !> \param ns ...
     492              : !> \param nao ...
     493              : !> \param re_sum ...
     494              : !> \param im_sum ...
     495              : ! **************************************************************************************************
     496          648 :    SUBROUTINE trace_op_in_mo(op_dbcsr, or_fm, v_cfm, ov_cfm, vov_cfm, o_struct, ns, nao, &
     497              :                              re_sum, im_sum)
     498              :       TYPE(dbcsr_type), POINTER                          :: op_dbcsr
     499              :       TYPE(cp_fm_type), INTENT(INOUT)                    :: or_fm
     500              :       TYPE(cp_cfm_type), INTENT(IN)                      :: v_cfm
     501              :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: ov_cfm, vov_cfm
     502              :       TYPE(cp_fm_struct_type), POINTER                   :: o_struct
     503              :       INTEGER, INTENT(IN)                                :: ns, nao
     504              :       REAL(dp), INTENT(OUT)                              :: re_sum, im_sum
     505              : 
     506              :       COMPLEX(dp)                                        :: di
     507              :       INTEGER                                            :: j
     508              :       TYPE(cp_cfm_type)                                  :: o_cfm
     509              : 
     510          324 :       CALL copy_dbcsr_to_fm(op_dbcsr, or_fm)
     511          324 :       CALL cp_cfm_create(o_cfm, o_struct)
     512          324 :       CALL cp_fm_to_cfm(or_fm, mtarget=o_cfm)
     513              :       CALL cp_cfm_gemm("N", "N", nao, ns, nao, (1._dp, 0._dp), o_cfm, v_cfm, &
     514          324 :                        (0._dp, 0._dp), ov_cfm)
     515              :       CALL cp_cfm_gemm("C", "N", ns, ns, nao, (1._dp, 0._dp), v_cfm, ov_cfm, &
     516          324 :                        (0._dp, 0._dp), vov_cfm)
     517          324 :       re_sum = 0.0_dp
     518          324 :       im_sum = 0.0_dp
     519         3996 :       DO j = 1, ns
     520         3672 :          CALL cp_cfm_get_element(vov_cfm, j, j, di)
     521         3672 :          re_sum = re_sum + REAL(di, KIND=dp)
     522         3996 :          im_sum = im_sum + AIMAG(di)
     523              :       END DO
     524          324 :       CALL cp_cfm_release(o_cfm)
     525              : 
     526          324 :    END SUBROUTINE trace_op_in_mo
     527              : 
     528              : ! **************************************************************************************************
     529              : !> \brief Calculates multipole moments per molecule from the Kim-Gordon AO density matrix
     530              : !> \param qs_env ...
     531              : !> \param unit_nr  output unit (the open DFT%PRINT%MOMENTS unit from the caller)
     532              : !> \param max_moment ...
     533              : !> \param magnetic ...
     534              : !> \param vel_reprs ...
     535              : !> \param com_nl ...
     536              : ! **************************************************************************************************
     537            0 :    SUBROUTINE calculate_kg_moments(qs_env, unit_nr, max_moment, magnetic, vel_reprs, com_nl)
     538              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     539              :       INTEGER, INTENT(IN)                                :: unit_nr, max_moment
     540              :       LOGICAL, INTENT(IN)                                :: magnetic, vel_reprs, com_nl
     541              : 
     542              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_kg_moments'
     543              : 
     544            0 :       CHARACTER(LEN=8), ALLOCATABLE, DIMENSION(:)        :: rlab
     545              :       CHARACTER(LEN=default_string_length)               :: mol_name
     546              :       INTEGER                                            :: akind, first_atom, handle, i, iatom, &
     547              :                                                             idir, imol, ispin, ix, iy, iz, jatom, &
     548              :                                                             l, last_atom, natom, nm, nmol, nmom, &
     549              :                                                             nspins, rmom_vel_size
     550            0 :       INTEGER, DIMENSION(:), POINTER                     :: atom_to_molecule
     551              :       LOGICAL                                            :: do_rtp, floating, found, ghost
     552              :       REAL(dp)                                           :: charge, dd, factor
     553            0 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: mmom, nlcom_rrv, nlcom_rrv_vrr, &
     554            0 :                                                             nlcom_rv, nlcom_rvr, nlcom_rxrv, &
     555            0 :                                                             qupole_der, rmom_vel
     556            0 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: rmom
     557              :       REAL(dp), DIMENSION(3)                             :: rcc, ria
     558            0 :       REAL(dp), DIMENSION(:), POINTER                    :: ref_point
     559            0 :       REAL(dp), DIMENSION(:, :), POINTER                 :: oblock, pblock, sblock
     560              :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     561              :       TYPE(cell_type), POINTER                           :: cell
     562              :       TYPE(dbcsr_iterator_type)                          :: iter
     563            0 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: magmom, matrix_s, moments, momentum, &
     564            0 :                                                             rho_ao, rho_ao_im
     565            0 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: moments_der
     566              :       TYPE(dft_control_type), POINTER                    :: dft_control
     567              :       TYPE(kg_environment_type), POINTER                 :: kg_env
     568              :       TYPE(molecule_kind_type), POINTER                  :: molecule_kind
     569            0 :       TYPE(molecule_type), POINTER                       :: molecule_set(:)
     570              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     571              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     572            0 :          POINTER                                         :: sab_orb
     573            0 :       TYPE(particle_type), POINTER                       :: particle_set(:)
     574            0 :       TYPE(qs_kind_type), POINTER                        :: qs_kind_set(:)
     575              :       TYPE(qs_rho_type), POINTER                         :: rho
     576              : 
     577            0 :       CALL timeset(routineN, handle)
     578              : 
     579            0 :       CALL cite_reference(Schreder2021)
     580            0 :       IF (max_moment > 1 .OR. magnetic .OR. vel_reprs .OR. com_nl) THEN
     581            0 :          CALL cite_reference(Schreder2024_1)
     582              :       END IF
     583              : 
     584            0 :       NULLIFY (cell, dft_control, kg_env, matrix_s, para_env, particle_set, &
     585            0 :                qs_kind_set, rho, sab_orb)
     586              :       CALL get_qs_env(qs_env, &
     587              :                       cell=cell, &
     588              :                       dft_control=dft_control, &
     589              :                       kg_env=kg_env, &
     590              :                       matrix_s=matrix_s, &
     591              :                       para_env=para_env, &
     592              :                       particle_set=particle_set, &
     593              :                       qs_kind_set=qs_kind_set, &
     594              :                       rho=rho, &
     595            0 :                       sab_orb=sab_orb)
     596              : 
     597            0 :       CPASSERT(ASSOCIATED(kg_env))
     598            0 :       molecule_set => kg_env%molecule_set
     599            0 :       atom_to_molecule => kg_env%atom_to_molecule
     600              : 
     601            0 :       nspins = dft_control%nspins
     602            0 :       do_rtp = qs_env%run_rtp
     603              : 
     604            0 :       nmom = MIN(max_moment, current_maxl)
     605            0 :       nm = (6 + 11*nmom + 6*nmom**2 + nmom**3)/6 - 1
     606            0 :       nmol = SIZE(molecule_set)
     607              : 
     608            0 :       NULLIFY (rho_ao, rho_ao_im)
     609            0 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
     610            0 :       IF (do_rtp) CALL qs_rho_get(rho, rho_ao_im=rho_ao_im)
     611              : 
     612            0 :       ALLOCATE (rmom(nm + 1, 3), rlab(nm + 1))
     613            0 :       IF (magnetic) ALLOCATE (mmom(3))
     614            0 :       IF (vel_reprs) THEN
     615            0 :          IF (com_nl .AND. (nmom >= 2)) THEN
     616              :             rmom_vel_size = 21
     617              :          ELSE
     618            0 :             rmom_vel_size = MAX(nm, 9)
     619              :          END IF
     620            0 :          ALLOCATE (rmom_vel(rmom_vel_size))
     621              :       END IF
     622              : 
     623            0 :       DO imol = 1, nmol
     624            0 :          molecule_kind => molecule_set(imol)%molecule_kind
     625            0 :          first_atom = molecule_set(imol)%first_atom
     626            0 :          last_atom = molecule_set(imol)%last_atom
     627            0 :          CALL get_molecule_kind(molecule_kind=molecule_kind, natom=natom, name=mol_name)
     628            0 :          NULLIFY (ref_point)
     629              :          CALL get_reference_point(rcc, qs_env=qs_env, reference=use_mom_ref_com, &
     630            0 :                                   ref_point=ref_point, ifirst=first_atom, ilast=last_atom)
     631              : 
     632            0 :          rmom = 0.0_dp
     633            0 :          rlab = ""
     634              : 
     635            0 :          NULLIFY (moments)
     636            0 :          CALL dbcsr_allocate_matrix_set(moments, nm)
     637            0 :          DO i = 1, nm
     638            0 :             ALLOCATE (moments(i)%matrix)
     639            0 :             IF (vel_reprs .AND. (nmom >= 2)) THEN
     640              :                CALL dbcsr_create(moments(i)%matrix, template=matrix_s(1)%matrix, &
     641            0 :                                  matrix_type=dbcsr_type_symmetric)
     642            0 :                CALL cp_dbcsr_alloc_block_from_nbl(moments(i)%matrix, sab_orb)
     643              :             ELSE
     644            0 :                CALL dbcsr_copy(moments(i)%matrix, matrix_s(1)%matrix, "Moments")
     645              :             END IF
     646            0 :             CALL dbcsr_set(moments(i)%matrix, 0.0_dp)
     647              :          END DO
     648            0 :          IF (vel_reprs .AND. (nmom >= 2)) THEN
     649            0 :             NULLIFY (moments_der)
     650            0 :             CALL dbcsr_allocate_matrix_set(moments_der, 3, 3)
     651            0 :             DO i = 1, 3
     652            0 :                DO idir = 1, 3
     653            0 :                   CALL dbcsr_init_p(moments_der(i, idir)%matrix)
     654              :                   CALL dbcsr_create(moments_der(i, idir)%matrix, template=matrix_s(1)%matrix, &
     655            0 :                                     matrix_type=dbcsr_type_antisymmetric)
     656            0 :                   CALL cp_dbcsr_alloc_block_from_nbl(moments_der(i, idir)%matrix, sab_orb)
     657            0 :                   CALL dbcsr_set(moments_der(i, idir)%matrix, 0.0_dp)
     658              :                END DO
     659              :             END DO
     660              :             CALL build_local_moments_der_matrix(qs_env, moments_der, 1, 2, ref_point=rcc, &
     661            0 :                                                 moments=moments)
     662              :          ELSE
     663            0 :             CALL build_local_moment_matrix(qs_env, moments, nmom, ref_point=rcc)
     664              :          END IF
     665              : 
     666            0 :          IF (magnetic) THEN
     667            0 :             NULLIFY (magmom)
     668            0 :             CALL dbcsr_allocate_matrix_set(magmom, 3)
     669            0 :             DO i = 1, 3
     670            0 :                CALL dbcsr_init_p(magmom(i)%matrix)
     671              :                CALL dbcsr_create(magmom(i)%matrix, template=matrix_s(1)%matrix, &
     672            0 :                                  matrix_type=dbcsr_type_antisymmetric)
     673            0 :                CALL cp_dbcsr_alloc_block_from_nbl(magmom(i)%matrix, sab_orb)
     674            0 :                CALL dbcsr_set(magmom(i)%matrix, 0.0_dp)
     675              :             END DO
     676            0 :             CALL build_local_magmom_matrix(qs_env, magmom, nmom, ref_point=rcc)
     677            0 :             mmom = 0.0_dp
     678              :          END IF
     679              : 
     680            0 :          IF (vel_reprs) THEN
     681            0 :             NULLIFY (momentum)
     682            0 :             CALL dbcsr_allocate_matrix_set(momentum, 3)
     683            0 :             DO i = 1, 3
     684            0 :                CALL dbcsr_init_p(momentum(i)%matrix)
     685              :                CALL dbcsr_create(momentum(i)%matrix, template=matrix_s(1)%matrix, &
     686            0 :                                  matrix_type=dbcsr_type_antisymmetric)
     687            0 :                CALL cp_dbcsr_alloc_block_from_nbl(momentum(i)%matrix, sab_orb)
     688            0 :                CALL dbcsr_set(momentum(i)%matrix, 0.0_dp)
     689              :             END DO
     690            0 :             CALL build_lin_mom_matrix(qs_env, momentum)
     691            0 :             rmom_vel = 0.0_dp
     692              :          END IF
     693              : 
     694            0 :          IF (vel_reprs .AND. (nmom >= 2)) THEN
     695            0 :             ALLOCATE (qupole_der(9))
     696            0 :             qupole_der = 0.0_dp
     697              :          END IF
     698              : 
     699            0 :          DO ispin = 1, nspins
     700            0 :             CALL dbcsr_iterator_readonly_start(iter, rho_ao(ispin)%matrix)
     701            0 :             DO WHILE (dbcsr_iterator_blocks_left(iter))
     702            0 :                CALL dbcsr_iterator_next_block(iter, iatom, jatom, pblock)
     703            0 :                IF (SIZE(pblock) == 0) CYCLE
     704            0 :                IF (atom_to_molecule(iatom) /= imol) CYCLE
     705            0 :                IF (atom_to_molecule(jatom) /= imol) CYCLE
     706            0 :                factor = MERGE(2.0_dp, 1.0_dp, iatom /= jatom)
     707            0 :                CALL dbcsr_get_readonly_block_p(matrix_s(1)%matrix, iatom, jatom, sblock, found)
     708            0 :                IF (found) rmom(1, 1) = rmom(1, 1) + factor*SUM(pblock*sblock)
     709            0 :                DO i = 1, nm
     710            0 :                   CALL dbcsr_get_readonly_block_p(moments(i)%matrix, iatom, jatom, oblock, found)
     711            0 :                   IF (found) rmom(i + 1, 1) = rmom(i + 1, 1) + factor*SUM(pblock*oblock)
     712              :                END DO
     713              :             END DO
     714            0 :             CALL dbcsr_iterator_stop(iter)
     715              : 
     716            0 :             IF (do_rtp .AND. (magnetic .OR. vel_reprs)) THEN
     717            0 :                CALL dbcsr_iterator_readonly_start(iter, rho_ao_im(ispin)%matrix)
     718            0 :                DO WHILE (dbcsr_iterator_blocks_left(iter))
     719            0 :                   CALL dbcsr_iterator_next_block(iter, iatom, jatom, pblock)
     720            0 :                   IF (SIZE(pblock) == 0) CYCLE
     721            0 :                   IF (atom_to_molecule(iatom) /= imol) CYCLE
     722            0 :                   IF (atom_to_molecule(jatom) /= imol) CYCLE
     723            0 :                   factor = MERGE(2.0_dp, 1.0_dp, iatom /= jatom)
     724            0 :                   IF (magnetic) THEN
     725            0 :                      DO i = 1, 3
     726            0 :                         CALL dbcsr_get_readonly_block_p(magmom(i)%matrix, iatom, jatom, oblock, found)
     727            0 :                         IF (found) mmom(i) = mmom(i) + factor*SUM(pblock*oblock)
     728              :                      END DO
     729              :                   END IF
     730            0 :                   IF (vel_reprs) THEN
     731            0 :                      DO i = 1, 3
     732            0 :                         CALL dbcsr_get_readonly_block_p(momentum(i)%matrix, iatom, jatom, oblock, found)
     733            0 :                         IF (found) rmom_vel(i) = rmom_vel(i) + factor*SUM(pblock*oblock)
     734              :                      END DO
     735            0 :                      IF (nmom >= 2) THEN
     736            0 :                         DO i = 1, 3
     737            0 :                            DO idir = 1, 3
     738              :                               CALL dbcsr_get_readonly_block_p(moments_der(i, idir)%matrix, &
     739            0 :                                                               iatom, jatom, oblock, found)
     740            0 :                               IF (found) &
     741              :                                  qupole_der((i - 1)*3 + idir) = &
     742            0 :                                  qupole_der((i - 1)*3 + idir) - factor*SUM(pblock*oblock)
     743              :                            END DO
     744              :                         END DO
     745              :                      END IF
     746              :                   END IF
     747              :                END DO
     748            0 :                CALL dbcsr_iterator_stop(iter)
     749              :             END IF
     750              :          END DO
     751              : 
     752            0 :          IF (vel_reprs .AND. (nmom >= 2)) THEN
     753            0 :             rmom_vel(4) = -2.0_dp*qupole_der(1) - rmom(1, 1)
     754            0 :             rmom_vel(5) = -qupole_der(2) - qupole_der(4)
     755            0 :             rmom_vel(6) = -qupole_der(3) - qupole_der(7)
     756            0 :             rmom_vel(7) = -2.0_dp*qupole_der(5) - rmom(1, 1)
     757            0 :             rmom_vel(8) = -qupole_der(6) - qupole_der(8)
     758            0 :             rmom_vel(9) = -2.0_dp*qupole_der(9) - rmom(1, 1)
     759            0 :             DEALLOCATE (qupole_der)
     760              :          END IF
     761              : 
     762            0 :          CALL para_env%sum(rmom(:, 1))
     763            0 :          IF (magnetic) CALL para_env%sum(mmom)
     764            0 :          IF (vel_reprs) CALL para_env%sum(rmom_vel)
     765              : 
     766            0 :          DO iatom = first_atom, first_atom + natom - 1
     767            0 :             ria = pbc(particle_set(iatom)%r - rcc, cell) + rcc
     768            0 :             ria = ria - rcc
     769            0 :             atomic_kind => particle_set(iatom)%atomic_kind
     770            0 :             CALL get_atomic_kind(atomic_kind, kind_number=akind)
     771              :             CALL get_qs_kind(qs_kind_set(akind), ghost=ghost, floating=floating, &
     772            0 :                              core_charge=charge)
     773            0 :             IF (ghost .OR. floating) CYCLE
     774            0 :             rmom(1, 2) = rmom(1, 2) - charge
     775            0 :             DO l = 1, nm
     776            0 :                ix = indco(1, l + 1)
     777            0 :                iy = indco(2, l + 1)
     778            0 :                iz = indco(3, l + 1)
     779            0 :                dd = 1.0_dp
     780            0 :                IF (ix > 0) dd = dd*ria(1)**ix
     781            0 :                IF (iy > 0) dd = dd*ria(2)**iy
     782            0 :                IF (iz > 0) dd = dd*ria(3)**iz
     783            0 :                rmom(l + 1, 2) = rmom(l + 1, 2) - charge*dd
     784            0 :                CALL set_label(rlab(l + 1), ix, iy, iz)
     785              :             END DO
     786              :          END DO
     787            0 :          rmom(:, :) = -rmom(:, :)
     788            0 :          rmom(:, 3) = rmom(:, 1) + rmom(:, 2)
     789              : 
     790            0 :          IF (com_nl) THEN
     791            0 :             IF ((nmom >= 1) .AND. vel_reprs) THEN
     792            0 :                ALLOCATE (nlcom_rv(3))
     793            0 :                nlcom_rv(:) = 0.0_dp
     794              :             END IF
     795            0 :             IF ((nmom >= 2) .AND. vel_reprs) THEN
     796            0 :                ALLOCATE (nlcom_rrv(6), nlcom_rvr(6), nlcom_rrv_vrr(6))
     797            0 :                nlcom_rrv(:) = 0.0_dp
     798            0 :                nlcom_rvr(:) = 0.0_dp
     799            0 :                nlcom_rrv_vrr(:) = 0.0_dp
     800              :             END IF
     801            0 :             IF (magnetic) THEN
     802            0 :                ALLOCATE (nlcom_rxrv(3))
     803            0 :                nlcom_rxrv(:) = 0.0_dp
     804              :             END IF
     805              :             CALL calculate_commutator_nl_terms(qs_env, nlcom_rv, nlcom_rxrv, nlcom_rrv, &
     806            0 :                                                nlcom_rvr, nlcom_rrv_vrr, rcc)
     807              :          END IF
     808              : 
     809            0 :          IF (unit_nr > 0) THEN
     810              :             WRITE (UNIT=unit_nr, FMT='(/,T3,A,I6,2X,A)') &
     811            0 :                "# Molecule:", imol, TRIM(mol_name)
     812            0 :             IF (magnetic .AND. vel_reprs) THEN
     813              :                CALL print_moments(unit_nr, nmom, rmom, rlab, rcc, cell, periodic=.FALSE., &
     814            0 :                                   mmom=mmom, rmom_vel=rmom_vel)
     815            0 :             ELSE IF (magnetic) THEN
     816              :                CALL print_moments(unit_nr, nmom, rmom, rlab, rcc, cell, periodic=.FALSE., &
     817            0 :                                   mmom=mmom)
     818            0 :             ELSE IF (vel_reprs) THEN
     819              :                CALL print_moments(unit_nr, nmom, rmom, rlab, rcc, cell, periodic=.FALSE., &
     820            0 :                                   rmom_vel=rmom_vel)
     821              :             ELSE
     822            0 :                CALL print_moments(unit_nr, nmom, rmom, rlab, rcc, cell, periodic=.FALSE.)
     823              :             END IF
     824              : 
     825            0 :             IF (com_nl) THEN
     826            0 :                IF (magnetic) mmom(:) = nlcom_rxrv(:)
     827            0 :                IF (vel_reprs .AND. (nmom >= 1)) rmom_vel(1:3) = nlcom_rv
     828            0 :                IF (vel_reprs .AND. (nmom >= 2)) THEN
     829            0 :                   rmom_vel(4:9) = nlcom_rrv
     830            0 :                   rmom_vel(10:15) = nlcom_rvr
     831            0 :                   rmom_vel(16:21) = nlcom_rrv_vrr
     832              :                END IF
     833            0 :                IF (magnetic .AND. vel_reprs) THEN
     834            0 :                   CALL print_moments_nl(unit_nr, nmom, rlab, mmom=mmom, rmom_vel=rmom_vel)
     835            0 :                ELSE IF (magnetic) THEN
     836            0 :                   CALL print_moments_nl(unit_nr, nmom, rlab, mmom=mmom)
     837            0 :                ELSE IF (vel_reprs) THEN
     838            0 :                   CALL print_moments_nl(unit_nr, nmom, rlab, rmom_vel=rmom_vel)
     839              :                END IF
     840              :             END IF
     841              :          END IF
     842              : 
     843            0 :          IF (com_nl) THEN
     844            0 :             IF ((nmom >= 1) .AND. vel_reprs) DEALLOCATE (nlcom_rv)
     845            0 :             IF ((nmom >= 2) .AND. vel_reprs) DEALLOCATE (nlcom_rrv, nlcom_rvr, nlcom_rrv_vrr)
     846            0 :             IF (magnetic) DEALLOCATE (nlcom_rxrv)
     847              :          END IF
     848            0 :          CALL dbcsr_deallocate_matrix_set(moments)
     849            0 :          IF (vel_reprs .AND. (nmom >= 2)) CALL dbcsr_deallocate_matrix_set(moments_der)
     850            0 :          IF (magnetic) CALL dbcsr_deallocate_matrix_set(magmom)
     851            0 :          IF (vel_reprs) CALL dbcsr_deallocate_matrix_set(momentum)
     852              :       END DO
     853              : 
     854            0 :       DEALLOCATE (rmom, rlab)
     855            0 :       IF (magnetic) DEALLOCATE (mmom)
     856            0 :       IF (vel_reprs) DEALLOCATE (rmom_vel)
     857              : 
     858            0 :       CALL timestop(handle)
     859              : 
     860            0 :    END SUBROUTINE calculate_kg_moments
     861              : 
     862              : END MODULE localized_moments
        

Generated by: LCOV version 2.0-1