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
147 integer,
intent(in) :: this_eps
152 logical :: firsttime = .
true.
153 logical :: initial_electron = .
true.
154 logical :: initial_external = .
true.
155 logical :: initial_kick = .
true.
162 message(1) =
"pcm_charges_propagation: EOM evolution of PCM charges can only be due to solute electrons"
163 message(2) =
"or external potential (including the kick)."
169 nts_act =
size(this_cts_act)
170 if (
size(q_t) /= nts_act)
then
171 message(1) =
"pcm_charges_propagation: Number of tesserae do not coincide with size of PCM charges array."
175 safe_allocate(cts_act(1:nts_act))
176 cts_act = this_cts_act
179 select case (which_eps)
180 case (pcm_debye_model)
181 if (
present(this_deb))
then
184 message(1) =
"pcm_charges_propagation: EOM-PCM error. Debye dielectric function requires three parameters."
188 if (
present(this_drl))
then
191 message(1) =
"pcm_charges_propagation: EOM-PCM error. Drude-Lorentz dielectric function requires three parameters."
195 message(1) =
"pcm_charges_propagation: EOM-PCM error. Only Debye or Drude-Lorent dielectric models are allowed."
200 message(1) =
"pcm_charges_propagation: EOM-PCM error. Debye EOM-PCM require a non-null Debye relaxation time."
208 select case (which_eps)
209 case (pcm_debye_model)
216 message(1) =
"pcm_charges_propagation: EOM-PCM error. Only Debye EOM-PCM can startup from input charges."
221 if ((initial_electron .and. which_eom == pcm_electrons) .or. &
223 (initial_kick .and. which_eom ==
pcm_kick))
then
231 if (initial_electron .and. which_eom == pcm_electrons) initial_electron = .false.
234 if (initial_kick .and. which_eom ==
pcm_kick) initial_kick = .false.
239 if (which_eps == pcm_debye_model)
then
253 real(real64),
intent(out) :: q_t(:)
254 real(real64),
intent(in) :: pot_t(:)
257 real(real64) :: aux1(3)
264 if (which_eom == pcm_electrons)
then
265 safe_allocate(q_tp(1:nts_act))
266 asc_unit =
io_open(
pcm_dir//
'ASC_e.dat', namespace, action=
'read')
268 read(asc_unit,*) aux1, q_t(ia), aux2
273 safe_allocate(qext_tp(1:nts_act))
274 asc_unit =
io_open(
pcm_dir//
'ASC_ext.dat', namespace, action=
'read')
276 read(asc_unit,*) aux1, q_t(ia), aux2
280 else if (which_eom ==
pcm_kick)
then
281 safe_allocate(qkick_tp(1:nts_act))
282 asc_unit =
io_open(
pcm_dir//
'ASC_kick.dat', namespace, action=
'read')
284 read(asc_unit,*) aux1, q_t(ia), aux2
290 safe_allocate(pot_tp(1:nts_act))
299 real(real64),
intent(out) :: q_t(:)
300 real(real64),
intent(in) :: pot_t(:)
305 if (which_eom == pcm_electrons)
then
309 message(1) =
'EOM-PCM for solvent polarization due to solute electrons considers that you start from a ground state run.'
312 safe_allocate(pot_tp(1:nts_act))
316 q_t = matmul(matq0, pot_t)
318 safe_allocate(q_tp(1:nts_act))
322 safe_allocate(dq_tp(1:nts_act))
323 safe_allocate(force_tp(1:nts_act))
332 safe_allocate(potext_tp(1:nts_act))
336 q_t = matmul(matqd_lf, pot_t)
338 safe_allocate(qext_tp(1:nts_act))
342 safe_allocate(dqext_tp(1:nts_act))
343 safe_allocate(force_qext_tp(1:nts_act))
348 else if (which_eom ==
pcm_kick)
then
351 safe_allocate(dqkick_tp(1:nts_act))
352 safe_allocate(force_qkick_tp(1:nts_act))
358 dqkick_tp = matmul(matqv_lf, pot_t)*dt
360 q_t = matmul(matqv_lf - matmul(matqq, matqd_lf), pot_t)
363 safe_allocate(qkick_tp(1:nts_act))
378 real(real64),
intent(out) :: q_t(:)
379 real(real64),
intent(in) :: pot_t(:)
383 if (which_eom == pcm_electrons)
then
385 q_t(:) = q_tp(:) - dt*matmul(matqq, q_tp) + &
386 dt*matmul(matqv, pot_tp) + &
387 matmul(matqd, pot_t - pot_tp)
395 q_t(:) = qext_tp(:) - dt*matmul(matqq, qext_tp) + &
396 dt*matmul(matqv_lf, potext_tp) + &
397 matmul(matqd_lf, pot_t - potext_tp)
403 else if (which_eom ==
pcm_kick)
then
405 q_t(:) = qkick_tp(:) - dt*matmul(matqq, qkick_tp)
436 real(real64),
intent(out) :: q_t(:)
437 real(real64),
intent(in) :: pot_t(:)
439 real(real64) :: force(nts_act)
443 if (which_eom == pcm_electrons)
then
446 q_t = q_tp + f1*dq_tp + f2*force_tp
447 force = -matmul(matqq, q_t) + matmul(matqv, pot_t)
448 dq_tp = f3*dq_tp + f4*(force+force_tp) -f5*force_tp
454 q_t = qext_tp + f1*dqext_tp + f2*force_qext_tp
455 force = -matmul(matqq, q_t) + matmul(matqv_lf, pot_t)
456 dqext_tp = f3*dqext_tp + f4*(force + force_qext_tp) -f5*force_qext_tp
457 force_qext_tp = force
460 else if (which_eom ==
pcm_kick)
then
462 q_t = qkick_tp + f1*dqkick_tp + f2*force_qkick_tp
463 force = -matmul(matqq, q_t)
464 dqkick_tp = f3*dqkick_tp + f4*(force + force_qkick_tp) -f5*force_qkick_tp
465 force_qkick_tp = force
479 integer :: itess, jtess
480 integer :: pcmmat0_unit, pcmmatd_unit
484 if (which_eom == pcm_electrons)
then
485 safe_allocate(matq0(1:nts_act, 1:nts_act))
486 safe_allocate(matqd(1:nts_act, 1:nts_act))
487 safe_allocate(matqv(1:nts_act, 1:nts_act))
488 if (.not.
allocated(matqq))
then
489 safe_allocate(matqq(1:nts_act, 1:nts_act))
492 safe_allocate(matq0_lf(1:nts_act, 1:nts_act))
493 safe_allocate(matqd_lf(1:nts_act, 1:nts_act))
494 safe_allocate(matqv_lf(1:nts_act, 1:nts_act))
495 if (.not.
allocated(matqq))
then
496 safe_allocate(matqq(1:nts_act, 1:nts_act))
501 if (which_eom == pcm_electrons)
then
502 pcmmat0_unit =
io_open(
pcm_dir//
'pcm_matrix_static_from_eom.out', namespace, action=
'write')
503 pcmmatd_unit =
io_open(
pcm_dir//
'pcm_matrix_dynamic_from_eom.out', namespace, action=
'write')
504 do jtess = 1, nts_act
505 do itess = 1, nts_act
506 write(pcmmat0_unit,*) matq0(itess, jtess)
507 write(pcmmatd_unit,*) matqd(itess, jtess)
513 pcmmat0_unit =
io_open(
pcm_dir//
'pcm_matrix_static_lf_from_eom.out', namespace, action=
'write')
514 pcmmatd_unit =
io_open(
pcm_dir//
'pcm_matrix_dynamic_lf_from_eom.out', namespace, action=
'write')
515 do jtess = 1, nts_act
516 do itess = 1, nts_act
517 write(pcmmat0_unit,*) matq0_lf(itess, jtess)
518 write(pcmmatd_unit,*) matqd_lf(itess, jtess)
534 safe_deallocate_a(q_tp)
535 safe_deallocate_a(qext_tp)
536 safe_deallocate_a(qkick_tp)
539 safe_deallocate_a(dq_tp)
540 safe_deallocate_a(dqext_tp)
541 safe_deallocate_a(dqkick_tp)
544 safe_deallocate_a(force_tp)
545 safe_deallocate_a(force_qext_tp)
546 safe_deallocate_a(force_qkick_tp)
549 safe_deallocate_a(matq0)
550 safe_deallocate_a(matqd)
551 safe_deallocate_a(matq0_lf)
552 safe_deallocate_a(matqd_lf)
553 safe_deallocate_a(matqv)
554 safe_deallocate_a(matqv_lf)
555 safe_deallocate_a(matqq)
557 safe_deallocate_a(pot_tp)
558 safe_deallocate_a(cts_act)
576 real(real64),
allocatable :: scr4(:,:), scr1(:,:)
577 real(real64),
allocatable :: scr2(:,:), scr3(:,:)
578 real(real64),
allocatable :: fact1(:), fact2(:)
580 real(real64),
allocatable :: Kdiag0(:), Kdiagd(:)
584 real(real64) :: sgn,sgn_lf, fac_eps0, fac_epsd
587 logical :: firsttime = .
true.
598 safe_allocate(cals(1:nts_act, 1:nts_act))
599 safe_allocate(cald(1:nts_act, 1:nts_act))
600 safe_allocate(kdiag0(1:nts_act))
601 safe_allocate(kdiagd(1:nts_act))
602 safe_allocate(fact1(1:nts_act))
603 safe_allocate(fact2(1:nts_act))
619 safe_deallocate_a(cals)
620 safe_deallocate_a(cald)
622 safe_allocate(scr4(1:nts_act, 1:nts_act))
623 safe_allocate(scr1(1:nts_act, 1:nts_act))
624 safe_allocate(scr2(1:nts_act, 1:nts_act))
625 safe_allocate(scr3(1:nts_act, 1:nts_act))
627 if (which_eps == pcm_debye_model)
then
629 fac_eps0 = (deb%eps_0 +
m_one)/(deb%eps_0 -
m_one)
630 kdiag0(:) = sgn_lf*(
m_two*
m_pi - sgn*sgn_lf*eigv(:))/(
m_two*
m_pi*fac_eps0 - sgn*eigv(:))
635 fac_epsd = (deb%eps_d +
m_one)/(deb%eps_d -
m_one)
636 kdiagd(:) = sgn_lf*(
m_two*
m_pi - sgn*sgn_lf*eigv(:))/(
m_two*
m_pi*fac_epsd - sgn*eigv(:))
642 fact2(:) = kdiag0(:)*fact1(:)
650 if (abs(drl%w0) <=
m_epsilon) drl%w0 = 1.0e-8_real64
651 fact1(:) = fact2(:) + drl%w0*drl%w0
653 kdiag0(:) = fact2(:)/fact1(:)
656 scr3 = matmul(sm12, eigt)
657 scr2 = matmul(transpose(eigt), sp12)
658 scr4 = transpose(scr3)
660 scr1(:,i) = scr3(:, i)*fact1(i)
662 matqq = matmul(scr1, scr2)
664 scr1(:,i) = scr3(:, i)*fact2(i)
666 if (which_eom == pcm_electrons)
then
667 matqv = -matmul(scr1, scr4)
669 matqv_lf = -matmul(scr1, scr4)
672 scr1(:,i) = scr3(:,i)*kdiag0(i)
674 if (which_eom == pcm_electrons)
then
675 matq0 = -matmul(scr1, scr4)
677 matq0_lf = -matmul(scr1, scr4)
680 scr1(:,i) = scr3(:, i)*kdiagd(i)
682 if (which_eom == pcm_electrons)
then
683 matqd = -matmul(scr1, scr4)
685 matqd_lf = -matmul(scr1, scr4)
688 safe_deallocate_a(scr4)
689 safe_deallocate_a(scr1)
690 safe_deallocate_a(scr2)
691 safe_deallocate_a(scr3)
692 safe_deallocate_a(fact1)
693 safe_deallocate_a(fact2)
694 safe_deallocate_a(kdiag0)
695 safe_deallocate_a(kdiagd)
697 if (enough_initial)
then
708 subroutine green_d(i, j, value)
709 integer,
intent(in) :: i, j
710 real(real64),
intent(out) :: value
712 real(real64) :: dist,diff(3)
717 diff = cts_act(i)%point - cts_act(j)%point
719 value = dot_product(cts_act(j)%normal, diff)/dist**3
722 value =
value/(
m_two*cts_act(i)%r_sphere)/cts_act(i)%area
732 subroutine green_s(i, j, value)
733 integer,
intent(in):: i,j
734 real(real64),
intent(out) :: value
736 real(real64) :: dist,diff(3)
741 diff = cts_act(i)%point - cts_act(j)%point
755 safe_allocate(eigv(1:nts_act))
756 safe_allocate(eigt(1:nts_act, 1:nts_act))
757 safe_allocate(sm12(1:nts_act, 1:nts_act))
758 safe_allocate(sp12(1:nts_act, 1:nts_act))
767 safe_deallocate_a(eigv)
768 safe_deallocate_a(eigt)
769 safe_deallocate_a(sm12)
770 safe_deallocate_a(sp12)
780 integer :: info, lwork, liwork
781 real(real64),
allocatable :: scr1(:,:), scr2(:,:), eigt_t(:,:)
784 integer,
allocatable :: iwork(:)
785 real(real64),
allocatable :: work(:)
789 safe_allocate(scr1(1:nts_act, 1:nts_act))
790 safe_allocate(scr2(1:nts_act, 1:nts_act))
791 safe_allocate(eigt_t(1:nts_act, 1:nts_act))
792 safe_allocate(work(1:1 + 6*nts_act + 2*nts_act*nts_act))
793 safe_allocate(iwork(1:3 + 5*nts_act))
799 lwork = 1 + 6*nts_act + 2*nts_act*nts_act
800 liwork = 3 + 5*nts_act
802 call dsyevd(jobz, uplo, nts_act, eigt, nts_act, eigv, work, lwork, iwork, liwork, info)
804 if (eigv(i) <
m_zero)
then
805 write(
message(1),*)
"Eigenvalue ", i,
" of S when constructing the TS matrix is negative!"
806 write(
message(2),*)
"I put it to 1e-8"
808 eigv(i) = 1.0e-8_real64
810 scr1(:,i) = eigt(:,i)*
sqrt(eigv(i))
812 eigt_t = transpose(eigt)
813 sp12 = matmul(scr1, eigt_t)
815 scr1(:, i) = eigt(:, i)/
sqrt(eigv(i))
817 sm12 = matmul(scr1, eigt_t)
819 scr1(:,i) = cald(:, i)*cts_act(i)%area
821 scr2 = matmul(matmul(sm12, scr1), sp12)
824 eigt(i, j) =
m_half*(scr2(i, j) + scr2(j, i))
827 call dsyevd(jobz,uplo,nts_act,eigt,nts_act,eigv,work,lwork, &
830 safe_deallocate_a(work)
831 safe_deallocate_a(iwork)
832 safe_deallocate_a(scr1)
833 safe_deallocate_a(scr2)
834 safe_deallocate_a(eigt_t)
841 logical,
intent(out) :: not_yet_called
846 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