34 use,
intrinsic :: iso_fortran_env
59 integer,
parameter :: &
60 OUTPUT_COORDINATES = 1, &
68 real(real64),
allocatable :: coords(:,:), gradients(:,:)
69 real(real64),
allocatable :: acc(:,:)
70 real(real64),
allocatable :: tot_force(:,:)
71 real(real64),
allocatable :: vel(:,:)
72 real(real64),
allocatable :: prev_tot_force(:,:)
73 integer,
allocatable :: species(:)
75 real(real64),
allocatable :: mass(:)
76 real(real64),
allocatable :: atom_charges(:,:)
77 character(len=LABEL_LEN),
allocatable :: labels(:)
78 real(real64),
allocatable :: prev_acc(:,:,:)
79 real(real64) :: scc_tolerance
80 class(ions_t),
pointer :: ions => null()
81 type(c_ptr) :: output_handle(2)
82 type(ion_dynamics_t) :: ions_dyn
83 class(lasers_t),
pointer :: lasers => null()
84 logical :: laser_field
85 real(real64) :: field(3)
86 real(real64) :: energy
88 type(TDftbPlus) :: dftbp
108 procedure dftb_constructor
112 integer,
parameter :: &
124 class(dftb_t),
pointer :: sys
125 type(namespace_t),
intent(in) :: namespace
126 type(mpi_grp_t),
intent(in) :: grp
131 message(1) =
"DFTB+ system not available. This feature requires compiling Octopus with the DFTB+ library"
148 subroutine dftb_init(this, namespace, grp)
149 class(dftb_t),
target,
intent(inout) :: this
150 type(namespace_t),
intent(in) :: namespace
151 type(mpi_grp_t),
intent(in) :: grp
153 integer :: ii, jj, ispec
154 character(len=MAX_PATH_LEN) :: slako_dir
155 character(len=1),
allocatable :: max_ang_mom(:)
156 character(len=LABEL_LEN) :: this_max_ang_mom, this_label
157 integer :: n_maxang_block
159 real(real64) :: initial_temp
163 type(fnode),
pointer :: proot, pgeo, pham, pdftb, pmaxang, pslakos, ptype2files, panalysis
164 type(fnode),
pointer :: pparseropts
165 type(fnode),
pointer :: pelecdyn, pperturb, plaser
170 this%namespace = namespace
172 call this%init_parallelization(grp)
175 allocate(this%supported_interactions(0))
176 allocate(this%supported_interactions_as_partner(0))
179 call this%quantities%add(
quantity_t(
"position", updated_on_demand = .false.))
180 call this%quantities%add(
quantity_t(
"velocity", updated_on_demand = .false.))
184 this%ions =>
ions_t(namespace, grp, shared_namespace=.
true.)
185 this%n_atom = this%ions%natoms
186 safe_allocate(this%coords(1:3, 1:this%n_atom))
187 safe_allocate(this%acc(1:3, 1:this%n_atom))
188 safe_allocate(this%vel(1:3, 1:this%n_atom))
189 safe_allocate(this%tot_force(1:3, 1:this%n_atom))
190 safe_allocate(this%prev_tot_force(1:3, 1:this%n_atom))
191 safe_allocate(this%gradients(1:3, 1:this%n_atom))
192 safe_allocate(this%species(1:this%n_atom))
193 safe_allocate(this%mass(1:this%n_atom))
194 safe_allocate(this%atom_charges(1:this%n_atom, 1))
195 safe_allocate(this%labels(1:this%ions%nspecies))
196 safe_allocate(max_ang_mom(1:this%ions%nspecies))
201 this%labels(1) = trim(this%ions%atom(1)%label)
203 this%coords = this%ions%pos
205 this%mass = this%ions%mass
206 do ii = 1, this%n_atom
207 if ((ii > 1) .and. .not. (any(this%labels(1:ispec) == this%ions%atom(ii)%label)))
then
209 this%labels(ispec) = trim(this%ions%atom(ii)%label)
212 if (trim(this%ions%atom(ii)%label) == trim(this%labels(jj)))
then
213 this%species(ii) = jj
235 if (
parse_block(namespace,
'MaxAngularMomentum', blk) == 0)
then
237 if (n_maxang_block /= this%ions%nspecies)
then
241 do ii = 1, n_maxang_block
244 if (.not. any([
"s",
"p",
"d",
"f"] == trim(adjustl(this_max_ang_mom))))
then
245 call messages_input_error(namespace,
"MaxAngularMomentum",
"Wrong maximum angular momentum for element"//trim(this_label))
247 do jj = 1, this%ions%nspecies
248 if (trim(adjustl(this_label)) == trim(adjustl(this%labels(jj))))
then
249 max_ang_mom(jj) = trim(adjustl(this_max_ang_mom))
272 if (this%dynamics ==
bo)
then
290 if (this%lasers%no_lasers > 0)
then
291 this%laser_field = .
true.
293 this%laser_field = .false.
297 call tdftbplus_init(this%dftbp)
299 call this%dftbp%getEmptyInput(
input)
300 call input%getRootNode(proot)
301 call setchild(proot,
"Geometry", pgeo)
302 call setchildvalue(pgeo,
"Periodic", .false.)
303 call setchildvalue(pgeo,
"TypeNames", this%labels(1:this%ions%nspecies))
304 call setchildvalue(pgeo,
"TypesAndCoordinates", reshape(this%species, [1,
size(this%species)]), this%coords)
305 call setchild(proot,
"Hamiltonian", pham)
306 call setchild(pham,
"Dftb", pdftb)
307 call setchildvalue(pdftb,
"Scc", .
true.)
316 call parse_variable(namespace,
'SccTolerance', 1e-9_real64, this%scc_tolerance)
318 call setchildvalue(pdftb,
"SccTolerance", this%scc_tolerance)
321 call setchild(pdftb,
"MaxAngularMomentum", pmaxang)
323 do ii = 1, this%ions%nspecies
324 call setchildvalue(pmaxang, this%labels(ii), max_ang_mom(ii))
330 call setchild(pdftb,
"SlaterKosterFiles", pslakos)
331 call setchild(pslakos,
"Type2FileNames", ptype2files)
332 call setchildvalue(ptype2files,
"Prefix", slako_dir)
333 call setchildvalue(ptype2files,
"Separator",
"-")
334 call setchildvalue(ptype2files,
"Suffix",
".skf")
337 call setchild(proot,
"Analysis", panalysis)
338 call setchildvalue(panalysis,
"CalculateForces", .
true.)
340 call setchild(proot,
"ParserOptions", pparseropts)
341 call setchildvalue(pparseropts,
"ParserVersion", 5)
343 if (this%dynamics == ehrenfest)
then
344 call setchild(proot,
"ElectronDynamics", pelecdyn)
345 call setchildvalue(pelecdyn,
"IonDynamics", this%ions_dyn%is_active())
346 if (this%ions_dyn%is_active())
then
347 call setchildvalue(pelecdyn,
"InitialTemperature", initial_temp)
351 call setchildvalue(pelecdyn,
"Steps", 1)
352 call setchildvalue(pelecdyn,
"TimeStep",
m_one)
353 call setchild(pelecdyn,
"Perturbation", pperturb)
354 if (this%laser_field)
then
355 call setchild(pperturb,
"Laser", plaser)
357 call setchildvalue(plaser,
"LaserEnergy",
m_one)
358 call setchildvalue(pelecdyn,
"FieldStrength",
m_one)
360 call setchild(pperturb,
"None", plaser)
364 message(1) =
'Input tree in HSD format:'
366 call dumphsd(
input%hsdTree, stdout)
369 call this%dftbp%setupCalculator(
input)
370 call this%dftbp%setGeometry(this%coords)
378 class(
dftb_t),
target,
intent(inout) :: this
383 select type (interaction)
385 message(1) =
"Trying to initialize an unsupported interaction by DFTB+."
394 class(
dftb_t),
intent(inout) :: this
399 select type (algo => this%algo)
401 select case (this%dynamics)
403 call this%dftbp%getGradients(this%gradients)
404 this%tot_force = -this%gradients
406 call this%dftbp%getEnergy(this%energy)
407 call this%dftbp%initializeTimeProp(algo%dt, this%laser_field, .false.)
417 class(
dftb_t),
intent(inout) :: this
419 character(len=:),
allocatable,
intent(out) :: updated_quantities(:)
421 integer :: ii, jj, il
422 type(
tdf_t) :: ff, phi
423 complex(real64) :: amp, pol(3)
424 real(real64) :: time, omega
427 call profiling_in(trim(this%namespace%get())//
":"//trim(operation%id))
429 select type (algo => this%algo)
433 select case (this%dynamics)
436 select case (operation%id)
441 safe_allocate(this%prev_acc(1:3, 1:this%n_atom, 1))
442 do jj = 1, this%n_atom
443 this%acc(1:3, jj) = this%tot_force(1:3, jj) / this%mass(jj)
447 safe_deallocate_a(this%prev_acc)
450 do jj = 1, this%n_atom
451 this%coords(1:3, jj) = this%coords(1:3, jj) + algo%dt * this%vel(1:3, jj) &
452 +
m_half * algo%dt**2 * this%acc(1:3, jj)
454 updated_quantities = [
"position"]
457 do ii =
size(this%prev_acc, dim=3) - 1, 1, -1
458 this%prev_acc(1:3, 1:this%n_atom, ii + 1) = this%prev_acc(1:3, 1:this%n_atom, ii)
460 this%prev_acc(1:3, 1:this%n_atom, 1) = this%acc(1:3, 1:this%n_atom)
462 call this%dftbp%setGeometry(this%coords)
463 call this%dftbp%getGradients(this%gradients)
464 this%tot_force = -this%gradients
466 do jj = 1, this%n_atom
467 this%acc(1:3, jj) = this%tot_force(1:3, jj) / this%mass(jj)
471 this%vel(1:3, 1:this%n_atom) = this%vel(1:3, 1:this%n_atom) &
472 +
m_half * algo%dt * (this%prev_acc(1:3, 1:this%n_atom, 1) + &
473 this%acc(1:3, 1:this%n_atom))
474 updated_quantities = [
"velocity"]
482 select case (operation%id)
491 time = this%iteration%value()
492 do il = 1, this%lasers%no_lasers
499 amp =
tdf(ff, time) *
exp(
m_zi * (omega*time +
tdf(phi, time)))
500 this%field(1:3) = this%field(1:3) + real(amp*pol(1:3), real64)
503 call this%dftbp%setTdElectricField(this%field)
504 call this%dftbp%doOneTdStep(this%iteration%counter(), atomnetcharges=this%atom_charges, coord=this%coords,&
505 force=this%tot_force, energy=this%energy)
519 call profiling_out(trim(this%namespace%get())//
":"//trim(operation%id))
525 class(
dftb_t),
intent(in) :: this
526 real(real64),
intent(in) :: tol
539 class(
dftb_t),
intent(inout) :: this
543 select type (algo => this%algo)
546 call io_mkdir(
'td.general', this%namespace)
547 if (this%grp%is_root())
then
548 call write_iter_init(this%output_handle(output_coordinates), 0, algo%dt, &
549 trim(
io_workpath(
"td.general/coordinates", this%namespace)))
551 trim(
io_workpath(
"td.general/forces", this%namespace)))
555 call this%output_write()
563 class(
dftb_t),
intent(inout) :: this
567 select type (algo => this%algo)
569 if (this%grp%is_root())
then
580 class(
dftb_t),
intent(inout) :: this
582 integer :: idir, iat, iout
583 character(len=50) :: aux
584 character(1) :: out_label(2)
585 real(real64) :: tmp(3)
587 if (.not. this%grp%is_root())
return
590 call profiling_in(trim(this%namespace%get())//
":"//
"OUTPUT_WRITE")
592 select type (algo => this%algo)
597 if (this%iteration%counter() == 0)
then
601 call write_iter_string(this%output_handle(iout),
'#####################################################################')
609 do iat = 1, this%n_atom
611 write(aux,
'(a1,a1,i3,a1,i3,a1)') out_label(iout),
'(', iat,
',', idir,
')'
622 do iat = 1, this%n_atom
631 call write_iter_string(this%output_handle(iout),
'#######################################################################')
639 do iat = 1, this%n_atom
653 call profiling_out(trim(this%namespace%get())//
":"//
"OUTPUT_WRITE")
659 class(
dftb_t),
intent(in) :: partner
664 select type (interaction)
666 message(1) =
"Unsupported interaction."
675 class(
dftb_t),
intent(inout) :: partner
680 select type (interaction)
682 message(1) =
"Unsupported interaction."
691 class(
dftb_t),
intent(inout) :: this
696 this%prev_tot_force(1:3, 1:this%n_atom) = this%tot_force(1:3, 1:this%n_atom)
703 class(
dftb_t),
intent(inout) :: this
707 this%kinetic_energy =
m_zero
714 class(
dftb_t),
intent(inout) :: this
718 message(1) =
"DFTB system "//trim(this%namespace%get())//
" cannot write restart data."
727 class(
dftb_t),
intent(inout) :: this
739 type(
dftb_t),
intent(inout) :: this
743 safe_deallocate_a(this%coords)
744 safe_deallocate_a(this%acc)
745 safe_deallocate_a(this%vel)
746 safe_deallocate_a(this%tot_force)
747 safe_deallocate_a(this%prev_tot_force)
748 safe_deallocate_a(this%gradients)
749 safe_deallocate_a(this%species)
750 safe_deallocate_a(this%mass)
753 deallocate(this%ions)
756 if (
associated(this%lasers))
then
757 deallocate(this%lasers)
761 call tdftbplus_destruct(this%dftbp)
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
Writes to the corresponding file and adds one to the iteration. Must be called after write_iter_init(...
double exp(double __x) __attribute__((__nothrow__
This module implements the basic elements defining algorithms.
subroutine dftb_output_write(this)
subroutine dftb_update_interactions_start(this)
subroutine dftb_init_interaction_as_partner(partner, interaction)
subroutine dftb_output_finish(this)
subroutine dftb_restart_write_data(this)
subroutine dftb_init_interaction(this, interaction)
logical function dftb_restart_read_data(this)
logical function dftb_do_algorithmic_operation(this, operation, updated_quantities)
subroutine dftb_update_kinetic_energy(this)
subroutine dftb_initialize(this)
integer, parameter output_forces
class(dftb_t) function, pointer dftb_constructor(namespace, grp)
The factory routine (or constructor) allocates a pointer of the corresponding type and then calls the...
subroutine dftb_finalize(this)
logical function dftb_is_tolerance_reached(this, tol)
subroutine dftb_output_start(this)
subroutine, public dftb_init(this, namespace, grp)
The init routine is a module level procedure This has the advantage that different classes can have d...
subroutine dftb_copy_quantities_to_interaction(partner, interaction)
real(real64), parameter, public m_zero
complex(real64), parameter, public m_zi
real(real64), parameter, public m_half
real(real64), parameter, public m_one
This module defines the abstract interaction_t class, and some auxiliary classes for interactions.
character(len=max_path_len) function, public io_workpath(path, namespace)
construct path name from given name and namespace
subroutine, public io_mkdir(fname, namespace, parents)
subroutine, public ion_dynamics_unfreeze(this)
Unfreezes the ionic movement.
subroutine, public ion_dynamics_init(this, namespace, ions, symmetrize, symm)
subroutine, public ion_dynamics_end(this)
complex(real64) function, dimension(3), public laser_polarization(laser)
subroutine, public lasers_parse_external_fields(this)
subroutine, public laser_get_f(laser, ff)
real(real64) function, public laser_carrier_frequency(laser)
subroutine, public laser_get_phi(laser, phi)
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
character(len=512), private msg
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)
subroutine, public messages_input_error(namespace, var, details, row, column)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
This module implements the multisystem debug functionality.
subroutine, public parse_block_string(blk, l, c, res, convert_to_c)
integer function, public parse_block(namespace, name, blk, check_varinfo_)
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
This module implements the basic propagator framework.
character(len=algo_label_len), parameter, public store_current_status
character(len=30), parameter, public verlet_start
character(len=30), parameter, public verlet_compute_acc
character(len=30), parameter, public verlet_update_pos
character(len=30), parameter, public verlet_finish
character(len=30), parameter, public verlet_compute_vel
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
This module implements the abstract system type.
subroutine, public system_end(this)
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
character(len=20) pure function, public units_abbrev(this)
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
type(unit_t), public unit_kelvin
For converting energies into temperatures.
Explicit interfaces to C functions, defined in write_iter_low.cc.
subroutine, public write_iter_header(out, string)
subroutine, public write_iter_string(out, string)
subroutine, public write_iter_init(out, iter, factor, file)
Descriptor of one algorithmic operation.
class for a tight binding
abstract interaction class
surrogate interaction class to avoid circular dependencies between modules.
Abstract class implementing propagators.
Systems (system_t) can expose quantities that can be used to calculate interactions with other system...
Abstract class for systems.