23#include "./base/base_uses.f90"
29 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'mulliken'
37 MODULE PROCEDURE mulliken_charges_a, mulliken_charges_b, mulliken_charges_c, &
39 mulliken_charges_akp, mulliken_charges_bkp, mulliken_charges_ckp
43 MODULE PROCEDURE ao_charges_1, ao_charges_2, ao_charges_kp, ao_charges_kp_2
72 s_matrix, p_matrix, energy, order_p, ks_matrix, w_matrix)
77 REAL(kind=
dp),
OPTIONAL :: energy, order_p
79 POINTER :: ks_matrix, w_matrix
81 INTEGER :: iblock_col, iblock_row, ispin, nblock, &
84 REAL(kind=
dp) :: mult, my_energy, my_order_p
85 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: charges, charges_deriv, ks_block, &
86 p_block, s_block, w_block
91 nspin =
SIZE(p_matrix)
94 ALLOCATE (charges(nblock, nspin))
95 ALLOCATE (charges_deriv(nblock, nspin))
101 CALL restraint_functional(mulliken_restraint_control, &
102 charges, charges_deriv, my_energy, my_order_p)
104 IF (
PRESENT(order_p))
THEN
107 IF (
PRESENT(energy))
THEN
111 IF (
PRESENT(ks_matrix))
THEN
118 row=iblock_row, col=iblock_col, block=ks_block, found=found)
120 IF (.NOT. (
ASSOCIATED(s_block) .AND.
ASSOCIATED(ks_block)))
THEN
121 cpabort(
"Unexpected s / ks structure")
123 mult = 0.5_dp*charges_deriv(iblock_row, ispin) + &
124 0.5_dp*charges_deriv(iblock_col, ispin)
126 ks_block = ks_block + mult*s_block
134 IF (
PRESENT(w_matrix))
THEN
141 row=iblock_row, col=iblock_col, block=w_block, found=found)
144 IF (.NOT. (
ASSOCIATED(w_block) .AND.
ASSOCIATED(p_block))) cycle
147 mult = -0.5_dp*charges_deriv(iblock_row, ispin) &
148 - 0.5_dp*charges_deriv(iblock_col, ispin)
150 w_block = w_block + mult*p_block
159 DEALLOCATE (charges_deriv)
178 SUBROUTINE restraint_functional(mulliken_restraint_control, charges, &
179 charges_deriv, energy, order_p)
181 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: charges, charges_deriv
182 REAL(kind=
dp),
INTENT(OUT) :: energy, order_p
187 charges_deriv = 0.0_dp
190 DO i = 1, mulliken_restraint_control%natoms
191 order_p = order_p + charges(mulliken_restraint_control%atoms(i), 1) &
192 - charges(mulliken_restraint_control%atoms(i), 2)
195 energy = mulliken_restraint_control%strength*(order_p - mulliken_restraint_control%target)**2
197 dum = 2*mulliken_restraint_control%strength*(order_p - mulliken_restraint_control%target)
198 DO i = 1, mulliken_restraint_control%natoms
199 charges_deriv(mulliken_restraint_control%atoms(i), 1) = dum
200 charges_deriv(mulliken_restraint_control%atoms(i), 2) = -dum
202 END SUBROUTINE restraint_functional
218 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: charges
221 INTEGER :: iblock_col, iblock_row, ispin, nspin
223 REAL(kind=
dp) :: mult
224 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: p_block, s_block
227 nspin =
SIZE(p_matrix)
233 NULLIFY (s_block, p_block)
236 row=iblock_row, col=iblock_col, block=p_block, found=found)
239 IF (.NOT. found) cycle
240 IF (.NOT. (
ASSOCIATED(s_block) .AND.
ASSOCIATED(p_block))) cycle
242 IF (iblock_row .EQ. iblock_col)
THEN
247 charges(iblock_row, ispin) = charges(iblock_row, ispin) + &
248 mult*sum(p_block*s_block)
249 charges(iblock_col, ispin) = charges(iblock_col, ispin) + &
250 mult*sum(p_block*s_block)
255 CALL para_env%sum(charges)
268 SUBROUTINE compute_charges_single(p_matrix, s_matrix, charges, para_env)
270 REAL(kind=
dp),
DIMENSION(:) :: charges
273 INTEGER :: iblock_col, iblock_row
275 REAL(kind=
dp) :: mult
276 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: p_block, s_block
282 NULLIFY (s_block, p_block)
285 row=iblock_row, col=iblock_col, block=p_block, found=found)
288 IF (.NOT. found) cycle
289 IF (.NOT. (
ASSOCIATED(s_block) .AND.
ASSOCIATED(p_block))) cycle
291 IF (iblock_row .EQ. iblock_col)
THEN
296 charges(iblock_row) = charges(iblock_row) + mult*sum(p_block*s_block)
297 charges(iblock_col) = charges(iblock_col) + mult*sum(p_block*s_block)
301 CALL para_env%sum(charges)
303 END SUBROUTINE compute_charges_single
315 SUBROUTINE compute_dcharges(p_matrix, s_matrix, charges, dcharges, para_env)
316 TYPE(
dbcsr_p_type),
DIMENSION(:),
POINTER :: p_matrix, s_matrix
317 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: charges, dcharges
320 INTEGER :: iblock_col, iblock_row, ider, ispin, &
323 REAL(kind=
dp) :: mult
324 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ds_block, p_block, s_block
327 nspin =
SIZE(p_matrix)
334 NULLIFY (s_block, p_block)
337 row=iblock_row, col=iblock_col, block=p_block, found=found)
340 IF (.NOT. found) cycle
341 IF (.NOT. (
ASSOCIATED(s_block) .AND.
ASSOCIATED(p_block))) cycle
343 IF (iblock_row .EQ. iblock_col)
THEN
348 charges(iblock_row, ispin) = charges(iblock_row, ispin) + mult*sum(p_block*s_block)
349 charges(iblock_col, ispin) = charges(iblock_col, ispin) + mult*sum(p_block*s_block)
352 row=iblock_row, col=iblock_col, block=ds_block, found=found)
353 dcharges(iblock_row, ider) = dcharges(iblock_row, ider) + mult*sum(p_block*ds_block)
354 dcharges(iblock_col, ider) = dcharges(iblock_col, ider) + mult*sum(p_block*ds_block)
360 CALL para_env%sum(charges)
361 CALL para_env%sum(dcharges)
363 END SUBROUTINE compute_dcharges
377 SUBROUTINE mulliken_charges_a(p_matrix, s_matrix, para_env, particle_set, &
378 qs_kind_set, scr, title)
384 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
386 CHARACTER(LEN=*) :: title
388 CHARACTER(len=*),
PARAMETER :: routineN =
'mulliken_charges_a'
390 INTEGER :: handle, nblock, nspin
391 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: charges
393 CALL timeset(routinen, handle)
395 cpassert(
ASSOCIATED(p_matrix))
396 cpassert(
ASSOCIATED(s_matrix))
398 nspin =
SIZE(p_matrix)
400 ALLOCATE (charges(nblock, nspin))
408 CALL timestop(handle)
410 END SUBROUTINE mulliken_charges_a
419 SUBROUTINE mulliken_charges_b(p_matrix, s_matrix, para_env, mcharge)
424 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: mcharge
426 CHARACTER(len=*),
PARAMETER :: routineN =
'mulliken_charges_b'
430 CALL timeset(routinen, handle)
432 IF (
ASSOCIATED(p_matrix) .AND.
ASSOCIATED(s_matrix))
THEN
436 CALL timestop(handle)
438 END SUBROUTINE mulliken_charges_b
448 SUBROUTINE mulliken_charges_c(p_matrix, s_matrix, para_env, mcharge, dmcharge)
450 TYPE(
dbcsr_p_type),
DIMENSION(:),
POINTER :: p_matrix, s_matrix
452 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: mcharge, dmcharge
454 CHARACTER(len=*),
PARAMETER :: routineN =
'mulliken_charges_c'
458 CALL timeset(routinen, handle)
460 IF (
ASSOCIATED(p_matrix) .AND.
ASSOCIATED(s_matrix))
THEN
461 CALL compute_dcharges(p_matrix, s_matrix, mcharge, dmcharge, para_env)
464 CALL timestop(handle)
466 END SUBROUTINE mulliken_charges_c
475 SUBROUTINE mulliken_charges_s(p_matrix, s_matrix, para_env, mcharge)
479 REAL(KIND=
dp),
DIMENSION(:) :: mcharge
481 CHARACTER(len=*),
PARAMETER :: routineN =
'mulliken_charges_s'
485 CALL timeset(routinen, handle)
487 CALL compute_charges_single(p_matrix, s_matrix, mcharge, para_env)
489 CALL timestop(handle)
491 END SUBROUTINE mulliken_charges_s
505 SUBROUTINE mulliken_charges_akp(p_matrix_kp, s_matrix_kp, para_env, particle_set, &
506 qs_kind_set, scr, title)
508 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: p_matrix_kp, s_matrix_kp
511 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
513 CHARACTER(LEN=*) :: title
515 CHARACTER(len=*),
PARAMETER :: routineN =
'mulliken_charges_akp'
517 INTEGER :: handle, ic, nblock, nspin
518 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: charges, charges_im
522 CALL timeset(routinen, handle)
524 cpassert(
ASSOCIATED(p_matrix_kp))
525 cpassert(
ASSOCIATED(s_matrix_kp))
527 nspin =
SIZE(p_matrix_kp, 1)
528 CALL dbcsr_get_info(s_matrix_kp(1, 1)%matrix, nblkrows_total=nblock)
529 ALLOCATE (charges(nblock, nspin), charges_im(nblock, nspin))
532 DO ic = 1,
SIZE(s_matrix_kp, 2)
533 NULLIFY (p_matrix, s_matrix)
534 p_matrix => p_matrix_kp(:, ic)
535 s_matrix => s_matrix_kp(1, ic)%matrix
538 charges(:, :) = charges(:, :) + charges_im(:, :)
543 DEALLOCATE (charges, charges_im)
545 CALL timestop(handle)
547 END SUBROUTINE mulliken_charges_akp
556 SUBROUTINE mulliken_charges_bkp(p_matrix_kp, s_matrix_kp, para_env, mcharge)
558 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: p_matrix_kp, s_matrix_kp
560 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: mcharge
562 CHARACTER(len=*),
PARAMETER :: routineN =
'mulliken_charges_bkp'
564 INTEGER :: handle, ic, natom, nspin
565 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: mcharge_im
569 CALL timeset(routinen, handle)
571 IF (
ASSOCIATED(p_matrix_kp) .AND.
ASSOCIATED(s_matrix_kp))
THEN
574 natom =
SIZE(mcharge, 1)
575 nspin =
SIZE(mcharge, 2)
576 ALLOCATE (mcharge_im(natom, nspin))
578 DO ic = 1,
SIZE(s_matrix_kp, 2)
579 NULLIFY (p_matrix, s_matrix)
580 p_matrix => p_matrix_kp(:, ic)
581 s_matrix => s_matrix_kp(1, ic)%matrix
582 IF (
ASSOCIATED(p_matrix) .AND.
ASSOCIATED(s_matrix))
THEN
584 mcharge(:, :) = mcharge(:, :) + mcharge_im(:, :)
588 DEALLOCATE (mcharge_im)
592 CALL timestop(handle)
594 END SUBROUTINE mulliken_charges_bkp
604 SUBROUTINE mulliken_charges_ckp(p_matrix_kp, s_matrix_kp, para_env, &
607 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: p_matrix_kp, s_matrix_kp
609 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: mcharge, dmcharge
611 CHARACTER(len=*),
PARAMETER :: routineN =
'mulliken_charges_ckp'
613 INTEGER :: handle, ic, natom, nder, nspin
614 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: dmcharge_im, mcharge_im
615 TYPE(
dbcsr_p_type),
DIMENSION(:),
POINTER :: p_matrix, s_matrix
617 CALL timeset(routinen, handle)
619 IF (
ASSOCIATED(p_matrix_kp) .AND.
ASSOCIATED(s_matrix_kp))
THEN
623 natom =
SIZE(mcharge, 1)
624 nspin =
SIZE(mcharge, 2)
625 nder =
SIZE(dmcharge, 2)
626 ALLOCATE (mcharge_im(natom, nspin), dmcharge_im(natom, nder))
628 DO ic = 1,
SIZE(s_matrix_kp, 2)
629 NULLIFY (p_matrix, s_matrix)
630 p_matrix => p_matrix_kp(:, ic)
631 s_matrix => s_matrix_kp(:, ic)
632 IF (
ASSOCIATED(p_matrix) .AND.
ASSOCIATED(s_matrix))
THEN
633 CALL compute_dcharges(p_matrix, s_matrix, mcharge_im, dmcharge_im, para_env)
634 mcharge(:, :) = mcharge(:, :) + mcharge_im(:, :)
635 dmcharge(:, :) = dmcharge(:, :) + dmcharge_im(:, :)
639 DEALLOCATE (mcharge_im, dmcharge_im)
643 CALL timestop(handle)
645 END SUBROUTINE mulliken_charges_ckp
658 REAL(kind=
dp),
DIMENSION(:, :) :: bond_order
662 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: ps,
sp
670 row=iat, col=jat, block=
sp, found=found)
671 IF (.NOT. found) cycle
672 IF (.NOT. (
ASSOCIATED(
sp) .AND.
ASSOCIATED(ps))) cycle
674 bond_order(iat, jat) = bond_order(iat, jat) + sum(ps*
sp)
692 SUBROUTINE ao_charges_1(p_matrix, s_matrix, charges, iatom, para_env)
695 REAL(KIND=
dp),
DIMENSION(:),
INTENT(INOUT) :: charges
696 INTEGER,
INTENT(IN) :: iatom
699 CHARACTER(len=*),
PARAMETER :: routineN =
'ao_charges_1'
701 INTEGER :: handle, i, iblock_col, iblock_row, &
704 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: p_block, s_block
707 CALL timeset(routinen, handle)
709 nspin =
SIZE(p_matrix)
714 NULLIFY (s_block, p_block)
717 row=iblock_row, col=iblock_col, block=p_block, found=found)
720 IF (.NOT. found) cycle
721 IF (.NOT. (
ASSOCIATED(s_block) .AND.
ASSOCIATED(p_block))) cycle
723 IF (iblock_row == iatom)
THEN
724 DO j = 1,
SIZE(p_block, 2)
725 DO i = 1,
SIZE(p_block, 1)
726 charges(i) = charges(i) + p_block(i, j)*s_block(i, j)
729 ELSEIF (iblock_col == iatom)
THEN
730 DO j = 1,
SIZE(p_block, 2)
731 DO i = 1,
SIZE(p_block, 1)
732 charges(j) = charges(j) + p_block(i, j)*s_block(i, j)
739 CALL para_env%sum(charges)
741 CALL timestop(handle)
743 END SUBROUTINE ao_charges_1
756 SUBROUTINE ao_charges_2(p_matrix, s_matrix, charges, para_env)
759 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: charges
762 CHARACTER(len=*),
PARAMETER :: routinen =
'ao_charges_2'
764 INTEGER :: handle, i, iblock_col, iblock_row, &
767 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: p_block, s_block
770 CALL timeset(routinen, handle)
772 nspin =
SIZE(p_matrix)
777 NULLIFY (s_block, p_block)
780 row=iblock_row, col=iblock_col, block=p_block, found=found)
783 IF (.NOT. found) cycle
784 IF (.NOT. (
ASSOCIATED(s_block) .AND.
ASSOCIATED(p_block))) cycle
786 DO j = 1,
SIZE(p_block, 2)
787 DO i = 1,
SIZE(p_block, 1)
788 charges(i, iblock_row) = charges(i, iblock_row) + p_block(i, j)*s_block(i, j)
791 IF (iblock_col /= iblock_row)
THEN
792 DO j = 1,
SIZE(p_block, 2)
793 DO i = 1,
SIZE(p_block, 1)
794 charges(j, iblock_col) = charges(j, iblock_col) + p_block(i, j)*s_block(i, j)
802 CALL para_env%sum(charges)
804 CALL timestop(handle)
806 END SUBROUTINE ao_charges_2
816 SUBROUTINE ao_charges_kp(p_matrix_kp, s_matrix_kp, charges, iatom, para_env)
818 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: p_matrix_kp, s_matrix_kp
819 REAL(KIND=
dp),
DIMENSION(:),
INTENT(INOUT) :: charges
820 INTEGER,
INTENT(IN) :: iatom
823 CHARACTER(len=*),
PARAMETER :: routineN =
'ao_charges_kp'
825 INTEGER :: handle, ic, na
826 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) :: charge_im
830 CALL timeset(routinen, handle)
832 IF (
ASSOCIATED(p_matrix_kp) .AND.
ASSOCIATED(s_matrix_kp))
THEN
835 na =
SIZE(charges, 1)
836 ALLOCATE (charge_im(na))
838 DO ic = 1,
SIZE(s_matrix_kp, 2)
839 NULLIFY (p_matrix, s_matrix)
840 p_matrix => p_matrix_kp(:, ic)
841 s_matrix => s_matrix_kp(1, ic)%matrix
842 IF (
ASSOCIATED(p_matrix) .AND.
ASSOCIATED(s_matrix))
THEN
843 CALL ao_charges_1(p_matrix, s_matrix, charge_im, iatom, para_env)
844 charges(:) = charges(:) + charge_im(:)
848 DEALLOCATE (charge_im)
852 CALL timestop(handle)
854 END SUBROUTINE ao_charges_kp
863 SUBROUTINE ao_charges_kp_2(p_matrix_kp, s_matrix_kp, charges, para_env)
865 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: p_matrix_kp, s_matrix_kp
866 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: charges
869 CHARACTER(len=*),
PARAMETER :: routinen =
'ao_charges_kp_2'
871 INTEGER :: handle, ic, na, nb
872 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: charge_im
876 CALL timeset(routinen, handle)
878 IF (
ASSOCIATED(p_matrix_kp) .AND.
ASSOCIATED(s_matrix_kp))
THEN
881 na =
SIZE(charges, 1)
882 nb =
SIZE(charges, 2)
883 ALLOCATE (charge_im(na, nb))
885 DO ic = 1,
SIZE(s_matrix_kp, 2)
886 NULLIFY (p_matrix, s_matrix)
887 p_matrix => p_matrix_kp(:, ic)
888 s_matrix => s_matrix_kp(1, ic)%matrix
889 IF (
ASSOCIATED(p_matrix) .AND.
ASSOCIATED(s_matrix))
THEN
890 CALL ao_charges_2(p_matrix, s_matrix, charge_im, para_env)
891 charges(:, :) = charges(:, :) + charge_im(:, :)
895 DEALLOCATE (charge_im)
899 CALL timestop(handle)
901 END SUBROUTINE ao_charges_kp_2
916 REAL(kind=
dp),
INTENT(IN) :: factor
917 REAL(kind=
dp),
DIMENSION(:),
POINTER :: atrace
919 INTEGER :: iblock_col, iblock_row, nblock
921 REAL(kind=
dp) :: btr, mult
922 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: a_block, b_block
926 cpassert(nblock ==
SIZE(atrace))
932 row=iblock_row, col=iblock_col, block=a_block, found=found)
935 IF (.NOT. (
ASSOCIATED(b_block) .AND.
ASSOCIATED(a_block))) cycle
937 IF (iblock_row .EQ. iblock_col)
THEN
942 btr = factor*mult*sum(a_block*b_block)
943 atrace(iblock_row) = atrace(iblock_row) + btr
944 atrace(iblock_col) = atrace(iblock_col) + btr
simple routine to print charges for all atomic charge methods (currently mulliken,...
subroutine, public print_atomic_charges(particle_set, qs_kind_set, scr, title, electronic_charges, atomic_charges)
generates a unified output format for atomic charges
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset)
...
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
subroutine, public dbcsr_get_block_p(matrix, row, col, block, found, row_size, col_size)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public sp
Interface to the message passing library MPI.
compute mulliken charges we (currently) define them as c_i = 1/2 [ (PS)_{ii} + (SP)_{ii} ]
subroutine, public mulliken_restraint(mulliken_restraint_control, para_env, s_matrix, p_matrix, energy, order_p, ks_matrix, w_matrix)
computes the energy and density matrix derivate of a constraint on the mulliken charges
subroutine, public compute_bond_order(psmat, spmat, bond_order)
compute Mayer bond orders for a single spin channel for complete result sum up over all spins and mul...
subroutine, public compute_charges(p_matrix, s_matrix, charges, para_env)
compute the mulliken charges
subroutine, public atom_trace(amat, bmat, factor, atrace)
Compute partial trace of product of two matrices.
Define the data structure for the particle information.
Define the quickstep kind type and their sub types.
stores all the informations relevant to an mpi environment
Provides all information about a quickstep kind.