40 use,
intrinsic :: iso_fortran_env
65 class(box_t),
pointer :: box
66 character(len=500) :: clist
67 character(len=15) :: lab
69 logical,
allocatable :: mesh_mask(:)
70 logical,
allocatable :: ions_mask(:)
71 type(local_write_t) :: writ
74 type(electrons_t),
pointer :: sys
75 integer,
parameter :: BADER = 9
101 safe_deallocate_p(sys)
116 type(local_domain_t),
allocatable :: loc_domains(:)
117 integer :: err, iter, l_start, l_end, l_step, id
118 integer :: ia, n_spec_def, read_data, iunit, ispec
119 integer ::
length, folder_index
120 real(real64) :: default_dt, dt
121 character(len=MAX_PATH_LEN) :: filename, folder, folder_default, radiifile
122 character(len=MAX_PATH_LEN) :: in_folder, restart_folder, basename, frmt, ldrestart_folder
123 character(len=15) :: lab
124 logical :: iterate, ldupdate, ldoverwrite, ldrestart
130 message(1) =
'Info: Creating local domains'
134 write(folder_default,
'(a)')
'restart/gs/'
145 if (index(folder,
'/', back = .
true.) /= len_trim(folder))
then
146 folder = trim(folder)//
'/'
152 write(
message(1),
'(a)')
'Input: TDTimeStep must be positive.'
153 write(
message(2),
'(a)')
'Input: TDTimeStep reset to 0. Check input file.'
166 if (basename ==
" ") basename =
""
168 length = len_trim(basename)
171 basename = trim(basename(1:
length-4))
203 if (trim(radiifile) /=
"default")
then
205 if (n_spec_def > 0) n_spec_def = n_spec_def - 1
208 do ia = 1, sys%ions%nspecies
211 if (iunit /= -1)
then
213 write(
message(1),
'(a,a)')
'Redefining def_rsize from file:', trim(radiifile)
217 default_file:
do ispec = 1, n_spec_def
219 if (trim(lab) == trim(sys%ions%species(ia)%s%get_label()))
then
220 select type(spec=>sys%ions%species(ia)%s)
229 write(
message(1),
'(a,a)')
'Octopus could not open then file:', trim(radiifile)
246 write(folder_default,
'(a)')
'ld.general'
258 if (index(ldrestart_folder,
'/', .
true.) /= len_trim(ldrestart_folder))
then
259 write(ldrestart_folder,
'(a,a1)') trim(ldrestart_folder),
'/'
300 message(1) =
'Info: Computing local multipoles'
304 call local_init(sys%space, sys%gr, sys%ions, nd, loc_domains)
307 if (any(loc_domains(:)%dshape == bader))
then
321 dir=trim(ldrestart_folder), mesh = sys%gr)
323 call restart_ld%end()
331 in_folder = folder(1:len_trim(folder)-1)
332 folder_index = index(in_folder,
'/', .
true.)
333 restart_folder = in_folder(1:folder_index)
335 restart_folder = folder
338 dir=trim(restart_folder), mesh = sys%gr)
341 do iter = l_start, l_end, l_step
344 write(in_folder,
'(a,i0.7,a)') folder(folder_index+1:len_trim(folder)-1),iter,
"/"
345 write(filename,
'(a,a,a)') trim(in_folder), trim(basename)
348 if (l_start /= l_end)
then
352 write(frmt,
'(a,i0,a)')
"(a,i0.",10-len_trim(basename),
")"
353 write(filename, fmt=trim(frmt)) trim(basename), iter
356 write(filename,
'(a,a,a,a)') trim(in_folder),
"/", trim(basename)
365 call restart%read_mesh_function(sys%space, trim(filename), sys%gr, sys%st%rho(:,1), err)
368 write(
message(1),*)
'While reading density: "', trim(filename),
'", error code:', err
373 if ((iter == l_start .and. .not. ldrestart) .or. ldupdate)
then
380 loc_domains(id)%mesh_mask, sys%gr, sys%st, sys%hm, sys%ks, sys%ions, &
381 sys%ext_partners, kick, iter, l_start, ldoverwrite)
392 safe_deallocate_a(loc_domains)
394 message(1) =
'Info: Exiting local domains'
405 subroutine local_init(space, mesh, ions, nd, loc_domains)
406 class(
space_t),
intent(in) :: space
407 class(
mesh_t),
intent(in) :: mesh
408 type(
ions_t),
intent(in) :: ions
409 integer,
intent(out) :: nd
456 safe_allocate(loc_domains(1:nd))
459 safe_allocate(loc_domains(id)%mesh_mask(1:mesh%np))
460 safe_allocate(loc_domains(id)%ions_mask(1:ions%natoms))
478 class(
box_t),
pointer :: box
482 if (domain%dshape /= bader)
then
484 safe_deallocate_p(box)
487 safe_deallocate_a(domain%mesh_mask)
488 safe_deallocate_a(domain%ions_mask)
496 class(
space_t),
intent(in) :: space
497 type(
ions_t),
intent(in) :: ions
498 type(
block_t),
intent(in) :: blk
499 integer,
intent(in) :: row
503 real(real64) :: radius, center(space%dim), half_length(space%dim)
510 select case (domain%dshape)
517 do ia = 1, ions%natoms
519 call minimum_box%add_box(
box_sphere_t(space%dim, ions%pos(:, ia), radius, namespace))
522 domain%box => minimum_box
525 do ia = 1, ions%natoms
526 if (domain%box%contains_point(ions%pos(:, ia)) .and. .not.
loct_isinstringlist(ia, domain%clist))
then
528 if (ic <= 20)
write(
message(ic),
'(a,a,I0,a,a)')
'Atom: ',trim(ions%atom(ia)%species%get_label()), ia, &
529 ' is inside the union box BUT not in list: ', trim(domain%clist)
535 message(1) =
' THIS COULD GIVE INCORRECT RESULTS '
538 message(1) =
' AT LEAST 19 ATOMS ARE NOT PRESENT IN THE LIST'
550 domain%box =>
box_sphere_t(space%dim, center, radius, namespace)
562 domain%box =>
box_cylinder_t(space%dim, center, ions%latt%rlattice, radius, half_length(1)*
m_two, namespace)
587 class(
space_t),
intent(in) :: space
588 class(
mesh_t),
intent(in) :: mesh
590 integer,
intent(in) :: nd
593 integer :: id, ip, iunit, ierr
594 character(len=MAX_PATH_LEN) :: dirname
595 character(len=140),
allocatable :: lines(:)
596 real(real64),
allocatable :: ff(:,:)
601 dirname =
"./restart/ld"
602 write(
message(1),
'(a,a)')
'Info: Writing restart info to ', trim(dirname)
607 safe_allocate(lines(1:nd+2))
608 write(lines(1),
'(a,1x,i5)')
'Number of local domains =', nd
609 write(lines(2),
'(a3,1x,a15,1x,a5,1x)')
'#id',
'label',
'shape'
611 write(lines(id+2),
'(i3,1x,a15,1x,i5)') id, trim(loc_domains(id)%lab), loc_domains(id)%dshape
613 iunit = restart%open(
"ldomains.info")
614 call restart%write(iunit, lines, nd+2, ierr)
616 safe_deallocate_a(lines)
618 safe_allocate(ff(1:mesh%np, 1))
622 if (loc_domains(id)%mesh_mask(ip)) ff(ip, 1) = ff(ip, 1) + 2**real(id, real64)
625 call restart%write_mesh_function(space,
"ldomains", mesh, ff(1:mesh%np, 1), ierr)
626 safe_deallocate_a(ff)
635 class(
space_t),
intent(in) :: space
636 class(
mesh_t),
intent(in) :: mesh
637 type(
ions_t),
intent(in) :: ions
638 integer,
intent(in) :: nd
642 integer :: id, ip, iunit, ierr
643 character(len=31) :: line(1), tmp
644 real(real64),
allocatable :: mask(:)
648 message(1) =
'Info: Reading mesh points inside each local domain'
651 safe_allocate(mask(1:mesh%np))
654 iunit = restart%open(
"ldomains.info", status=
'old')
655 call restart%read(iunit, line, 1, ierr)
656 read(line(1),
'(a25,1x,i5)') tmp, ierr
657 call restart%close(iunit)
659 call restart%read_mesh_function(space,
"ldomains", mesh, mask, ierr)
662 loc_domains(id)%mesh_mask = .false.
664 if (
bitand(int(mask(ip)), 2**id) /= 0) loc_domains(id)%mesh_mask(ip) = .
true.
668 call local_ions_mask(loc_domains(id)%mesh_mask, ions, mesh, loc_domains(id)%ions_mask)
671 safe_deallocate_a(mask)
678 class(
space_t),
intent(in) :: space
679 class(
mesh_t),
intent(in) :: mesh
681 integer,
intent(in) :: nd
684 real(real64),
intent(in) :: ff(:)
686 integer(int64) :: how
687 integer :: id, ip, ierr
689 character(len=MAX_PATH_LEN) :: filename
690 real(real64),
allocatable :: dble_domain_map(:), domain_mesh(:)
695 message(1) =
'Info: Assigning mesh points inside each local domain'
699 if (any(loc_domains(:)%dshape == bader))
then
700 if (mesh%parallel_in_domains)
then
701 write(
message(1),
'(a)')
'Bader volumes can only be computed in serial'
709 select case (loc_domains(id)%dshape)
717 call local_ions_mask(loc_domains(id)%mesh_mask, ions, mesh, loc_domains(id)%ions_mask)
720 if (any(loc_domains(:)%dshape == bader))
then
731 safe_allocate(dble_domain_map(1:mesh%np))
732 safe_allocate(domain_mesh(1:mesh%np))
738 if (loc_domains(id)%mesh_mask(ip))
then
739 dble_domain_map(ip) = real(id, real64)
740 domain_mesh(ip) = domain_mesh(ip) + dble_domain_map(ip)
744 write(filename,
'(a,a)')
'domain.', trim(loc_domains(id)%lab)
746 pos=ions%pos, atoms=ions%atom)
750 pos=ions%pos, atoms=ions%atom)
752 safe_deallocate_a(dble_domain_map)
753 safe_deallocate_a(domain_mesh)
760 subroutine create_basins(namespace, space, mesh, ions, ff, basins)
762 class(
space_t),
intent(in) :: space
763 class(
mesh_t),
intent(in) :: mesh
764 type(
ions_t),
intent(in) :: ions
765 real(real64),
intent(in) :: ff(:)
766 type(
basins_t),
intent(inout) :: basins
768 logical :: use_atomic_radii
769 integer :: ip, ierr, ia, is, rankmin
770 integer(int64) :: how
771 real(real64) :: bader_threshold, dmin, dd
772 integer,
allocatable :: ion_map(:)
773 real(real64),
allocatable :: ff2(:,:), ffs(:)
785 call parse_variable(namespace,
'LDBaderThreshold', 0.01_real64, bader_threshold)
788 safe_allocate(ff2(1:mesh%np,1))
789 ff2(1:mesh%np,1) = ff(1:mesh%np)
792 safe_allocate(ffs(1:mesh%np))
793 do ia = 1, ions%natoms
795 ions%pos(:, ia), mesh, ffs)
796 do is = 1, ubound(ff2, dim=2)
797 ff2(1:mesh%np, is) = ff2(1:mesh%np, is) - ffs(1:mesh%np)
800 safe_deallocate_a(ffs)
803 call basins_analyze(basins, namespace, mesh, ff2(:,1), ff2, bader_threshold)
811 call dio_function_output(how,
'local.general',
'basinsmap', namespace, space, mesh, real(basins%map(1:mesh%np), real64) , &
812 unit_one, ierr, pos=ions%pos, atoms=ions%atom)
813 call dio_function_output(how,
'local.general',
'dens_ff2', namespace, space, mesh, ff2(:,1), &
814 unit_one, ierr, pos=ions%pos, atoms=ions%atom)
816 safe_deallocate_a(ff2)
827 if (use_atomic_radii)
then
828 safe_allocate(ion_map(1:ions%natoms))
830 do ia = 1, ions%natoms
836 if (all(ion_map(:) /= basins%map(ip)))
then
838 do ia = 1, ions%natoms
839 dd = norm2(mesh%x(ip, :) - ions%pos(:, ia))
840 if (dd <= ions%atom(ia)%species%get_vdw_radius()) basins%map(ip) = ion_map(ia)
845 safe_deallocate_a(ion_map)
854 class(
mesh_t),
intent(in) :: mesh
858 domain%mesh_mask = domain%box%contains_points(mesh%np, mesh%x)
866 type(
basins_t),
intent(in) :: basins
867 class(
mesh_t),
intent(in) :: mesh
868 type(
ions_t),
intent(in) :: ions
870 integer :: ia, ib, ip, ix, n_basins, rankmin
872 integer,
allocatable :: domain_map(:)
878 do ia = 1, ions%natoms
882 safe_allocate(domain_map(1:n_basins))
887 do ia = 1, ions%natoms
891 domain_map(ib) = basins%map(ix)
897 domain%mesh_mask(ip) = any(domain_map(1:n_basins) == basins%map(ip))
900 safe_deallocate_a(domain_map)
908 logical,
intent(in) :: mesh_mask(:)
909 type(
ions_t),
intent(in) :: ions
910 class(
mesh_t),
intent(in) :: mesh
911 logical,
intent(out) :: ions_mask(:)
914 integer,
allocatable :: mask_tmp(:)
920 safe_allocate(mask_tmp(1:ions%natoms))
923 do ia = 1, ions%natoms
925 if (rankmin /= mesh%mpi_grp%rank) cycle
926 if (mesh_mask(ix)) mask_tmp(ia) = 1
929 call mesh%allreduce(mask_tmp, ions%natoms)
930 ions_mask = mask_tmp == 1
932 safe_deallocate_a(mask_tmp)
subroutine create_basins(namespace, space, mesh, ions, ff, basins)
program oct_local_multipoles
subroutine local_restart_read(space, mesh, ions, nd, loc_domains, restart)
subroutine local_ions_mask(mesh_mask, ions, mesh, ions_mask)
subroutine local_restart_write(namespace, space, mesh, mc, nd, loc_domains)
Write restart files for local domains.
subroutine local_inside_domain(space, mesh, ions, nd, loc_domains, namespace, ff)
subroutine bader_domain_create_mask(domain, basins, mesh, ions)
subroutine local_read_from_block(domain, space, ions, blk, row, namespace)
subroutine local_domains()
Reads a global grid and density and make local domains This is a high-level interface that reads the ...
subroutine local_init(space, mesh, ions, nd, loc_domains)
Initialize local_domain_t variable, allocating variable and reading parameters from input file.
subroutine local_end(domain)
Ending local_domain_t variable, allocating variable and reading parameters from input file.
subroutine box_domain_create_mask(domain, mesh)
subroutine, public basins_init(this, namespace, mesh)
subroutine, public basins_analyze(this, namespace, mesh, f, rho, threshold)
subroutine, public basins_end(this)
Module, implementing a factory for boxes.
integer, parameter, public sphere
integer, parameter, public minimum
integer, parameter, public parallelepiped
integer, parameter, public cylinder
This module handles the calculation mode.
type(calc_mode_par_t), public calc_mode_par
Singleton instance of parallel calculation mode.
integer, parameter, public p_strategy_states
parallelization in states
type(debug_t), save, public debug
real(real64), parameter, public m_two
subroutine, public global_end()
Finalise parser varinfo file, and MPI.
real(real64), parameter, public m_zero
subroutine, public global_init(communicator)
Initialise Octopus.
integer, parameter, public length
subroutine, public dio_function_output(how, dir, fname, namespace, space, mesh, ff, unit, ierr, pos, atoms, grp, root)
Top-level IO routine for functions defined on the mesh.
subroutine, public io_init(defaults)
If the argument defaults is present and set to true, then the routine will not try to read anything f...
subroutine, public io_close(iunit, grp)
subroutine, public io_end()
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
subroutine, public kick_end(kick)
subroutine, public kick_init(kick, namespace, space, kpoints, nspin)
subroutine, public local_write_init(writ, namespace, lab, iter, dt)
subroutine, public local_write_end(writ)
subroutine, public local_write_iter(writ, namespace, space, lab, ions_mask, mesh_mask, mesh, st, hm, ks, ions, ext_partners, kick, iter, l_start, ldoverwrite)
logical function, public loct_isinstringlist(a, s)
This module defines the meshes, which are used in Octopus.
integer function, public mesh_nearest_point(mesh, pos, dmin, rankmin)
Returns the index of the point which is nearest to a given vector position pos.
subroutine, public messages_end()
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
character(len=512), private msg
subroutine, public messages_init(output_dir)
subroutine, public messages_warning(no_lines, all_nodes, namespace)
subroutine, public print_date(str)
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_experimental(name, namespace)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
type(mpi_grp_t), public mpi_world
This module handles the communicators for the various parallelization strategies.
type(namespace_t), public global_namespace
subroutine, public parser_init()
Initialise the Octopus parser.
subroutine, public parser_end()
End the Octopus parser.
integer function, public parse_block(namespace, name, blk, check_varinfo_)
subroutine, public profiling_end(namespace)
subroutine, public profiling_init(namespace)
Create profiling subdirectory.
subroutine, public read_from_default_file(iunit, read_data, spec)
integer, parameter, public restart_undefined
integer, parameter, public restart_type_dump
integer, parameter, public restart_type_load
subroutine, public species_get_long_range_density(species, namespace, space, latt, pos, mesh, rho, sphere_inout, nlr_x)
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
This module defines the unit system, used for input and output.
subroutine, public unit_system_init(namespace)
type(unit_system_t), public units_inp
the units systems for reading and writing
type(unit_t), public unit_one
some special units required for particular quantities
This module is intended to contain simple general-purpose utility functions and procedures.
subroutine, public print_header()
This subroutine prints the logo followed by information about the compilation and the system....
Class implementing a cylinder box. The cylinder axis is always along the first direction defined by t...
class to tell whether a point is inside or outside
Class implementing a parallelepiped box. Currently this is restricted to a rectangular cuboid (all th...
Class implementing a spherical box.
Class implementing a box that is an union other boxes.
Class describing the electron system.
Describes mesh distribution to nodes.
Stores all communicators and groups.