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