20#include "build_info.h"
35 use,
intrinsic :: iso_fortran_env
69 integer(int64) :: type
72 real(real64) :: line_tol
73 real(real64) :: fire_mass
74 integer :: fire_integrator
75 real(real64) :: tolgrad
78 integer :: what2minimize
82 type(ions_t),
pointer :: ions
83 type(hamiltonian_elec_t),
pointer :: hm
84 type(electrons_t),
pointer :: syst
85 class(mesh_t),
pointer :: mesh
86 type(states_elec_t),
pointer :: st
88 integer :: periodic_dim
90 integer :: fixed_atom = 0
92 real(real64),
allocatable :: cell_force(:, :)
93 logical :: symmetrize = .false.
94 real(real64),
allocatable :: initial_length(:)
95 real(real64),
allocatable :: initial_rlattice(:, :)
96 real(real64),
allocatable :: inv_initial_rlattice(:, :)
97 real(real64) :: pressure =
m_zero
99 logical :: poscar_output = .false.
102 integer :: calculator
103 logical :: ml_preopt = .false.
106 type(geom_opt_t),
save :: g_opt
108 integer,
parameter :: &
109 MINWHAT_ENERGY = 1, &
112 integer,
parameter :: &
117 integer,
parameter :: &
118 GO_CALCULATOR_INTERNAL = 1, &
124 subroutine mattersim_paths(mattersim_share, mattersim_python, namespace)
125 character(len=*),
intent(out) :: mattersim_share, mattersim_python
126 type(namespace_t),
intent(in) :: namespace
128 logical :: python_exists
132 mattersim_share = trim(
conf%share)
133 mattersim_python = trim(mattersim_share) //
"/mattersim_env/bin/python"
134 inquire(file=trim(mattersim_python), exist=python_exists)
135 if (python_exists)
return
137 mattersim_share = share_dir
138 mattersim_python = trim(mattersim_share) //
"/mattersim_env/bin/python"
139 inquire(file=trim(mattersim_python), exist=python_exists)
140 if (python_exists)
return
142 message(1) =
'Unable to find the MatterSim Python environment.'
143 message(2) =
'Please install Octopus with MatterSim support before using the MatterSim calculator.'
149 class(*),
intent(inout) :: system
150 logical,
intent(inout) :: from_scratch
156 message(1) =
"CalculationMode = go not implemented for multi-system calculations"
168 logical,
intent(inout) :: fromscratch
171 real(real64),
allocatable :: coords(:)
172 real(real64) :: energy
174 real(real64),
allocatable :: mass(:)
175 integer :: iatom, imass
177 logical :: known_lower_bound
178 logical :: default_val
184 if (sys%space%periodic_dim == 1)
then
185 message(1) =
"Geometry optimization is not allowed for systems periodic in 1D, "
186 message(2) =
"as the ion-ion interaction and the stress tensor are not available."
190 if (sys%space%periodic_dim == 2)
then
195 if (sys%hm%pcm%run_pcm)
then
199 if (sys%kpoints%use_symmetries)
then
203 g_opt%symmetrize = sys%kpoints%use_symmetries .or. sys%st%symmetrize_density
205 call init_(fromscratch)
208 if (.not. fromscratch)
then
211 call states_elec_load(restart_load, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
212 fixed_occ=.false., ierr=ierr)
214 call restart_load%end()
216 message(1) =
"Unable to read wavefunctions: Starting from scratch."
222 call scf_init(g_opt%scfv, sys%namespace, sys%gr, sys%ions, sys%st, sys%mc, sys%hm, sys%space)
225 if (.not. g_opt%scfv%calc_stress)
then
226 message(1) =
"In order to optimize the cell, one needs to set SCFCalculateStress = yes."
231 if (fromscratch)
then
232 call lcao_run(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm, &
233 lmm_r = g_opt%scfv%lmm_r, known_lower_bound=known_lower_bound)
237 message(1) =
'Info: Setting up Hamiltonian.'
239 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
244 safe_allocate(coords(1:g_opt%size))
247 if (sys%st%pack_states .and. sys%hm%apply_packed())
call sys%st%pack()
250 select case (g_opt%method)
252 call minimize_multidim_nograd(g_opt%method, g_opt%size, coords, g_opt%step,&
253 g_opt%toldr, g_opt%max_iter, &
258 safe_allocate(mass(1:g_opt%size))
259 mass = g_opt%fire_mass
261 do iatom = 1, sys%ions%natoms
262 if (g_opt%fixed_atom == iatom) cycle
263 if (g_opt%ions%fixed(iatom)) cycle
264 if (g_opt%fire_mass <=
m_zero) mass(imass:imass + 2) = sys%ions%mass(iatom)
265 imass = imass + g_opt%dim
269 call minimize_fire(g_opt%size, g_opt%ions%space%dim, coords, g_opt%step, g_opt%tolgrad, &
272 safe_deallocate_a(mass)
275 call minimize_multidim(g_opt%method, g_opt%size, coords, g_opt%step ,&
276 g_opt%line_tol , g_opt%tolgrad, g_opt%toldr, g_opt%max_iter, &
281 if (ierr == 1025)
then
283 message(1) =
"Reached maximum number of iterations allowed by GOMaxIter."
286 message(1) =
"Error occurred during the GSL minimization procedure:"
291 if (sys%st%pack_states .and. sys%hm%apply_packed())
call sys%st%unpack()
295 message(1) =
"Writing final coordinates to min.xyz"
298 call g_opt%ions%write_xyz(
'./min')
300 safe_deallocate_a(coords)
303 call g_opt%scfv%criterion_list%empty()
310 subroutine init_(fromscratch)
311 logical,
intent(inout) :: fromscratch
313 logical :: center, does_exist
314 integer :: iter, iatom, idir
315 character(len=100) :: filename
316 real(real64) :: default_toldr
317 real(real64) :: default_step
322 if (sys%space%is_periodic())
then
350 write(
message(1),
'(a)')
'Input: [GOType = '
351 if (
bitand(g_opt%type, go_ions) /= 0)
then
355 if (len_trim(
message(1)) > 16)
then
361 if (len_trim(
message(1)) > 16)
then
370 message(1) =
"Cell and volume optimization cannot be used simultaneously."
382 do iatom = 1, sys%ions%natoms
383 select type(spec=>sys%ions%atom(iatom)%species)
385 write(
message(1),
'(a)')
"Geometry optimization for all-electron potential is not implemented."
395 g_opt%ions => sys%ions
399 g_opt%dim = sys%space%dim
400 g_opt%periodic_dim = sys%space%periodic_dim
404 if (
bitand(g_opt%type, go_ions) /= 0)
then
405 g_opt%size = g_opt%dim * g_opt%ions%natoms
410 g_opt%size = g_opt%size + (g_opt%periodic_dim +1) * g_opt%periodic_dim / 2
411 safe_allocate(g_opt%cell_force(1:g_opt%periodic_dim, 1:g_opt%periodic_dim))
416 g_opt%size = g_opt%size + g_opt%periodic_dim
417 safe_allocate(g_opt%cell_force(1:g_opt%periodic_dim, 1:1))
419 safe_allocate(g_opt%initial_length(1:g_opt%periodic_dim))
420 do idir = 1, g_opt%periodic_dim
421 g_opt%initial_length(idir) = norm2(g_opt%ions%latt%rlattice(1:g_opt%periodic_dim, idir))
427 safe_allocate(g_opt%initial_rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim))
428 g_opt%initial_rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim) &
429 = g_opt%ions%latt%rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim)
430 safe_allocate(g_opt%inv_initial_rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim))
431 g_opt%inv_initial_rlattice(:, :) = g_opt%initial_rlattice(:, :)
432 call lalg_inverse(g_opt%periodic_dim, g_opt%inv_initial_rlattice,
'dir')
435 if(g_opt%ions%space%is_periodic())
then
451 if (center .and.
bitand(g_opt%type, go_ions) /= 0)
then
453 g_opt%size = g_opt%size - g_opt%dim
458 do iatom = 1, g_opt%ions%natoms
459 if (g_opt%ions%fixed(iatom) .and.
bitand(g_opt%type, go_ions) /= 0)
then
460 g_opt%size = g_opt%size - g_opt%dim
464 assert(g_opt%size > 0)
540 default_toldr = 0.001_real64
542 default_toldr = -
m_one
559 call parse_variable(sys%namespace,
'GOStep', default_step, g_opt%step)
574 call parse_variable(sys%namespace,
'GOLineTol', 0.1_real64, g_opt%line_tol)
584 call parse_variable(sys%namespace,
'GOMaxIter', 200, g_opt%max_iter)
585 if (g_opt%max_iter <= 0)
then
586 message(1) =
"GOMaxIter has to be larger than 0"
623 call parse_variable(sys%namespace,
'GOFireIntegrator', option__gofireintegrator__verlet, g_opt%fire_integrator)
644 call parse_variable(sys%namespace,
'GOObjective', minwhat_energy, g_opt%what2minimize)
705 if (g_opt%ions%natoms /= xyz%n)
then
706 write(
message(1),
'(a,i4,a,i4)')
'I need exactly ', g_opt%ions%natoms,
' constrains, but I found ', xyz%n
710 do iatom = 1, g_opt%ions%natoms
711 where(abs(xyz%atom(iatom)%x) <=
m_epsilon)
712 g_opt%ions%atom(iatom)%c =
m_zero
714 g_opt%ions%atom(iatom)%c =
m_one
721 if (g_opt%fixed_atom > 0)
then
725 do iatom = 1, g_opt%ions%natoms
726 g_opt%ions%atom(iatom)%c =
m_zero
745 call parse_variable(sys%namespace,
'GOCalculator', go_calculator_internal, g_opt%calculator)
749#ifndef HAVE_MATTERSIM
751 message(1) =
'Octopus was not compiled with support for MatterSim'
774 if (sys%space%periodic_dim /= 3 .and. &
777 default_val = .false.
779 call parse_variable(sys%namespace,
'GOMLPreoptimize', default_val, g_opt%ml_preopt)
780#ifndef HAVE_MATTERSIM
781 if (g_opt%ml_preopt)
then
782 message(1) =
'Octopus was not compiled with support for MatterSim'
787 call io_mkdir(
'geom', sys%namespace)
789 if (g_opt%ml_preopt)
then
794 call io_rm(
"geom/optimization.log", sys%namespace)
796 call io_rm(
"work-geom.xyz", sys%namespace)
798 if (.not. fromscratch)
then
799 inquire(file =
'./last.xyz', exist = does_exist)
800 if (.not. does_exist) fromscratch = .
true.
803 if (.not. fromscratch)
call g_opt%ions%read_xyz(
'./last')
808 write(filename,
'(a,i4.4,a)')
"geom/go.", iter,
".xyz"
809 inquire(file = trim(filename), exist = does_exist)
811 call io_rm(trim(filename), sys%namespace)
812 if (sys%space%periodic_dim > 0)
then
813 write(filename,
'(a,i4.4,a)')
"geom/go.", iter,
".xyz_red"
814 call io_rm(trim(filename), sys%namespace)
815 write(filename,
'(a,i4.4,a)')
"geom/go.", iter,
".xsf"
816 call io_rm(trim(filename), sys%namespace)
837 call g_opt%scfv%restart_dump%end()
845 safe_deallocate_a(g_opt%cell_force)
856 subroutine calc_point(size, coords, objective, getgrad, df)
857 integer,
intent(in) :: size
858 real(real64),
intent(in) :: coords(size)
859 real(real64),
intent(inout) :: objective
860 integer,
intent(in) :: getgrad
861 real(real64),
intent(inout) :: df(size)
863 integer :: iatom, idir, jdir, iunit, command_status, command_exit
864 real(real64),
dimension(g_opt%periodic_dim, g_opt%periodic_dim) :: stress, strain, right_stretch, inv_right_stretch, &
867 character(len=MAX_PATH_LEN) :: cmd, mattersim_share, mattersim_python
871 assert(
size == g_opt%size)
881 if (g_opt%fixed_atom /= 0)
then
882 call g_opt%ions%translate(g_opt%ions%center())
887 call g_opt%ions%fold_atoms_into_cell()
890 do iatom = 1, g_opt%ions%natoms
891 if (.not. g_opt%syst%gr%box%contains_point(g_opt%ions%pos(:, iatom)))
then
892 if (g_opt%syst%space%periodic_dim /= g_opt%syst%space%dim)
then
896 write(
message(1),
'(a,i5,a)')
"Atom ", iatom,
" has moved outside the box during the geometry optimization."
902 if (g_opt%calculator==go_calculator_internal)
then
903 call g_opt%ions%write_xyz(
'./work-geom', append = .
true.)
905 if (g_opt%ions%space%is_periodic())
then
906 call write_extended_xyz_file(
'.',
'work-geom', g_opt%ions%space, g_opt%ions%latt, g_opt%ions%pos, g_opt%ions%atom, &
907 g_opt%syst%gr%box, g_opt%syst%namespace)
909 call g_opt%ions%write_xyz(
'./work-geom', append = .false.)
916 g_opt%syst%space, g_opt%syst%hm%psolver, g_opt%syst%hm%kpoints, &
917 g_opt%syst%mc, g_opt%syst%st%qtot, g_opt%ions%latt)
921 if (g_opt%ions%force_total_enforce)
then
928 select case (g_opt%calculator)
929 case (go_calculator_internal)
933 g_opt%ions, g_opt%syst%ext_partners, g_opt%st)
934 call density_calc(g_opt%st, g_opt%syst%gr, g_opt%st%rho, &
935 ep = g_opt%hm%ep, vnl = g_opt%hm%uspp_overlap, phase = g_opt%hm%phase)
936 call v_ks_calc(g_opt%syst%ks, g_opt%syst%namespace, g_opt%syst%space, g_opt%hm, g_opt%st, &
937 g_opt%ions,g_opt%syst%ext_partners, calc_eigenval = .
true.)
938 call energy_calc_total(g_opt%syst%namespace, g_opt%syst%space, g_opt%hm, g_opt%syst%gr, g_opt%st, g_opt%syst%ext_partners)
941 call scf_run(g_opt%scfv, g_opt%syst%namespace, g_opt%syst%space, g_opt%syst%mc, g_opt%syst%gr, &
942 g_opt%ions, g_opt%syst%ext_partners, &
943 g_opt%st, g_opt%syst%ks, g_opt%hm, outp = g_opt%syst%outp, verbosity =
verb_compact, restart_dump=g_opt%scfv%restart_dump)
948 call mattersim_paths(mattersim_share, mattersim_python, g_opt%syst%namespace)
952 cmd = trim(mattersim_python) //
" -I " // trim(mattersim_share) &
953 //
"/scripts/run_mattersim.py work-geom.xyz ml_forces.xyz " // trim(mattersim_share)
954 call execute_command_line(trim(cmd), exitstat=command_exit, cmdstat=command_status)
955 if (command_status == 0) command_status = command_exit
957 call mpi_world%bcast(command_status, 1, mpi_integer, 0)
958 if (command_status /= 0)
then
959 write(
message(1),
'(a,i0)')
'MatterSim force calculation failed with exit status ', command_status
966 read(iunit, *) g_opt%hm%energy%total
967 do iatom = 1, g_opt%ions%natoms
968 read(iunit,*) g_opt%ions%tot_force(:, iatom)
973 read(iunit,*) g_opt%syst%st%stress_tensors%total(:, idir)
990 stress = -g_opt%syst%st%stress_tensors%total(1:g_opt%periodic_dim, 1:g_opt%periodic_dim)
994 strain = matmul(g_opt%ions%latt%rlattice(1:g_opt%periodic_dim,1:g_opt%periodic_dim), g_opt%inv_initial_rlattice)
996 inv_right_stretch = right_stretch
997 call lalg_inverse(g_opt%periodic_dim, inv_right_stretch,
'dir')
998 rotation = matmul(strain, inv_right_stretch)
1003 sym_stress = matmul(transpose(rotation), matmul(stress, rotation))
1004 sym_stress =
m_half*(sym_stress + transpose(sym_stress)) * det
1008 do idir = 1, g_opt%periodic_dim
1009 sym_stress(idir, idir) = sym_stress(idir, idir) - g_opt%pressure
1011 g_opt%cell_force = sym_stress * g_opt%ions%latt%rcell_volume
1013 g_opt%cell_force = matmul(g_opt%cell_force, inv_right_stretch)
1016 g_opt%cell_force =
m_half*(g_opt%cell_force + transpose(g_opt%cell_force))
1021 stress = g_opt%syst%st%stress_tensors%total(1:g_opt%periodic_dim, 1:g_opt%periodic_dim)
1022 do idir = 1, g_opt%periodic_dim
1023 g_opt%cell_force(idir, 1) = -(g_opt%pressure + stress(idir, idir)) * g_opt%ions%latt%rcell_volume
1029 do idir = 1, g_opt%periodic_dim
1031 jdir = 1, g_opt%periodic_dim)
1033 call messages_info(1+g_opt%periodic_dim, namespace=g_opt%ions%namespace, debug_only=.
true.)
1035 do idir = 1, ubound(g_opt%cell_force, 2)
1037 jdir = 1, g_opt%periodic_dim)
1039 call messages_info(1+g_opt%periodic_dim, namespace=g_opt%ions%namespace, debug_only=.
true.)
1044 if (getgrad == 1)
call to_grad(g_opt, df)
1048 do iatom = 1, g_opt%ions%natoms
1049 if (g_opt%ions%fixed(iatom)) cycle
1050 objective = objective + sum(g_opt%ions%tot_force(:, iatom)**2)
1053 do idir = 1, g_opt%periodic_dim
1054 objective = objective + sum(g_opt%cell_force(:, idir)**2)
1058 objective = objective + sum(g_opt%cell_force(:,1)**2)
1060 objective =
sqrt(objective)
1062 objective = g_opt%hm%energy%total
1076 real(real64) :: coords(size)
1077 real(real64) :: objective
1080 real(real64),
allocatable :: df(:)
1084 assert(
size == g_opt%size)
1087 safe_allocate(df(1:size))
1090 call calc_point(
size, coords, objective, getgrad, df)
1091 safe_deallocate_a(df)
1099 subroutine write_iter_info(geom_iter, size, energy, maxdx, maxdf, coords)
1100 integer,
intent(in) :: geom_iter
1101 integer,
intent(in) :: size
1102 real(real64),
intent(in) :: energy, maxdx, maxdf
1103 real(real64),
intent(in) :: coords(size)
1105 character(len=256) :: c_geom_iter, title, c_forces_iter
1110 write(c_geom_iter,
'(a,i4.4)')
"go.", geom_iter
1112 call g_opt%ions%write_xyz(
'geom/'//trim(c_geom_iter), comment = trim(title))
1113 call g_opt%ions%write_xyz(
'./last')
1115 if(g_opt%periodic_dim > 0)
then
1116 call g_opt%ions%write_xyz(
'geom/'//trim(c_geom_iter), comment =
'Reduced coordinates', reduce_coordinates = .
true.)
1118 g_opt%ions%pos, g_opt%ions%atom, g_opt%syst%gr, g_opt%ions%grp, g_opt%syst%namespace)
1121 if (g_opt%syst%outp%what(option__output__forces))
then
1122 write(c_forces_iter,
'(a,i4.4)')
"forces.", geom_iter
1123 if (
bitand(g_opt%syst%outp%how(option__output__forces), option__outputformat__bild) /= 0)
then
1124 call g_opt%ions%write_bild_forces_file(
'forces', trim(c_forces_iter))
1127 g_opt%ions%pos, g_opt%ions%atom, g_opt%syst%gr, g_opt%ions%grp, g_opt%syst%namespace, &
1128 total_forces=g_opt%ions%tot_force)
1132 if (g_opt%ions%grp%is_root())
then
1133 iunit =
io_open(trim(
'geom/optimization.log'), g_opt%syst%namespace, &
1134 action =
'write', position =
'append')
1136 if (geom_iter == 1)
then
1138 write(iunit,
'(a10,5(5x,a20),a)')
'# iter',
'energy [' // trim(
units_abbrev(
units_out%energy)) //
']', &
1143 ' alpha, beta, gamma [degrees]'
1145 write(iunit,
'(a10,3(5x,a20))')
'# iter',
'energy [' // trim(
units_abbrev(
units_out%energy)) //
']', &
1159 g_opt%ions%latt%alpha, g_opt%ions%latt%beta, g_opt%ions%latt%gamma
1172 call messages_write(
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", new_line = .
true.)
1174 call messages_write(
"+++++++++++++++++++++ MINIMIZATION ITER #:")
1181 if (g_opt%periodic_dim == 0)
then
1192 call messages_write(maxdf, fmt =
"f16.10,1x", print_units = .false., new_line = .
true.)
1196 call messages_write(maxdx, fmt =
"f16.10,1x", print_units = .false., new_line = .
true.)
1199 call messages_write(
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", new_line = .
true.)
1200 call messages_write(
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", new_line = .
true.)
1212 real(real64),
contiguous,
intent(out) :: coords(:)
1214 integer :: iatom, idir, jdir, icoord
1215 real(real64) :: tmp_pos(gopt%dim), strain(g_opt%periodic_dim,g_opt%periodic_dim)
1221 if (
bitand(g_opt%type, go_ions) /= 0)
then
1222 do iatom = 1, gopt%ions%natoms
1223 if (gopt%fixed_atom == iatom) cycle
1224 if (gopt%ions%fixed(iatom)) cycle
1225 tmp_pos = gopt%ions%pos(1:gopt%dim, iatom)
1226 if (gopt%fixed_atom > 0) tmp_pos = tmp_pos - gopt%ions%pos(1:gopt%dim, gopt%fixed_atom)
1227 tmp_pos = gopt%ions%latt%cart_to_red(tmp_pos)
1228 do idir = 1, gopt%dim
1229 coords(icoord) = tmp_pos(idir)
1240 strain = matmul(gopt%ions%latt%rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim), g_opt%inv_initial_rlattice)
1241 do idir = 1, g_opt%periodic_dim
1242 do jdir = idir, g_opt%periodic_dim
1243 coords(icoord) = strain(idir, jdir)
1251 do idir = 1, g_opt%periodic_dim
1252 coords(icoord) = norm2(gopt%ions%latt%rlattice(1:g_opt%periodic_dim, idir))/g_opt%initial_length(idir)
1263 subroutine to_grad(gopt, grad)
1265 real(real64),
contiguous,
intent(out) :: grad(:)
1267 integer :: iatom, idir, jdir, icoord
1268 real(real64) :: tmp_force(1:gopt%dim)
1274 if (
bitand(g_opt%type, go_ions) /= 0)
then
1275 do iatom = 1, gopt%ions%natoms
1276 if (gopt%fixed_atom == iatom) cycle
1277 if (gopt%ions%fixed(iatom)) cycle
1278 do idir = 1, gopt%dim
1279 if (abs(gopt%ions%atom(iatom)%c(idir)) <=
m_epsilon)
then
1280 tmp_force(idir) = -gopt%ions%tot_force(idir, iatom)
1284 if (gopt%fixed_atom > 0)
then
1285 tmp_force(idir) = tmp_force(idir) + gopt%ions%tot_force(idir, gopt%fixed_atom)
1288 tmp_force = gopt%ions%latt%cart_to_red(tmp_force)
1289 do idir = 1, gopt%dim
1290 grad(icoord) = tmp_force(idir)
1298 do idir = 1, g_opt%periodic_dim
1299 do jdir = idir, g_opt%periodic_dim
1300 grad(icoord) = -g_opt%cell_force(idir, jdir)
1308 do idir = 1, g_opt%periodic_dim
1309 grad(icoord) = -g_opt%cell_force(idir, 1)
1322 real(real64),
contiguous,
intent(in) :: coords(:)
1324 integer :: iatom, idir, jdir, icoord
1325 real(real64) :: tmp_pos(gopt%dim, gopt%ions%natoms), strain(g_opt%periodic_dim,g_opt%periodic_dim)
1326 real(real64) :: eigenvalues(g_opt%periodic_dim)
1334 if (
bitand(g_opt%type, go_ions) /= 0)
then
1335 do iatom = 1, gopt%ions%natoms
1336 if (gopt%fixed_atom == iatom) cycle
1337 if (gopt%ions%fixed(iatom)) cycle
1338 do idir = 1, gopt%dim
1339 tmp_pos(idir, iatom) = coords(icoord)
1344 do iatom = 1, gopt%ions%natoms
1345 tmp_pos(:, iatom) = gopt%ions%latt%cart_to_red(gopt%ions%pos(:, iatom))
1351 do idir = 1, g_opt%periodic_dim
1352 do jdir = idir, g_opt%periodic_dim
1353 strain(idir, jdir) = coords(icoord)
1364 gopt%ions%latt%rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim) = matmul(strain, g_opt%initial_rlattice)
1370 assert(all(eigenvalues >
m_zero))
1375 do idir = 1, g_opt%periodic_dim
1376 gopt%ions%latt%rlattice(1:g_opt%periodic_dim, idir) = coords(icoord) &
1377 * gopt%initial_rlattice(1:g_opt%periodic_dim, idir)
1384 call g_opt%syst%gr%symmetrizer%symmetrize_lattice_vectors(g_opt%periodic_dim, g_opt%initial_rlattice, &
1385 gopt%ions%latt%rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim), gopt%symmetrize)
1386 call gopt%ions%update_lattice_vectors(gopt%ions%latt, gopt%symmetrize)
1390 if (
bitand(g_opt%type, go_ions) /= 0)
then
1392 do iatom = 1, gopt%ions%natoms
1393 if (gopt%fixed_atom == iatom) cycle
1394 if (gopt%ions%fixed(iatom)) cycle
1395 tmp_pos(:, iatom) = gopt%ions%latt%red_to_cart(tmp_pos(:, iatom))
1396 do idir = 1, gopt%dim
1397 if (abs(gopt%ions%atom(iatom)%c(idir)) <=
m_epsilon)
then
1398 gopt%ions%pos(idir, iatom) = tmp_pos(idir, iatom)
1401 if (gopt%fixed_atom > 0)
then
1402 gopt%ions%pos(:, iatom) = gopt%ions%pos(:, iatom) + gopt%ions%pos(:, gopt%fixed_atom)
1406 do iatom = 1, gopt%ions%natoms
1407 gopt%ions%pos(:, iatom) = gopt%ions%latt%red_to_cart(tmp_pos(:, iatom))
1411 if (gopt%symmetrize)
then
1412 call gopt%ions%symmetrize_atomic_coord()
1416 call gopt%ions%print_spacegroup()
1425 integer,
intent(in) :: geom_iter
1426 integer,
intent(in) :: size
1427 real(real64),
intent(in) :: energy, maxdx
1428 real(real64),
intent(in) :: coords(size)
1442 integer :: iunit, iatom, idir, command_status, command_exit
1443 logical :: has_constrains
1444 character(len=MAX_PATH_LEN) :: cmd, mattersim_share, mattersim_python
1445 character(len=64) :: constrains_arg
1451 call io_rm(
'ml_cell.xyz', g_opt%syst%namespace)
1453 if (g_opt%ions%space%is_periodic())
then
1454 call write_extended_xyz_file(
'.',
'work-geom', g_opt%ions%space, g_opt%ions%latt, g_opt%ions%pos, g_opt%ions%atom, &
1455 g_opt%syst%gr%box, g_opt%syst%namespace)
1457 call g_opt%ions%write_xyz(
'./work-geom', append = .false.)
1462 has_constrains = any(g_opt%ions%fixed) .or. g_opt%fixed_atom > 0
1463 do iatom = 1, g_opt%ions%natoms
1464 has_constrains = has_constrains .or. any(g_opt%ions%atom(iatom)%c /= 0)
1468 if (has_constrains)
then
1469 constrains_arg =
' --constrains ml_constrains.dat'
1472 do iatom = 1, g_opt%ions%natoms
1473 if (g_opt%ions%fixed(iatom) .or. iatom == g_opt%fixed_atom)
then
1474 write(iunit,
'(3(1x,i1))') (1, idir = 1, g_opt%ions%space%dim)
1476 write(iunit,
'(3(1x,i1))') (g_opt%ions%atom(iatom)%c(idir), idir = 1, g_opt%ions%space%dim)
1483 call mattersim_paths(mattersim_share, mattersim_python, g_opt%syst%namespace)
1487 write(cmd,
'(a,1x,es24.16,1x,i0,1x,l1,a)') &
1488 trim(mattersim_python) //
" -I " // trim(mattersim_share) &
1489 //
"/scripts/run_mattersim_preopt.py work-geom.xyz ml_cell.xyz " // trim(mattersim_share), &
1490 g_opt%pressure, g_opt%type, g_opt%symmetrize, trim(constrains_arg)
1491 call execute_command_line(trim(cmd), exitstat=command_exit, cmdstat=command_status)
1492 if (command_status == 0) command_status = command_exit
1495 call mpi_world%bcast(command_status, 1, mpi_integer, 0)
1496 if (command_status /= 0)
then
1497 write(
message(1),
'(a,i0)')
'MatterSim pre-optimization failed with exit status ', command_status
1505 do iatom = 1, g_opt%ions%natoms
1506 read(iunit,*) g_opt%ions%pos(:, iatom)
1511 read(iunit,*) g_opt%ions%latt%rlattice(:, idir)
1516 call g_opt%ions%update_lattice_vectors(g_opt%ions%latt, g_opt%symmetrize)
1518 if (
debug%info)
then
1519 call g_opt%ions%print_spacegroup()
1522 call g_opt%ions%fold_atoms_into_cell()
1527 g_opt%syst%space, g_opt%syst%hm%psolver, g_opt%syst%hm%kpoints, &
1528 g_opt%syst%mc, g_opt%syst%st%qtot, g_opt%ions%latt)
1532 g_opt%ions, g_opt%syst%ext_partners, g_opt%st)
1534 call g_opt%ions%print_spacegroup()
subroutine init_(fromscratch)
Note that lalg_determinant and lalg_inverse are just wrappers over the same routine.
type(debug_t), save, public debug
This module implements a calculator for the density and defines related functions.
subroutine, public density_calc(st, gr, density, istin, ep, vnl, phase)
Computes the density from the orbitals in st.
subroutine, public energy_calc_total(namespace, space, hm, gr, st, ext_partners, iunit, full)
This subroutine calculates the total energy of the system. Basically, it adds up the KS eigenvalues,...
subroutine, public forces_set_total_to_zero(ions, force)
subroutine, public geom_opt_run(system, from_scratch)
integer, parameter go_calculator_mattersim
subroutine calc_point_ng(size, coords, objective)
Same as calc_point, but without the gradients. No intents here is unfortunately required because the ...
subroutine to_grad(gopt, grad)
Transfer data from the forces to the work array for the gradients (grad)
integer, parameter go_cell
integer, parameter minwhat_forces
subroutine write_iter_info_ng(geom_iter, size, energy, maxdx, coords)
Same as write_iter_info, but without the gradients.
subroutine ml_preopt(g_opt)
Calls a python script to do a pre-optimization based on machine-learned interatomic potential.
subroutine write_iter_info(geom_iter, size, energy, maxdx, maxdf, coords)
Output the information after each iteration of the geometry optimization.
subroutine calc_point(size, coords, objective, getgrad, df)
Note: you might think it would be better to change the arguments with '(size)' below to '(:)'....
subroutine to_coords(gopt, coords)
Transfer the data from the data structures to the work array (coords)
integer, parameter go_volume
subroutine from_coords(gopt, coords)
Transfer the data from the work array (coords) to the actual data structures.
subroutine geom_opt_run_legacy(sys, fromscratch)
subroutine mattersim_paths(mattersim_share, mattersim_python, namespace)
real(real64), parameter, public m_zero
real(real64), parameter, public m_epsilon
type(conf_t), public conf
Global instance of Octopus configuration.
real(real64), parameter, public m_half
real(real64), parameter, public m_one
subroutine, public hamiltonian_elec_epot_generate(this, namespace, space, gr, ions, ext_partners, st, time)
subroutine, public write_extended_xyz_file(dir, fname, space, latt, pos, atoms, box, namespace)
Write an extended xyz file compatible with ASE.
subroutine, public write_xsf_geometry_file(dir, fname, space, latt, pos, atoms, mesh, mpi_grp, namespace, total_forces)
subroutine, public io_close(iunit, grp)
subroutine, public io_rm(fname, namespace)
subroutine, public io_mkdir(fname, namespace, parents)
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
subroutine, public electrons_lattice_vectors_update(namespace, gr, space, psolver, kpoints, mc, qtot, new_latt)
subroutine, public ion_dynamics_box_update(namespace, gr, space, new_latt)
real(real64) function, dimension(1:n, 1:n), public lalg_remove_rotation(n, A)
Remove rotation from affine transformation A by computing the polar decomposition and discarding the ...
subroutine, public lcao_run(namespace, space, gr, ions, ext_partners, st, ks, hm, st_start, lmm_r, known_lower_bound)
System information (time, memory, sysname)
subroutine, public loct_strerror(errno, res)
This module is intended to contain "only mathematical" functions and procedures.
This module defines the meshes, which are used in Octopus.
subroutine, public messages_not_implemented(feature, namespace)
subroutine, public messages_warning(no_lines, all_nodes, namespace)
subroutine, public messages_obsolete_variable(namespace, name, rep)
subroutine, public messages_new_line()
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)
integer, parameter, public minmethod_nmsimplex
integer, parameter, public minmethod_fire
type(mpi_grp_t), public mpi_world
This module implements the basic mulsisystem class, a container system for other systems.
type(namespace_t), public global_namespace
logical function, public parse_is_defined(namespace, name)
/* To use the profiling module, call profiling_in and profiling_out with the label of the region as a...
integer, parameter, public read_coords_err
for read_coords_info::file_type
subroutine, public read_coords_init(gf)
subroutine, public read_coords_end(gf)
subroutine, public read_coords_read(what, gf, space, namespace)
integer, parameter, public restart_gs
integer, parameter, public restart_type_dump
integer, parameter, public restart_type_load
subroutine, public scf_set_lower_bound_is_known(scf, known_lower_bound)
Set the flag lower_bound_is_known.
subroutine, public scf_print_mem_use(namespace)
subroutine, public scf_mix_clear(scf)
integer, parameter, public verb_compact
subroutine, public scf_init(scf, namespace, gr, ions, st, mc, hm, space)
subroutine, public scf_end(scf)
subroutine, public scf_run(scf, namespace, space, mc, gr, ions, ext_partners, st, ks, hm, outp, verbosity, iters_done, restart_dump)
Legacy version of the SCF code.
subroutine, public states_elec_deallocate_wfns(st)
Deallocates the KS wavefunctions defined within a states_elec_t structure.
subroutine, public states_elec_allocate_wfns(st, mesh, wfs_type, skip, packed)
Allocates the KS wavefunctions defined within a states_elec_t structure.
This module handles reading and writing restart information for the states_elec_t.
subroutine, public states_elec_load(restart, namespace, space, st, mesh, kpoints, fixed_occ, ierr, iter, lr, lowest_missing, label, verbose, skip)
returns in ierr: <0 => Fatal error, or nothing read =0 => read all wavefunctions >0 => could only rea...
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_t), public unit_femtosecond
Time in femtoseconds.
type(unit_t), public unit_amu
Mass in atomic mass units (AKA Dalton).
type(unit_system_t), public units_out
type(unit_system_t), public units_inp
the units systems for reading and writing
subroutine, public v_ks_calc(ks, namespace, space, hm, st, ions, ext_partners, calc_eigenval, time, calc_energy, calc_current, force_semilocal)
subroutine, public v_ks_h_setup(namespace, space, gr, ions, ext_partners, st, ks, hm, calc_eigenval, calc_current)
An abstract type for all electron species.
Class describing the electron system.
Container class for lists of system_oct_m::system_t.