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)
140 real(real64),
intent(out) :: q_t(:)
141 real(real64),
intent(in) :: pot_t(:)
142 real(real64),
intent(in) :: this_dt
143 type(pcm_tessera_t),
intent(in) :: this_cts_act(:)
144 logical,
intent(in) :: input_asc
145 integer,
intent(in) :: this_eom
147 integer,
intent(in) :: this_eps
153 logical,
save :: firsttime = .
true.
154 logical,
save :: initial_electron = .
true.
155 logical,
save :: initial_external = .
true.
156 logical,
save :: initial_kick = .
true.
163 message(1) =
"pcm_charges_propagation: EOM evolution of PCM charges can only be due to solute electrons"
164 message(2) =
"or external potential (including the kick)."
170 nts_act =
size(this_cts_act)
171 if (
size(q_t) /= nts_act)
then
172 message(1) =
"pcm_charges_propagation: Number of tesserae do not coincide with size of PCM charges array."
176 safe_allocate(cts_act(1:nts_act))
177 cts_act = this_cts_act
180 select case (which_eps)
181 case (pcm_debye_model)
182 if (
present(this_deb))
then
185 message(1) =
"pcm_charges_propagation: EOM-PCM error. Debye dielectric function requires three parameters."
189 if (
present(this_drl))
then
192 message(1) =
"pcm_charges_propagation: EOM-PCM error. Drude-Lorentz dielectric function requires three parameters."
196 message(1) =
"pcm_charges_propagation: EOM-PCM error. Only Debye or Drude-Lorent dielectric models are allowed."
201 message(1) =
"pcm_charges_propagation: EOM-PCM error. Debye EOM-PCM require a non-null Debye relaxation time."
209 select case (which_eps)
210 case (pcm_debye_model)
217 message(1) =
"pcm_charges_propagation: EOM-PCM error. Only Debye EOM-PCM can startup from input charges."
222 if ((initial_electron .and. which_eom == pcm_electrons) .or. &
224 (initial_kick .and. which_eom ==
pcm_kick))
then
232 if (initial_electron .and. which_eom == pcm_electrons) initial_electron = .false.
235 if (initial_kick .and. which_eom ==
pcm_kick) initial_kick = .false.
240 if (which_eps == pcm_debye_model)
then
254 real(real64),
intent(out) :: q_t(:)
255 real(real64),
intent(in) :: pot_t(:)
258 real(real64) :: aux1(3)
265 if (which_eom == pcm_electrons)
then
266 safe_allocate(q_tp(1:nts_act))
267 asc_unit =
io_open(
pcm_dir//
'ASC_e.dat', namespace, action=
'read')
269 read(asc_unit,*) aux1, q_t(ia), aux2
274 safe_allocate(qext_tp(1:nts_act))
275 asc_unit =
io_open(
pcm_dir//
'ASC_ext.dat', namespace, action=
'read')
277 read(asc_unit,*) aux1, q_t(ia), aux2
281 else if (which_eom ==
pcm_kick)
then
282 safe_allocate(qkick_tp(1:nts_act))
283 asc_unit =
io_open(
pcm_dir//
'ASC_kick.dat', namespace, action=
'read')
285 read(asc_unit,*) aux1, q_t(ia), aux2
291 safe_allocate(pot_tp(1:nts_act))
300 real(real64),
intent(out) :: q_t(:)
301 real(real64),
intent(in) :: pot_t(:)
306 if (which_eom == pcm_electrons)
then
310 message(1) =
'EOM-PCM for solvent polarization due to solute electrons considers that you start from a ground state run.'
313 safe_allocate(pot_tp(1:nts_act))
317 q_t = matmul(matq0, pot_t)
319 safe_allocate(q_tp(1:nts_act))
323 safe_allocate(dq_tp(1:nts_act))
324 safe_allocate(force_tp(1:nts_act))
333 safe_allocate(potext_tp(1:nts_act))
337 q_t = matmul(matqd_lf, pot_t)
339 safe_allocate(qext_tp(1:nts_act))
343 safe_allocate(dqext_tp(1:nts_act))
344 safe_allocate(force_qext_tp(1:nts_act))
349 else if (which_eom ==
pcm_kick)
then
352 safe_allocate(dqkick_tp(1:nts_act))
353 safe_allocate(force_qkick_tp(1:nts_act))
359 dqkick_tp = matmul(matqv_lf, pot_t)*dt
361 q_t = matmul(matqv_lf - matmul(matqq, matqd_lf), pot_t)
364 safe_allocate(qkick_tp(1:nts_act))
379 real(real64),
intent(out) :: q_t(:)
380 real(real64),
intent(in) :: pot_t(:)
384 if (which_eom == pcm_electrons)
then
386 q_t(:) = q_tp(:) - dt*matmul(matqq, q_tp) + &
387 dt*matmul(matqv, pot_tp) + &
388 matmul(matqd, pot_t - pot_tp)
396 q_t(:) = qext_tp(:) - dt*matmul(matqq, qext_tp) + &
397 dt*matmul(matqv_lf, potext_tp) + &
398 matmul(matqd_lf, pot_t - potext_tp)
404 else if (which_eom ==
pcm_kick)
then
406 q_t(:) = qkick_tp(:) - dt*matmul(matqq, qkick_tp)
437 real(real64),
intent(out) :: q_t(:)
438 real(real64),
intent(in) :: pot_t(:)
440 real(real64) :: force(nts_act)
444 if (which_eom == pcm_electrons)
then
447 q_t = q_tp + f1*dq_tp + f2*force_tp
448 force = -matmul(matqq, q_t) + matmul(matqv, pot_t)
449 dq_tp = f3*dq_tp + f4*(force+force_tp) -f5*force_tp
455 q_t = qext_tp + f1*dqext_tp + f2*force_qext_tp
456 force = -matmul(matqq, q_t) + matmul(matqv_lf, pot_t)
457 dqext_tp = f3*dqext_tp + f4*(force + force_qext_tp) -f5*force_qext_tp
458 force_qext_tp = force
461 else if (which_eom ==
pcm_kick)
then
463 q_t = qkick_tp + f1*dqkick_tp + f2*force_qkick_tp
464 force = -matmul(matqq, q_t)
465 dqkick_tp = f3*dqkick_tp + f4*(force + force_qkick_tp) -f5*force_qkick_tp
466 force_qkick_tp = force
480 integer :: itess, jtess
481 integer :: pcmmat0_unit, pcmmatd_unit
485 if (which_eom == pcm_electrons)
then
486 safe_allocate(matq0(1:nts_act, 1:nts_act))
487 safe_allocate(matqd(1:nts_act, 1:nts_act))
488 safe_allocate(matqv(1:nts_act, 1:nts_act))
489 if (.not.
allocated(matqq))
then
490 safe_allocate(matqq(1:nts_act, 1:nts_act))
493 safe_allocate(matq0_lf(1:nts_act, 1:nts_act))
494 safe_allocate(matqd_lf(1:nts_act, 1:nts_act))
495 safe_allocate(matqv_lf(1:nts_act, 1:nts_act))
496 if (.not.
allocated(matqq))
then
497 safe_allocate(matqq(1:nts_act, 1:nts_act))
502 if (which_eom == pcm_electrons)
then
503 pcmmat0_unit =
io_open(
pcm_dir//
'pcm_matrix_static_from_eom.out', namespace, action=
'write')
504 pcmmatd_unit =
io_open(
pcm_dir//
'pcm_matrix_dynamic_from_eom.out', namespace, action=
'write')
505 do jtess = 1, nts_act
506 do itess = 1, nts_act
507 write(pcmmat0_unit,*) matq0(itess, jtess)
508 write(pcmmatd_unit,*) matqd(itess, jtess)
514 pcmmat0_unit =
io_open(
pcm_dir//
'pcm_matrix_static_lf_from_eom.out', namespace, action=
'write')
515 pcmmatd_unit =
io_open(
pcm_dir//
'pcm_matrix_dynamic_lf_from_eom.out', namespace, action=
'write')
516 do jtess = 1, nts_act
517 do itess = 1, nts_act
518 write(pcmmat0_unit,*) matq0_lf(itess, jtess)
519 write(pcmmatd_unit,*) matqd_lf(itess, jtess)
535 safe_deallocate_a(q_tp)
536 safe_deallocate_a(qext_tp)
537 safe_deallocate_a(qkick_tp)
540 safe_deallocate_a(dq_tp)
541 safe_deallocate_a(dqext_tp)
542 safe_deallocate_a(dqkick_tp)
545 safe_deallocate_a(force_tp)
546 safe_deallocate_a(force_qext_tp)
547 safe_deallocate_a(force_qkick_tp)
550 safe_deallocate_a(matq0)
551 safe_deallocate_a(matqd)
552 safe_deallocate_a(matq0_lf)
553 safe_deallocate_a(matqd_lf)
554 safe_deallocate_a(matqv)
555 safe_deallocate_a(matqv_lf)
556 safe_deallocate_a(matqq)
558 safe_deallocate_a(pot_tp)
559 safe_deallocate_a(cts_act)
575 integer,
save :: i, j
576 real(real64),
allocatable,
save :: scr4(:,:), scr1(:,:)
577 real(real64),
allocatable,
save :: scr2(:,:), scr3(:,:)
578 real(real64),
allocatable,
save :: fact1(:), fact2(:)
581 real(real64),
allocatable,
save :: Kdiag0(:), Kdiagd(:)
586 real(real64),
save :: sgn,sgn_lf, fac_eps0, fac_epsd
587 real(real64),
save :: temp
589 logical,
save :: firsttime = .
true.
600 safe_allocate(cals(1:nts_act, 1:nts_act))
601 safe_allocate(cald(1:nts_act, 1:nts_act))
602 safe_allocate(kdiag0(1:nts_act))
603 safe_allocate(kdiagd(1:nts_act))
604 safe_allocate(fact1(1:nts_act))
605 safe_allocate(fact2(1:nts_act))
621 safe_deallocate_a(cals)
622 safe_deallocate_a(cald)
624 safe_allocate(scr4(1:nts_act, 1:nts_act))
625 safe_allocate(scr1(1:nts_act, 1:nts_act))
626 safe_allocate(scr2(1:nts_act, 1:nts_act))
627 safe_allocate(scr3(1:nts_act, 1:nts_act))
629 if (which_eps == pcm_debye_model)
then
631 fac_eps0 = (deb%eps_0 +
m_one)/(deb%eps_0 -
m_one)
632 kdiag0(:) = sgn_lf*(
m_two*
m_pi - sgn*sgn_lf*eigv(:))/(
m_two*
m_pi*fac_eps0 - sgn*eigv(:))
637 fac_epsd = (deb%eps_d +
m_one)/(deb%eps_d -
m_one)
638 kdiagd(:) = sgn_lf*(
m_two*
m_pi - sgn*sgn_lf*eigv(:))/(
m_two*
m_pi*fac_epsd - sgn*eigv(:))
644 fact2(:) = kdiag0(:)*fact1(:)
652 if (abs(drl%w0) <=
m_epsilon) drl%w0 = 1.0e-8_real64
653 fact1(:) = fact2(:) + drl%w0*drl%w0
655 kdiag0(:) = fact2(:)/fact1(:)
658 scr3 = matmul(sm12, eigt)
659 scr2 = matmul(transpose(eigt), sp12)
660 scr4 = transpose(scr3)
662 scr1(:,i) = scr3(:, i)*fact1(i)
664 matqq = matmul(scr1, scr2)
666 scr1(:,i) = scr3(:, i)*fact2(i)
668 if (which_eom == pcm_electrons)
then
669 matqv = -matmul(scr1, scr4)
671 matqv_lf = -matmul(scr1, scr4)
674 scr1(:,i) = scr3(:,i)*kdiag0(i)
676 if (which_eom == pcm_electrons)
then
677 matq0 = -matmul(scr1, scr4)
679 matq0_lf = -matmul(scr1, scr4)
682 scr1(:,i) = scr3(:, i)*kdiagd(i)
684 if (which_eom == pcm_electrons)
then
685 matqd = -matmul(scr1, scr4)
687 matqd_lf = -matmul(scr1, scr4)
690 safe_deallocate_a(scr4)
691 safe_deallocate_a(scr1)
692 safe_deallocate_a(scr2)
693 safe_deallocate_a(scr3)
694 safe_deallocate_a(fact1)
695 safe_deallocate_a(fact2)
696 safe_deallocate_a(kdiag0)
697 safe_deallocate_a(kdiagd)
699 if (enough_initial)
then
711 subroutine green_d(i, j, value)
712 integer,
intent(in) :: i, j
713 real(real64),
intent(out) :: value
715 real(real64) :: dist,diff(3)
720 diff = cts_act(i)%point - cts_act(j)%point
722 value = dot_product(cts_act(j)%normal, diff)/dist**3
725 value =
value/(
m_two*cts_act(i)%r_sphere)/cts_act(i)%area
736 subroutine green_s(i, j, value)
737 integer,
intent(in):: i,j
738 real(real64),
intent(out) :: value
740 real(real64) :: dist,diff(3)
745 diff = cts_act(i)%point - cts_act(j)%point
759 safe_allocate(eigv(1:nts_act))
760 safe_allocate(eigt(1:nts_act, 1:nts_act))
761 safe_allocate(sm12(1:nts_act, 1:nts_act))
762 safe_allocate(sp12(1:nts_act, 1:nts_act))
771 safe_deallocate_a(eigv)
772 safe_deallocate_a(eigt)
773 safe_deallocate_a(sm12)
774 safe_deallocate_a(sp12)
784 integer :: info, lwork, liwork
785 real(real64),
allocatable :: scr1(:,:), scr2(:,:), eigt_t(:,:)
788 integer,
allocatable :: iwork(:)
789 real(real64),
allocatable :: work(:)
793 safe_allocate(scr1(1:nts_act, 1:nts_act))
794 safe_allocate(scr2(1:nts_act, 1:nts_act))
795 safe_allocate(eigt_t(1:nts_act, 1:nts_act))
796 safe_allocate(work(1:1 + 6*nts_act + 2*nts_act*nts_act))
797 safe_allocate(iwork(1:3 + 5*nts_act))
803 lwork = 1 + 6*nts_act + 2*nts_act*nts_act
804 liwork = 3 + 5*nts_act
806 call dsyevd(jobz, uplo, nts_act, eigt, nts_act, eigv, work, lwork, iwork, liwork, info)
808 if (eigv(i) <
m_zero)
then
809 write(
message(1),*)
"Eigenvalue ", i,
" of S when constructing the TS matrix is negative!"
810 write(
message(2),*)
"I put it to 1e-8"
812 eigv(i) = 1.0e-8_real64
814 scr1(:,i) = eigt(:,i)*
sqrt(eigv(i))
816 eigt_t = transpose(eigt)
817 sp12 = matmul(scr1, eigt_t)
819 scr1(:, i) = eigt(:, i)/
sqrt(eigv(i))
821 sm12 = matmul(scr1, eigt_t)
823 scr1(:,i) = cald(:, i)*cts_act(i)%area
825 scr2 = matmul(matmul(sm12, scr1), sp12)
828 eigt(i, j) =
m_half*(scr2(i, j) + scr2(j, i))
831 call dsyevd(jobz,uplo,nts_act,eigt,nts_act,eigv,work,lwork, &
834 safe_deallocate_a(work)
835 safe_deallocate_a(iwork)
836 safe_deallocate_a(scr1)
837 safe_deallocate_a(scr2)
838 safe_deallocate_a(eigt_t)
845 logical,
intent(out) :: not_yet_called
849 enough_initial = .
true.
850 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