24 use,
intrinsic :: iso_fortran_env
50 real(real64) :: point(1:3)
52 real(real64) :: normal(1:3)
53 real(real64) :: r_sphere
56 type(pcm_tessera_t),
allocatable :: cts_act(:)
75 integer,
parameter :: &
76 PCM_DEBYE_MODEL = 1, &
79 integer,
parameter :: &
87 type(debye_param_t) :: deb
88 type(drude_param_t) :: drl
99 real(real64),
allocatable :: q_tp(:), dq_tp(:)
100 real(real64),
allocatable :: qext_tp(:), dqext_tp(:)
101 real(real64),
allocatable :: qkick_tp(:), dqkick_tp(:)
103 real(real64),
allocatable :: pot_tp(:)
104 real(real64),
allocatable :: potext_tp(:)
107 real(real64) :: f1, f2, f3, f4, f5
109 real(real64),
allocatable :: force_tp(:)
110 real(real64),
allocatable :: force_qext_tp(:)
111 real(real64),
allocatable :: force_qkick_tp(:)
115 real(real64),
allocatable :: cals(:,:), cald(:,:)
116 real(real64),
allocatable :: eigv(:), eigt(:,:)
117 real(real64),
allocatable :: sm12(:,:), sp12(:,:)
119 real(real64),
allocatable :: matq0(:,:), matqd(:,:)
120 real(real64),
allocatable :: matq0_lf(:,:), matqd_lf(:,:)
123 real(real64),
allocatable :: matqv(:,:), matqq(:,:)
124 real(real64),
allocatable :: matqv_lf(:,:)
131 logical :: enough_initial = .false.
139 this_eps, namespace, this_deb, this_drl)
141 real(real64),
intent(out) :: q_t(:)
142 real(real64),
intent(in) :: pot_t(:)
143 real(real64),
intent(in) :: this_dt
145 logical,
intent(in) :: input_asc
146 integer,
intent(in) :: this_eom
148 integer,
intent(in) :: this_eps
155 logical :: initial_electron = .
true.
156 logical :: initial_external = .
true.
157 logical :: initial_kick = .
true.
164 message(1) =
"pcm_charges_propagation: EOM evolution of PCM charges can only be due to solute electrons"
165 message(2) =
"or external potential (including the kick)."
171 nts_act =
size(this_cts_act)
172 if (
size(q_t) /= nts_act)
then
173 message(1) =
"pcm_charges_propagation: Number of tesserae do not coincide with size of PCM charges array."
177 safe_allocate(cts_act(1:nts_act))
178 cts_act = this_cts_act
181 select case (which_eps)
182 case (pcm_debye_model)
183 if (
present(this_deb))
then
186 message(1) =
"pcm_charges_propagation: EOM-PCM error. Debye dielectric function requires three parameters."
190 if (
present(this_drl))
then
193 message(1) =
"pcm_charges_propagation: EOM-PCM error. Drude-Lorentz dielectric function requires three parameters."
197 message(1) =
"pcm_charges_propagation: EOM-PCM error. Only Debye or Drude-Lorent dielectric models are allowed."
202 message(1) =
"pcm_charges_propagation: EOM-PCM error. Debye EOM-PCM require a non-null Debye relaxation time."
210 select case (which_eps)
211 case (pcm_debye_model)
218 message(1) =
"pcm_charges_propagation: EOM-PCM error. Only Debye EOM-PCM can startup from input charges."
223 if ((initial_electron .and. which_eom == pcm_electrons) .or. &
225 (initial_kick .and. which_eom ==
pcm_kick))
then
233 if (initial_electron .and. which_eom == pcm_electrons) initial_electron = .false.
236 if (initial_kick .and. which_eom ==
pcm_kick) initial_kick = .false.
241 if (which_eps == pcm_debye_model)
then
255 real(real64),
intent(out) :: q_t(:)
256 real(real64),
intent(in) :: pot_t(:)
259 real(real64) :: aux1(3)
266 if (which_eom == pcm_electrons)
then
267 safe_allocate(q_tp(1:nts_act))
268 asc_unit =
io_open(
pcm_dir//
'ASC_e.dat', namespace, action=
'read')
270 read(asc_unit,*) aux1, q_t(ia), aux2
275 safe_allocate(qext_tp(1:nts_act))
276 asc_unit =
io_open(
pcm_dir//
'ASC_ext.dat', namespace, action=
'read')
278 read(asc_unit,*) aux1, q_t(ia), aux2
282 else if (which_eom ==
pcm_kick)
then
283 safe_allocate(qkick_tp(1:nts_act))
284 asc_unit =
io_open(
pcm_dir//
'ASC_kick.dat', namespace, action=
'read')
286 read(asc_unit,*) aux1, q_t(ia), aux2
292 safe_allocate(pot_tp(1:nts_act))
301 real(real64),
intent(out) :: q_t(:)
302 real(real64),
intent(in) :: pot_t(:)
307 if (which_eom == pcm_electrons)
then
311 message(1) =
'EOM-PCM for solvent polarization due to solute electrons considers that you start from a ground state run.'
314 safe_allocate(pot_tp(1:nts_act))
318 q_t = matmul(matq0, pot_t)
320 safe_allocate(q_tp(1:nts_act))
324 safe_allocate(dq_tp(1:nts_act))
325 safe_allocate(force_tp(1:nts_act))
334 safe_allocate(potext_tp(1:nts_act))
338 q_t = matmul(matqd_lf, pot_t)
340 safe_allocate(qext_tp(1:nts_act))
344 safe_allocate(dqext_tp(1:nts_act))
345 safe_allocate(force_qext_tp(1:nts_act))
350 else if (which_eom ==
pcm_kick)
then
353 safe_allocate(dqkick_tp(1:nts_act))
354 safe_allocate(force_qkick_tp(1:nts_act))
360 dqkick_tp = matmul(matqv_lf, pot_t)*dt
362 q_t = matmul(matqv_lf - matmul(matqq, matqd_lf), pot_t)
365 safe_allocate(qkick_tp(1:nts_act))
380 real(real64),
intent(out) :: q_t(:)
381 real(real64),
intent(in) :: pot_t(:)
385 if (which_eom == pcm_electrons)
then
387 q_t(:) = q_tp(:) - dt*matmul(matqq, q_tp) + &
388 dt*matmul(matqv, pot_tp) + &
389 matmul(matqd, pot_t - pot_tp)
397 q_t(:) = qext_tp(:) - dt*matmul(matqq, qext_tp) + &
398 dt*matmul(matqv_lf, potext_tp) + &
399 matmul(matqd_lf, pot_t - potext_tp)
405 else if (which_eom ==
pcm_kick)
then
407 q_t(:) = qkick_tp(:) - dt*matmul(matqq, qkick_tp)
438 real(real64),
intent(out) :: q_t(:)
439 real(real64),
intent(in) :: pot_t(:)
441 real(real64) :: force(nts_act)
445 if (which_eom == pcm_electrons)
then
448 q_t = q_tp + f1*dq_tp + f2*force_tp
449 force = -matmul(matqq, q_t) + matmul(matqv, pot_t)
450 dq_tp = f3*dq_tp + f4*(force+force_tp) -f5*force_tp
456 q_t = qext_tp + f1*dqext_tp + f2*force_qext_tp
457 force = -matmul(matqq, q_t) + matmul(matqv_lf, pot_t)
458 dqext_tp = f3*dqext_tp + f4*(force + force_qext_tp) -f5*force_qext_tp
459 force_qext_tp = force
462 else if (which_eom ==
pcm_kick)
then
464 q_t = qkick_tp + f1*dqkick_tp + f2*force_qkick_tp
465 force = -matmul(matqq, q_t)
466 dqkick_tp = f3*dqkick_tp + f4*(force + force_qkick_tp) -f5*force_qkick_tp
467 force_qkick_tp = force
481 integer :: itess, jtess
482 integer :: pcmmat0_unit, pcmmatd_unit
486 if (which_eom == pcm_electrons)
then
487 safe_allocate(matq0(1:nts_act, 1:nts_act))
488 safe_allocate(matqd(1:nts_act, 1:nts_act))
489 safe_allocate(matqv(1:nts_act, 1:nts_act))
490 if (.not.
allocated(matqq))
then
491 safe_allocate(matqq(1:nts_act, 1:nts_act))
494 safe_allocate(matq0_lf(1:nts_act, 1:nts_act))
495 safe_allocate(matqd_lf(1:nts_act, 1:nts_act))
496 safe_allocate(matqv_lf(1:nts_act, 1:nts_act))
497 if (.not.
allocated(matqq))
then
498 safe_allocate(matqq(1:nts_act, 1:nts_act))
503 if (which_eom == pcm_electrons)
then
504 pcmmat0_unit =
io_open(
pcm_dir//
'pcm_matrix_static_from_eom.out', namespace, action=
'write')
505 pcmmatd_unit =
io_open(
pcm_dir//
'pcm_matrix_dynamic_from_eom.out', namespace, action=
'write')
506 do jtess = 1, nts_act
507 do itess = 1, nts_act
508 write(pcmmat0_unit,*) matq0(itess, jtess)
509 write(pcmmatd_unit,*) matqd(itess, jtess)
515 pcmmat0_unit =
io_open(
pcm_dir//
'pcm_matrix_static_lf_from_eom.out', namespace, action=
'write')
516 pcmmatd_unit =
io_open(
pcm_dir//
'pcm_matrix_dynamic_lf_from_eom.out', namespace, action=
'write')
517 do jtess = 1, nts_act
518 do itess = 1, nts_act
519 write(pcmmat0_unit,*) matq0_lf(itess, jtess)
520 write(pcmmatd_unit,*) matqd_lf(itess, jtess)
536 safe_deallocate_a(q_tp)
537 safe_deallocate_a(qext_tp)
538 safe_deallocate_a(qkick_tp)
541 safe_deallocate_a(dq_tp)
542 safe_deallocate_a(dqext_tp)
543 safe_deallocate_a(dqkick_tp)
546 safe_deallocate_a(force_tp)
547 safe_deallocate_a(force_qext_tp)
548 safe_deallocate_a(force_qkick_tp)
551 safe_deallocate_a(matq0)
552 safe_deallocate_a(matqd)
553 safe_deallocate_a(matq0_lf)
554 safe_deallocate_a(matqd_lf)
555 safe_deallocate_a(matqv)
556 safe_deallocate_a(matqv_lf)
557 safe_deallocate_a(matqq)
559 safe_deallocate_a(pot_tp)
560 safe_deallocate_a(cts_act)
578 real(real64),
allocatable :: scr4(:,:), scr1(:,:)
579 real(real64),
allocatable :: scr2(:,:), scr3(:,:)
580 real(real64),
allocatable :: fact1(:), fact2(:)
583 real(real64),
allocatable :: Kdiag0(:), Kdiagd(:)
588 real(real64) :: sgn,sgn_lf, fac_eps0, fac_epsd
591 logical :: firsttime = .
true.
602 safe_allocate(cals(1:nts_act, 1:nts_act))
603 safe_allocate(cald(1:nts_act, 1:nts_act))
604 safe_allocate(kdiag0(1:nts_act))
605 safe_allocate(kdiagd(1:nts_act))
606 safe_allocate(fact1(1:nts_act))
607 safe_allocate(fact2(1:nts_act))
623 safe_deallocate_a(cals)
624 safe_deallocate_a(cald)
626 safe_allocate(scr4(1:nts_act, 1:nts_act))
627 safe_allocate(scr1(1:nts_act, 1:nts_act))
628 safe_allocate(scr2(1:nts_act, 1:nts_act))
629 safe_allocate(scr3(1:nts_act, 1:nts_act))
631 if (which_eps == pcm_debye_model)
then
633 fac_eps0 = (deb%eps_0 +
m_one)/(deb%eps_0 -
m_one)
634 kdiag0(:) = sgn_lf*(
m_two*
m_pi - sgn*sgn_lf*eigv(:))/(
m_two*
m_pi*fac_eps0 - sgn*eigv(:))
639 fac_epsd = (deb%eps_d +
m_one)/(deb%eps_d -
m_one)
640 kdiagd(:) = sgn_lf*(
m_two*
m_pi - sgn*sgn_lf*eigv(:))/(
m_two*
m_pi*fac_epsd - sgn*eigv(:))
646 fact2(:) = kdiag0(:)*fact1(:)
654 if (abs(drl%w0) <=
m_epsilon) drl%w0 = 1.0e-8_real64
655 fact1(:) = fact2(:) + drl%w0*drl%w0
657 kdiag0(:) = fact2(:)/fact1(:)
660 scr3 = matmul(sm12, eigt)
661 scr2 = matmul(transpose(eigt), sp12)
662 scr4 = transpose(scr3)
664 scr1(:,i) = scr3(:, i)*fact1(i)
666 matqq = matmul(scr1, scr2)
668 scr1(:,i) = scr3(:, i)*fact2(i)
670 if (which_eom == pcm_electrons)
then
671 matqv = -matmul(scr1, scr4)
673 matqv_lf = -matmul(scr1, scr4)
676 scr1(:,i) = scr3(:,i)*kdiag0(i)
678 if (which_eom == pcm_electrons)
then
679 matq0 = -matmul(scr1, scr4)
681 matq0_lf = -matmul(scr1, scr4)
684 scr1(:,i) = scr3(:, i)*kdiagd(i)
686 if (which_eom == pcm_electrons)
then
687 matqd = -matmul(scr1, scr4)
689 matqd_lf = -matmul(scr1, scr4)
692 safe_deallocate_a(scr4)
693 safe_deallocate_a(scr1)
694 safe_deallocate_a(scr2)
695 safe_deallocate_a(scr3)
696 safe_deallocate_a(fact1)
697 safe_deallocate_a(fact2)
698 safe_deallocate_a(kdiag0)
699 safe_deallocate_a(kdiagd)
701 if (enough_initial)
then
713 subroutine green_d(i, j, value)
714 integer,
intent(in) :: i, j
715 real(real64),
intent(out) :: value
717 real(real64) :: dist,diff(3)
722 diff = cts_act(i)%point - cts_act(j)%point
724 value = dot_product(cts_act(j)%normal, diff)/dist**3
727 value =
value/(
m_two*cts_act(i)%r_sphere)/cts_act(i)%area
738 subroutine green_s(i, j, value)
739 integer,
intent(in):: i,j
740 real(real64),
intent(out) :: value
742 real(real64) :: dist,diff(3)
747 diff = cts_act(i)%point - cts_act(j)%point
761 safe_allocate(eigv(1:nts_act))
762 safe_allocate(eigt(1:nts_act, 1:nts_act))
763 safe_allocate(sm12(1:nts_act, 1:nts_act))
764 safe_allocate(sp12(1:nts_act, 1:nts_act))
773 safe_deallocate_a(eigv)
774 safe_deallocate_a(eigt)
775 safe_deallocate_a(sm12)
776 safe_deallocate_a(sp12)
786 integer :: info, lwork, liwork
787 real(real64),
allocatable :: scr1(:,:), scr2(:,:), eigt_t(:,:)
790 integer,
allocatable :: iwork(:)
791 real(real64),
allocatable :: work(:)
795 safe_allocate(scr1(1:nts_act, 1:nts_act))
796 safe_allocate(scr2(1:nts_act, 1:nts_act))
797 safe_allocate(eigt_t(1:nts_act, 1:nts_act))
798 safe_allocate(work(1:1 + 6*nts_act + 2*nts_act*nts_act))
799 safe_allocate(iwork(1:3 + 5*nts_act))
805 lwork = 1 + 6*nts_act + 2*nts_act*nts_act
806 liwork = 3 + 5*nts_act
808 call dsyevd(jobz, uplo, nts_act, eigt, nts_act, eigv, work, lwork, iwork, liwork, info)
810 if (eigv(i) <
m_zero)
then
811 write(
message(1),*)
"Eigenvalue ", i,
" of S when constructing the TS matrix is negative!"
812 write(
message(2),*)
"I put it to 1e-8"
814 eigv(i) = 1.0e-8_real64
816 scr1(:,i) = eigt(:,i)*
sqrt(eigv(i))
818 eigt_t = transpose(eigt)
819 sp12 = matmul(scr1, eigt_t)
821 scr1(:, i) = eigt(:, i)/
sqrt(eigv(i))
823 sm12 = matmul(scr1, eigt_t)
825 scr1(:,i) = cald(:, i)*cts_act(i)%area
827 scr2 = matmul(matmul(sm12, scr1), sp12)
830 eigt(i, j) =
m_half*(scr2(i, j) + scr2(j, i))
833 call dsyevd(jobz,uplo,nts_act,eigt,nts_act,eigv,work,lwork, &
836 safe_deallocate_a(work)
837 safe_deallocate_a(iwork)
838 safe_deallocate_a(scr1)
839 safe_deallocate_a(scr2)
840 safe_deallocate_a(eigt_t)
847 logical,
intent(out) :: not_yet_called
852 not_yet_called = .false.
double sqrt(double __x) __attribute__((__nothrow__
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
real(real64), parameter, public m_four
real(real64), parameter, public m_pi
some mathematical constants
character(len= *), parameter, public pcm_dir
real(real64), parameter, public m_epsilon
real(real64), parameter, public m_half
real(real64), parameter, public m_one
subroutine, public io_close(iunit, grp)
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
This module is intended to contain "only mathematical" functions and procedures.
subroutine, public messages_warning(no_lines, all_nodes, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
integer, parameter, public pcm_external_plus_kick
subroutine pcm_bem_init(namespace)
Boundary Element Method (BEM) EOM-IEF-PCM matrices initialization.
integer, parameter, public pcm_electrons
integer, parameter, public pcm_kick
subroutine do_ts_matrix(namespace)
Subroutine to build matrices , , and (notation of Refs.1-2)
integer, parameter, public pcm_nuclei
subroutine do_pcm_propmat(namespace)
Subroutine to build the required BEM matrices for the EOM-IEF-PCM for Debye and Drude-Lorentz cases.
subroutine init_vv_propagator
Subroutine to initialize numerical constants required by the Velocity-Verlet (VV) algorithm.
subroutine, public pcm_charges_propagation(q_t, pot_t, this_dt, this_cts_act, input_asc, this_eom, this_eps, namespace, this_deb, this_drl)
Driving subroutine for the Equation of Motion (EOM) propagation of the polarization charges within th...
subroutine pcm_ief_prop_deb(q_t, pot_t)
Euler method for integrating first order EOM for the polarization charges within IEF-PCM in the case ...
subroutine green_d(i, j, value)
Subroutine to build BEM matrix corresponding to the Calderon operator D, using the Green function of ...
integer, parameter, public pcm_external_potential
subroutine deallocate_ts_matrix()
subroutine init_charges(q_t, pot_t, namespace)
Polarization charges initialization (in equilibrium with the initial potential for electrons)
integer, parameter, public pcm_drude_model
subroutine, public pcm_eom_end()
subroutine pcm_charges_from_input_file(q_t, pot_t, namespace)
Polarization charges initialization from input file.
subroutine allocate_ts_matrix()
subroutine green_s(i, j, value)
Subroutine to build BEM matrix corresponding to the Calderon operator S, using the Green function of ...
subroutine, public pcm_eom_enough_initial(not_yet_called)
subroutine pcm_ief_prop_vv_ief_drl(q_t, pot_t)
VV algorithm for integrating second order EOM for the polarization charges within IEF-PCM in the case...
integer, parameter, public pcm_debye_model
set of parameters for Debye dielectric model
set of parameters for Drude-Lorentz dielectric model