Octopus
geom_opt.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2007 M. Marques, A. Castro, A. Rubio, G. Bertsch, M. Oliveira
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21module geom_opt_oct_m
23 use debug_oct_m
27 use forces_oct_m
28 use global_oct_m
30 use io_oct_m
33 use ions_oct_m
34 use, intrinsic :: iso_fortran_env
36 use lcao_oct_m
37 use loct_oct_m
38 use math_oct_m
39 use mesh_oct_m
42 use mpi_oct_m
45 use parser_oct_m
46 use pcm_oct_m
50 use scf_oct_m
56 use unit_oct_m
58 use v_ks_oct_m
60
61 implicit none
62
63 private
64 public :: geom_opt_run
65
66 type geom_opt_t
67 private
68 integer(int64) :: type
69 integer :: method
70 real(real64) :: step
71 real(real64) :: line_tol
72 real(real64) :: fire_mass
73 integer :: fire_integrator
74 real(real64) :: tolgrad
75 real(real64) :: toldr
76 integer :: max_iter
77 integer :: what2minimize
78
80 type(scf_t) :: scfv
81 type(ions_t), pointer :: ions
82 type(hamiltonian_elec_t), pointer :: hm
83 type(electrons_t), pointer :: syst
84 class(mesh_t), pointer :: mesh
85 type(states_elec_t), pointer :: st
86 integer :: dim
87 integer :: periodic_dim
88 integer :: size
89 integer :: fixed_atom = 0
90
91 real(real64), allocatable :: cell_force(:, :)
92 logical :: symmetrize = .false.
93 real(real64), allocatable :: initial_length(:)
94 real(real64), allocatable :: initial_rlattice(:, :)
95 real(real64), allocatable :: inv_initial_rlattice(:, :)
96 real(real64) :: pressure = m_zero
97
98 logical :: poscar_output = .false.
99
101 integer :: calculator
102 logical :: ml_preopt = .false.
103 end type geom_opt_t
104
105 type(geom_opt_t), save :: g_opt
106
107 integer, parameter :: &
108 MINWHAT_ENERGY = 1, &
110
111 integer, parameter :: &
112 GO_IONS = 1, &
113 go_cell = 2, &
114 go_volume = 4
115
116 integer, parameter :: &
117 GO_CALCULATOR_INTERNAL = 1, &
119
120contains
121
122 ! ---------------------------------------------------------
123 subroutine mattersim_paths(mattersim_share, mattersim_python, namespace)
124 character(len=*), intent(out) :: mattersim_share, mattersim_python
125 type(namespace_t), intent(in) :: namespace
126
127 logical :: python_exists
128
129 ! In build-tree runs conf%share points to build/share, but the
130 ! MatterSim virtual environment is created when installing Octopus.
131 mattersim_share = trim(conf%share)
132 mattersim_python = trim(mattersim_share) // "/mattersim_env/bin/python"
133 inquire(file=trim(mattersim_python), exist=python_exists)
134 if (python_exists) return
135
136 mattersim_share = share_dir
137 mattersim_python = trim(mattersim_share) // "/mattersim_env/bin/python"
138 inquire(file=trim(mattersim_python), exist=python_exists)
139 if (python_exists) return
140
141 message(1) = 'Unable to find the MatterSim Python environment.'
142 message(2) = 'Please install Octopus with MatterSim support before using the MatterSim calculator.'
143 call messages_fatal(2, namespace=namespace)
144 end subroutine mattersim_paths
145
146 ! ---------------------------------------------------------
147 subroutine geom_opt_run(system, from_scratch)
148 class(*), intent(inout) :: system
149 logical, intent(inout) :: from_scratch
150
151 push_sub(geom_opt_run)
152
153 select type (system)
154 class is (multisystem_basic_t)
155 message(1) = "CalculationMode = go not implemented for multi-system calculations"
156 call messages_fatal(1, namespace=system%namespace)
157 type is (electrons_t)
158 call geom_opt_run_legacy(system, from_scratch)
159 end select
160
162 end subroutine geom_opt_run
164 ! ---------------------------------------------------------
165 subroutine geom_opt_run_legacy(sys, fromscratch)
166 type(electrons_t), target, intent(inout) :: sys
167 logical, intent(inout) :: fromscratch
169 integer :: ierr
170 real(real64), allocatable :: coords(:)
171 real(real64) :: energy
173 real(real64), allocatable :: mass(:)
174 integer :: iatom, imass
175 type(restart_t) :: restart_load
176 logical :: known_lower_bound
177 logical :: default_val
181 ! For 1D-periodic systems the ion-ion interaction (hence the forces) and the stress
182 ! tensor are not implemented.
183 if (sys%space%periodic_dim == 1) then
184 message(1) = "Geometry optimization is not allowed for systems periodic in 1D, "
185 message(2) = "as the ion-ion interaction and the stress tensor are not available."
186 call messages_fatal(2, namespace=sys%namespace)
187 end if
189 if (sys%space%periodic_dim == 2) then
190 call messages_experimental("Geometry optimization for 2D-periodic systems", namespace=sys%namespace)
191 end if
192
194 if (sys%hm%pcm%run_pcm) then
195 call messages_not_implemented("PCM for CalculationMode /= gs or td", namespace=sys%namespace)
196 end if
198 if (sys%kpoints%use_symmetries) then
199 call messages_experimental("KPoints symmetries with CalculationMode = go", namespace=sys%namespace)
200 end if
201
202 g_opt%symmetrize = sys%kpoints%use_symmetries .or. sys%st%symmetrize_density
203
204 call init_(fromscratch)
205
206 ! load wavefunctions
207 if (.not. fromscratch) then
208 call restart_load%init(sys%namespace, restart_gs, restart_type_load, sys%mc, ierr, mesh=sys%gr)
209 if (ierr == 0) then
210 call states_elec_load(restart_load, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
211 fixed_occ=.false., ierr=ierr)
212 end if
213 call restart_load%end()
214 if (ierr /= 0) then
215 message(1) = "Unable to read wavefunctions: Starting from scratch."
216 call messages_warning(1, namespace=sys%namespace)
217 fromscratch = .true.
218 end if
219 end if
220
221 call scf_init(g_opt%scfv, sys%namespace, sys%gr, sys%ions, sys%st, sys%mc, sys%hm, sys%space)
222
223 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0) then
224 if (.not. g_opt%scfv%calc_stress) then
225 message(1) = "In order to optimize the cell, one needs to set SCFCalculateStress = yes."
226 call messages_fatal(1, namespace=sys%namespace)
227 end if
228 end if
229
230 if (fromscratch) then
231 call lcao_run(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm, &
232 lmm_r = g_opt%scfv%lmm_r, known_lower_bound=known_lower_bound)
233 call scf_set_lower_bound_is_known(g_opt%scfv, known_lower_bound)
234 else
235 ! setup Hamiltonian
236 message(1) = 'Info: Setting up Hamiltonian.'
237 call messages_info(1, namespace=sys%namespace)
238 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
239 call scf_set_lower_bound_is_known(g_opt%scfv, .true.)
240 end if
241
242 !Initial point
243 safe_allocate(coords(1:g_opt%size))
244 call to_coords(g_opt, coords)
245
246 if (sys%st%pack_states .and. sys%hm%apply_packed()) call sys%st%pack()
247
248 !Minimize
249 select case (g_opt%method)
251 call minimize_multidim_nograd(g_opt%method, g_opt%size, coords, g_opt%step,&
252 g_opt%toldr, g_opt%max_iter, &
253 calc_point_ng, write_iter_info_ng, energy, ierr)
254
255 case (minmethod_fire)
256
257 safe_allocate(mass(1:g_opt%size))
258 mass = g_opt%fire_mass
259 imass = 1
260 do iatom = 1, sys%ions%natoms
261 if (g_opt%fixed_atom == iatom) cycle
262 if (g_opt%ions%fixed(iatom)) cycle
263 if (g_opt%fire_mass <= m_zero) mass(imass:imass + 2) = sys%ions%mass(iatom)
264 imass = imass + g_opt%dim
265 end do
266
267 !TODO: add variable to use Euler integrator
268 call minimize_fire(g_opt%size, g_opt%ions%space%dim, coords, g_opt%step, g_opt%tolgrad, &
269 g_opt%max_iter, calc_point, write_iter_info, energy, ierr, mass, integrator=g_opt%fire_integrator)
270
271 safe_deallocate_a(mass)
272
273 case default
274 call minimize_multidim(g_opt%method, g_opt%size, coords, g_opt%step ,&
275 g_opt%line_tol , g_opt%tolgrad, g_opt%toldr, g_opt%max_iter, &
276 calc_point, write_iter_info, energy, ierr)
277
278 end select
279
280 if (ierr == 1025) then
281 ! not a GSL error, set by our minimize routines, so we must handle it separately
282 message(1) = "Reached maximum number of iterations allowed by GOMaxIter."
283 call messages_info(1, namespace=sys%namespace)
284 else if (ierr /= 0 .and. g_opt%method /= minmethod_fire) then
285 message(1) = "Error occurred during the GSL minimization procedure:"
286 call loct_strerror(ierr, message(2))
287 call messages_fatal(2, namespace=sys%namespace)
288 end if
289
290 if (sys%st%pack_states .and. sys%hm%apply_packed()) call sys%st%unpack()
291
292
293 ! print out geometry
294 message(1) = "Writing final coordinates to min.xyz"
295 call messages_info(1, namespace=sys%namespace)
296 call from_coords(g_opt, coords)
297 call g_opt%ions%write_xyz('./min')
298
299 safe_deallocate_a(coords)
300 call scf_end(g_opt%scfv)
301 ! Because g_opt has the "save" attribute, we need to explicitly empty the criteria list here, or there will be a memory leak.
302 call g_opt%scfv%criterion_list%empty()
303 call end_()
304
305 pop_sub(geom_opt_run_legacy)
306 contains
307
308 ! ---------------------------------------------------------
309 subroutine init_(fromscratch)
310 logical, intent(inout) :: fromscratch
311
312 logical :: center, does_exist
313 integer :: iter, iatom, idir
314 character(len=100) :: filename
315 real(real64) :: default_toldr
316 real(real64) :: default_step
317 type(read_coords_info) :: xyz
318
319 push_sub(geom_opt_run_legacy.init_)
320
321 if (sys%space%is_periodic()) then
322 call messages_experimental('Geometry optimization for periodic systems', namespace=sys%namespace)
323 end if
324
325 !%Variable GOType
326 !%Type flag
327 !%Default ions
328 !%Section Calculation Modes::Geometry Optimization
329 !%Description
330 !% This variable defines which parameters are allowed to change during the optimization.
331 !% Multiple options can be chosen e.g. “ion_positions + cell_shape”.
332 !% Only one type of lattice vectors relaxation is possible.
333 !%Option ion_positions 1
334 !% Relax position of ions based on the forces acting on the ions.
335 !%Option cell_shape 2
336 !% Relax cell shape. This changes lattice vector lengths and directions
337 !% based on the stress acting on the lattice vectors.
338 !% See for instance Wentzcovitch, PRB 44, 2358 (1991).
339 !%Option cell_volume 4
340 !% Relax cell volume. Only allow for rescaling the lengths of lattice vectors.
341 !% This is a simplication of the option cell_shape, where only a diagonal strain is allowed.
342 !%End
343
344 call parse_variable(sys%namespace, 'GOType', go_ions, g_opt%type)
345 if (.not. varinfo_valid_option('GOType', g_opt%type, is_flag=.true.)) then
346 call messages_input_error(sys%namespace, 'GOType')
347 end if
348
349 write(message(1),'(a)') 'Input: [GOType = '
350 if (bitand(g_opt%type, go_ions) /= 0) then
351 write(message(1),'(a,1x,a)') trim(message(1)), 'ion_positions'
352 end if
353 if (bitand(g_opt%type, go_cell) /= 0) then
354 if (len_trim(message(1)) > 16) then
355 write(message(1),'(a,1x,a)') trim(message(1)), '+'
356 end if
357 write(message(1),'(a,1x,a)') trim(message(1)), 'cell_shape'
358 end if
359 if (bitand(g_opt%type, go_volume) /= 0) then
360 if (len_trim(message(1)) > 16) then
361 write(message(1),'(a,1x,a)') trim(message(1)), '+'
362 end if
363 write(message(1),'(a,1x,a)') trim(message(1)), 'cell_volume'
364 end if
365 write(message(1),'(2a)') trim(message(1)), ']'
366 call messages_info(1, namespace=sys%namespace)
367
368 if (bitand(g_opt%type, go_volume) /= 0 .and. bitand(g_opt%type, go_cell) /= 0) then
369 message(1) = "Cell and volume optimization cannot be used simultaneously."
370 call messages_fatal(1, namespace=sys%namespace)
371 end if
372
373
374 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0) then
375 if (parse_is_defined(sys%namespace, 'TDMomentumTransfer') .or. &
376 parse_is_defined(sys%namespace, 'TDReducedMomentumTransfer')) then
377 call messages_not_implemented("Cell dynamics with TDMomentumTransfer and TDReducedMomentumTransfer")
378 end if
379 end if
380
381 do iatom = 1, sys%ions%natoms
382 select type(spec=>sys%ions%atom(iatom)%species)
383 class is(allelectron_t)
384 write(message(1),'(a)') "Geometry optimization for all-electron potential is not implemented."
385 call messages_fatal(1)
386 end select
387 end do
388
389
390 call states_elec_allocate_wfns(sys%st, sys%gr, packed=.true.)
391
392 ! shortcuts
393 g_opt%mesh => sys%gr
394 g_opt%ions => sys%ions
395 g_opt%st => sys%st
396 g_opt%hm => sys%hm
397 g_opt%syst => sys
398 g_opt%dim = sys%space%dim
399 g_opt%periodic_dim = sys%space%periodic_dim
400
401 g_opt%size = 0
402 ! Ion dyamics
403 if (bitand(g_opt%type, go_ions) /= 0) then
404 g_opt%size = g_opt%dim * g_opt%ions%natoms
405 end if
406
407 ! Cell dynamics
408 if (bitand(g_opt%type, go_cell) /= 0) then
409 g_opt%size = g_opt%size + (g_opt%periodic_dim +1) * g_opt%periodic_dim / 2
410 safe_allocate(g_opt%cell_force(1:g_opt%periodic_dim, 1:g_opt%periodic_dim))
411 end if
412
413 ! Volume dynamics
414 if (bitand(g_opt%type, go_volume) /= 0) then
415 g_opt%size = g_opt%size + g_opt%periodic_dim
416 safe_allocate(g_opt%cell_force(1:g_opt%periodic_dim, 1:1))
417 ! Store the length of the original lattic vectors, to work with reduced lengthes
418 safe_allocate(g_opt%initial_length(1:g_opt%periodic_dim))
419 do idir = 1, g_opt%periodic_dim
420 g_opt%initial_length(idir) = norm2(g_opt%ions%latt%rlattice(1:g_opt%periodic_dim, idir))
421 end do
422 end if
423
424 ! Store the initial lattice vectors and the inverse matrix
425 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0) then
426 safe_allocate(g_opt%initial_rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim))
427 g_opt%initial_rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim) &
428 = g_opt%ions%latt%rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim)
429 safe_allocate(g_opt%inv_initial_rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim))
430 g_opt%inv_initial_rlattice(:, :) = g_opt%initial_rlattice(:, :)
431 call lalg_inverse(g_opt%periodic_dim, g_opt%inv_initial_rlattice, 'dir')
432 end if
433
434 if(g_opt%ions%space%is_periodic()) then
435 call parse_variable(sys%namespace, 'HydrostaticPressure', m_zero, g_opt%pressure)
436 end if
437
438 !%Variable GOCenter
439 !%Type logical
440 !%Default no
441 !%Section Calculation Modes::Geometry Optimization
442 !%Description
443 !% (Experimental) If set to yes, Octopus centers the geometry at
444 !% every optimization step. It also reduces the degrees of
445 !% freedom of the optimization by using the translational
446 !% invariance.
447 !%End
448 call parse_variable(sys%namespace, 'GOCenter', .false., center)
449
450 if (center .and. bitand(g_opt%type, go_ions) /= 0) then
451 g_opt%fixed_atom = 1
452 g_opt%size = g_opt%size - g_opt%dim
453 call messages_experimental('GOCenter', namespace=sys%namespace)
454 end if
455
456 !Check if atoms are allowed to move and redifine g_opt%size
457 do iatom = 1, g_opt%ions%natoms
458 if (g_opt%ions%fixed(iatom) .and. bitand(g_opt%type, go_ions) /= 0) then
459 g_opt%size = g_opt%size - g_opt%dim
460 end if
461 end do
462
463 assert(g_opt%size > 0)
464
465 !%Variable GOMethod
466 !%Type integer
467 !%Default fire
468 !%Section Calculation Modes::Geometry Optimization
469 !%Description
470 !% Method by which the minimization is performed. For more information see the
471 !% <a href=http://www.gnu.org/software/gsl/manual/html_node/Multidimensional-Minimization.html>
472 !% GSL documentation</a>.
473 !%Option steep 1
474 !% Simple steepest descent.
475 !%Option steep_native -1
476 !% (Experimental) Non-gsl implementation of steepest descent.
477 !%Option cg_fr 2
478 !% Fletcher-Reeves conjugate-gradient algorithm. The
479 !% conjugate-gradient algorithm proceeds as a succession of line
480 !% minimizations. The sequence of search directions is used to build
481 !% up an approximation to the curvature of the function in the
482 !% neighborhood of the minimum.
483 !%Option cg_pr 3
484 !% Polak-Ribiere conjugate-gradient algorithm.
485 !%Option cg_bfgs 4
486 !% Vector Broyden-Fletcher-Goldfarb-Shanno (BFGS) conjugate-gradient algorithm.
487 !% It is a quasi-Newton method which builds up an approximation to the second
488 !% derivatives of the function <i>f</i> using the difference between successive gradient
489 !% vectors. By combining the first and second derivatives, the algorithm is able
490 !% to take Newton-type steps towards the function minimum, assuming quadratic
491 !% behavior in that region.
492 !%Option cg_bfgs2 5
493 !% The bfgs2 version of this minimizer is the most efficient version available,
494 !% and is a faithful implementation of the line minimization scheme described in
495 !% Fletcher, <i>Practical Methods of Optimization</i>, Algorithms 2.6.2 and 2.6.4.
496 !%Option simplex 6
497 !% This is experimental, and in fact, <b>not</b> recommended unless you just want to
498 !% fool around. It is the Nead-Melder simplex algorithm, as implemented in the
499 !% GNU Scientific Library (GSL). It does not make use of the gradients (<i>i.e.</i>, the
500 !% forces) which makes it less efficient than other schemes. It is included here
501 !% for completeness, since it is free.
502 !%Option fire 8
503 !% The FIRE algorithm. See also <tt>GOFireMass</tt> and <tt>GOFireIntegrator</tt>.
504 !% Ref: E. Bitzek, P. Koskinen, F. Gahler, M. Moseler, and P. Gumbsch, <i>Phys. Rev. Lett.</i> <b>97</b>, 170201 (2006).
505 !%End
506 call parse_variable(sys%namespace, 'GOMethod', minmethod_fire, g_opt%method)
507 if (.not. varinfo_valid_option('GOMethod', g_opt%method)) call messages_input_error(sys%namespace, 'GOMethod')
508
509
510 call messages_print_var_option("GOMethod", g_opt%method, namespace=sys%namespace)
511
512 !%Variable GOTolerance
513 !%Type float
514 !%Default 0.001 H/b (0.051 eV/A)
515 !%Section Calculation Modes::Geometry Optimization
516 !%Description
517 !% Convergence criterion, for stopping the minimization. In
518 !% units of force; minimization is stopped when all forces on
519 !% ions are smaller than this criterion, or the
520 !% <tt>GOMinimumMove</tt> is satisfied. If <tt>GOTolerance < 0</tt>,
521 !% this criterion is ignored.
522 !%End
523 call parse_variable(sys%namespace, 'GOTolerance', 0.001_real64, g_opt%tolgrad, units_inp%force)
524
525 !%Variable GOMinimumMove
526 !%Type float
527 !%Section Calculation Modes::Geometry Optimization
528 !%Description
529 !% Convergence criterion, for stopping the minimization. In
530 !% units of length; minimization is stopped when the coordinates
531 !% of all species change less than <tt>GOMinimumMove</tt>, or the
532 !% <tt>GOTolerance</tt> criterion is satisfied.
533 !% If <tt>GOMinimumMove < 0</tt>, this criterion is ignored.
534 !% Default is -1, except 0.001 b with <tt>GOMethod = simplex</tt>.
535 !% Note that if you use <tt>GOMethod = simplex</tt>,
536 !% then you must supply a non-zero <tt>GOMinimumMove</tt>.
537 !%End
538 if (g_opt%method == minmethod_nmsimplex) then
539 default_toldr = 0.001_real64
540 else
541 default_toldr = -m_one
542 end if
543 call parse_variable(sys%namespace, 'GOMinimumMove', default_toldr, g_opt%toldr, units_inp%length)
544
545 if (g_opt%method == minmethod_nmsimplex .and. g_opt%toldr <= m_zero) call messages_input_error(sys%namespace, 'GOMinimumMove')
546
547 !%Variable GOStep
548 !%Type float
549 !%Section Calculation Modes::Geometry Optimization
550 !%Description
551 !% Initial step for the geometry optimizer. The default is 0.5.
552 !% WARNING: in some weird units.
553 !% For the FIRE minimizer, default value is 0.1 fs,
554 !% and corresponds to the initial time-step for the MD.
555 !%End
556 if (g_opt%method /= minmethod_fire) then
557 default_step = m_half
558 call parse_variable(sys%namespace, 'GOStep', default_step, g_opt%step)
559 else
560 default_step = 0.1_real64*unit_femtosecond%factor
561 call parse_variable(sys%namespace, 'GOStep', default_step, g_opt%step, unit = units_inp%time)
562 end if
563
564 !%Variable GOLineTol
565 !%Type float
566 !%Default 0.1
567 !%Section Calculation Modes::Geometry Optimization
568 !%Description
569 !% Tolerance for line-minimization. Applies only to GSL methods
570 !% that use the forces.
571 !% WARNING: in some weird units.
572 !%End
573 call parse_variable(sys%namespace, 'GOLineTol', 0.1_real64, g_opt%line_tol)
574
575 !%Variable GOMaxIter
576 !%Type integer
577 !%Default 200
578 !%Section Calculation Modes::Geometry Optimization
579 !%Description
580 !% Even if the convergence criterion is not satisfied, the minimization will stop
581 !% after this number of iterations.
582 !%End
583 call parse_variable(sys%namespace, 'GOMaxIter', 200, g_opt%max_iter)
584 if (g_opt%max_iter <= 0) then
585 message(1) = "GOMaxIter has to be larger than 0"
586 call messages_fatal(1, namespace=sys%namespace)
587 end if
588
589 !%Variable GOFireMass
590 !%Type float
591 !%Default 1.0 amu
592 !%Section Calculation Modes::Geometry Optimization
593 !%Description
594 !% The Fire algorithm (<tt>GOMethod = fire</tt>) assumes that all degrees of freedom
595 !% are comparable. All the velocities should be on the same
596 !% scale, which for heteronuclear systems can be roughly
597 !% achieved by setting all the atom masses equal, to the value
598 !% specified by this variable.
599 !% By default the mass of a proton is selected (1 amu).
600 !% However, a selection of <tt>GOFireMass = 0.01</tt> can, in manys systems,
601 !% speed up the geometry optimization procedure.
602 !% If <tt>GOFireMass</tt> <= 0, the masses of each
603 !% species will be used.
604 !%End
605 call parse_variable(sys%namespace, 'GOFireMass', m_one*unit_amu%factor, g_opt%fire_mass, unit = unit_amu)
606
607 !%Variable GOFireIntegrator
608 !%Type integer
609 !%Default verlet
610 !%Section Calculation Modes::Geometry Optimization
611 !%Description
612 !% The Fire algorithm (<tt>GOMethod = fire</tt>) uses a molecular dynamics
613 !% integrator to compute new geometries and velocities.
614 !% Currently, two integrator schemes can be selected
615 !%Option euler 0
616 !% The Explicit Euler method.
617 !%Option verlet 1
618 !% The Velocity Verlet algorithm.
619 !%Option semi_implicit_euler 2
620 !% Semi-implicit Euler integration, see J. Guénolé, et al. Computational Materials Science 175 (2020) 109584.
621 !%End
622 call parse_variable(sys%namespace, 'GOFireIntegrator', option__gofireintegrator__verlet, g_opt%fire_integrator)
623
624 call messages_obsolete_variable(sys%namespace, 'GOWhat2Minimize', 'GOObjective')
625
626 !%Variable GOObjective
627 !%Type integer
628 !%Default minimize_energy
629 !%Section Calculation Modes::Geometry Optimization
630 !%Description
631 !% This rather esoteric option allows one to choose which
632 !% objective function to minimize during a geometry
633 !% minimization. The use of this variable may lead to
634 !% inconsistencies, so please make sure you know what you are
635 !% doing.
636 !%Option minimize_energy 1
637 !% Use the total energy as objective function.
638 !%Option minimize_forces 2
639 !% Use <math>\sqrt{\sum_i \left| f_i \right|^2}</math> as objective function.
640 !% Note that in this case one still uses the forces as the gradient of the objective function.
641 !% This is, of course, inconsistent, and may lead to very strange behavior.
642 !%End
643 call parse_variable(sys%namespace, 'GOObjective', minwhat_energy, g_opt%what2minimize)
644 if (.not. varinfo_valid_option('GOObjective', g_opt%what2minimize)) call messages_input_error(sys%namespace, 'GOObjective')
645 call messages_print_var_option("GOObjective", g_opt%what2minimize, namespace=sys%namespace)
646
647
648 !%Variable XYZGOConstrains
649 !%Type string
650 !%Section Calculation Modes::Geometry Optimization
651 !%Description
652 !% <tt>Octopus</tt> will try to read the coordinate-dependent constrains from the XYZ file
653 !% specified by the variable <tt>XYZGOConstrains</tt>.
654 !% Note: It is important for the contrains to maintain the ordering
655 !% in which the atoms were defined in the coordinates specifications.
656 !% Moreover, constrains impose fixed absolute coordinates, therefore
657 !% constrains are not compatible with GOCenter = yes
658 !%End
659
660 !%Variable XSFGOConstrains
661 !%Type string
662 !%Section Calculation Modes::Geometry Optimization
663 !%Description
664 !% Like <tt>XYZGOConstrains</tt> but in XCrySDen format, as in <tt>XSFCoordinates</tt>.
665 !%End
666
667 !%Variable PDBGOConstrains
668 !%Type string
669 !%Section Calculation Modes::Geometry Optimization
670 !%Description
671 !% Like <tt>XYZGOConstrains</tt> but in PDB format, as in <tt>PDBCoordinates</tt>.
672 !%End
673
674 !%Variable GOConstrains
675 !%Type block
676 !%Section Calculation Modes::Geometry Optimization
677 !%Description
678 !% If <tt>XYZGOConstrains</tt>, <tt>PDBConstrains</tt>, and <tt>XSFGOConstrains</tt>
679 !% are not present, <tt>Octopus</tt> will try to fetch the geometry optimization
680 !% contrains from this block. If this block is not present, <tt>Octopus</tt>
681 !% will not set any constrains. The format of this block can be
682 !% illustrated by this example:
683 !%
684 !% <tt>%GOConstrains
685 !% <br>&nbsp;&nbsp;'C' | 1 | 0 | 0
686 !% <br>&nbsp;&nbsp;'O' | &nbsp;1 | 0 | 0
687 !% <br>%</tt>
688 !%
689 !% Coordinates with a constrain value of 0 will be optimized, while
690 !% coordinates with a constrain different from zero will be kept fixed. So,
691 !% in this example the x coordinates of both atoms will remain fixed and the
692 !% distance between the two atoms along the x axis will be constant.
693 !%
694 !% Note: It is important for the constrains to maintain the ordering
695 !% in which the atoms were defined in the coordinates specifications.
696 !% Moreover, constrains impose fixed absolute coordinates, therefore
697 !% constrains are not compatible with GOCenter = yes
698 !%End
699
700 call read_coords_init(xyz)
701 call read_coords_read('GOConstrains', xyz, g_opt%ions%space, sys%namespace)
702 if (xyz%source /= read_coords_err) then
703 !Sanity check
704 if (g_opt%ions%natoms /= xyz%n) then
705 write(message(1), '(a,i4,a,i4)') 'I need exactly ', g_opt%ions%natoms, ' constrains, but I found ', xyz%n
706 call messages_fatal(1, namespace=sys%namespace)
707 end if
708 ! copy information and adjust units
709 do iatom = 1, g_opt%ions%natoms
710 where(abs(xyz%atom(iatom)%x) <= m_epsilon)
711 g_opt%ions%atom(iatom)%c = m_zero
712 elsewhere
713 g_opt%ions%atom(iatom)%c = m_one
714 end where
715 end do
716
717 call read_coords_end(xyz)
718
719
720 if (g_opt%fixed_atom > 0) then
721 call messages_not_implemented("GOCenter with constrains", namespace=sys%namespace)
722 end if
723 else
724 do iatom = 1, g_opt%ions%natoms
725 g_opt%ions%atom(iatom)%c = m_zero
726 end do
727 end if
728
729 !%Variable GOCalculator
730 !%Type integer
731 !%Default internal
732 !%Section Calculation Modes::Geometry Optimization
733 !%Description
734 !% Defines what calculator is used for performing geometry optimization.
735 !% By default, Octopus is used for computing the forces and energy.
736 !% However, it is possible to use (if selected at compile time) a machine-learned
737 !% universal force field to do the optimization of the geometry instead of Octopus.
738 !%
739 !%Option internal 1
740 !% Usual case: forces/stress are only computed by Octopus
741 !%Option mattersim 2
742 !% MatterSim deep learning atomistic model.
743 !%End
744 call parse_variable(sys%namespace, 'GOCalculator', go_calculator_internal, g_opt%calculator)
745 if (.not. varinfo_valid_option('GOCalculator', g_opt%calculator)) then
746 call messages_input_error(sys%namespace, 'GOCalculator')
747 end if
748#ifndef HAVE_MATTERSIM
749 if (g_opt%calculator == go_calculator_mattersim) then
750 message(1) = 'Octopus was not compiled with support for MatterSim'
751 call messages_fatal(1, namespace=sys%namespace)
752 end if
753#endif
754
755 !%Variable GOMLPreoptimize
756 !%Type logical
757 !%Default yes (if compiled with MatterSim)
758 !%Section Calculation Modes::Geometry Optimization
759 !%Description
760 !% If true, a machine-learned force field is used to pre-optimize the geometry,
761 !% once, before the actual optimization starts.
762 !% Currently, only uses MatterSim. This is not compatible with <tt>GOCalculator=mattersim</tt>.
763 !% Requires Octopus to be compiled with MatterSim; the default is no otherwise.
764 !% The default is also no for <tt>GOCalculator=mattersim</tt>, and when relaxing
765 !% the cell of a system which is not periodic along all three directions.
766 !% The pre-optimization keeps the coordinates fixed by <tt>GOConstrains</tt> and
767 !% <tt>GOCenter</tt>, as well as the atoms of a fixed species.
768 !%End
769#ifdef HAVE_MATTERSIM
770 default_val = .true.
771 if (g_opt%calculator == go_calculator_mattersim) default_val = .false.
772 !TODO: Add support for mixed periodicity
773 if (sys%space%periodic_dim /= 3 .and. &
774 (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0)) default_val = .false.
775#else
776 default_val = .false.
777#endif
778 call parse_variable(sys%namespace, 'GOMLPreoptimize', default_val, g_opt%ml_preopt)
779#ifndef HAVE_MATTERSIM
780 if (g_opt%ml_preopt) then
781 message(1) = 'Octopus was not compiled with support for MatterSim'
782 call messages_fatal(1, namespace=sys%namespace)
783 end if
784#endif
785
786 call io_mkdir('geom', sys%namespace)
787
788 if (g_opt%ml_preopt) then
789 call ml_preopt(g_opt)
790 end if
791
792
793 call io_rm("geom/optimization.log", sys%namespace)
794
795 call io_rm("work-geom.xyz", sys%namespace)
796
797 if (.not. fromscratch) then
798 inquire(file = './last.xyz', exist = does_exist)
799 if (.not. does_exist) fromscratch = .true.
800 end if
801
802 if (.not. fromscratch) call g_opt%ions%read_xyz('./last')
803
804 ! clean out old geom/go.XXXX.xyz files. must be consistent with write_iter_info
805 iter = 1
806 do
807 write(filename, '(a,i4.4,a)') "geom/go.", iter, ".xyz"
808 inquire(file = trim(filename), exist = does_exist)
809 if (does_exist) then
810 call io_rm(trim(filename), sys%namespace)
811 if (sys%space%periodic_dim > 0) then
812 write(filename, '(a,i4.4,a)') "geom/go.", iter, ".xyz_red"
813 call io_rm(trim(filename), sys%namespace)
814 write(filename, '(a,i4.4,a)') "geom/go.", iter, ".xsf"
815 call io_rm(trim(filename), sys%namespace)
816 end if
817 iter = iter + 1
818 else
819 exit
820 end if
821 ! TODO: clean forces directory
822 end do
823
824 call g_opt%scfv%restart_dump%init(sys%namespace, restart_gs, restart_type_dump, sys%mc, ierr, mesh=sys%gr)
825
827 end subroutine init_
828
829
830 ! ---------------------------------------------------------
831 subroutine end_()
832 push_sub(geom_opt_run_legacy.end_)
833
834 call states_elec_deallocate_wfns(sys%st)
835
836 call g_opt%scfv%restart_dump%end()
837
838 nullify(g_opt%mesh)
839 nullify(g_opt%ions)
840 nullify(g_opt%st)
841 nullify(g_opt%hm)
842 nullify(g_opt%syst)
843
844 safe_deallocate_a(g_opt%cell_force)
845
847 end subroutine end_
848
849 end subroutine geom_opt_run_legacy
850
851
852 ! ---------------------------------------------------------
855 subroutine calc_point(size, coords, objective, getgrad, df)
856 integer, intent(in) :: size
857 real(real64), intent(in) :: coords(size)
858 real(real64), intent(inout) :: objective
859 integer, intent(in) :: getgrad
860 real(real64), intent(inout) :: df(size)
861
862 integer :: iatom, idir, jdir, iunit, command_status, command_exit
863 real(real64), dimension(g_opt%periodic_dim, g_opt%periodic_dim) :: stress, strain, right_stretch, inv_right_stretch, &
864 rotation, sym_stress
865 real(real64) :: det
866 character(len=MAX_PATH_LEN) :: cmd, mattersim_share, mattersim_python
867
868 push_sub(calc_point)
869
870 assert(size == g_opt%size)
871 command_status = 0
872 command_exit = 0
873
874 call from_coords(g_opt, coords)
875
876 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0 ) then
877 call ion_dynamics_box_update(g_opt%syst%namespace, g_opt%syst%gr, g_opt%syst%space, g_opt%ions%latt)
878 end if
879
880 if (g_opt%fixed_atom /= 0) then
881 call g_opt%ions%translate(g_opt%ions%center())
882 end if
883
884 ! When the system is periodic in some directions, the atoms might have moved to a an adjacent cell,
885 ! so we need to move them back to the original cell
886 call g_opt%ions%fold_atoms_into_cell()
887
888 ! Some atoms might have moved outside the simulation box. We stop if this happens.
889 do iatom = 1, g_opt%ions%natoms
890 if (.not. g_opt%syst%gr%box%contains_point(g_opt%ions%pos(:, iatom))) then
891 if (g_opt%syst%space%periodic_dim /= g_opt%syst%space%dim) then
892 ! FIXME: This could fail for partial periodicity systems
893 ! because contains_point is too strict with atoms close to
894 ! the upper boundary to the cell.
895 write(message(1), '(a,i5,a)') "Atom ", iatom, " has moved outside the box during the geometry optimization."
896 call messages_fatal(1, namespace=g_opt%syst%namespace)
897 end if
898 end if
899 end do
900
901 if (g_opt%calculator==go_calculator_internal) then
902 call g_opt%ions%write_xyz('./work-geom', append = .true.)
903 else
904 if (g_opt%ions%space%is_periodic()) then
905 call write_extended_xyz_file('.', 'work-geom', g_opt%ions%space, g_opt%ions%latt, g_opt%ions%pos, g_opt%ions%atom, &
906 g_opt%syst%gr%box, g_opt%syst%namespace)
907 else
908 call g_opt%ions%write_xyz('./work-geom', append = .false.)
909 end if
910 end if
911
912 ! Update lattice vectors and regenerate grid
913 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0 ) then
914 call electrons_lattice_vectors_update(g_opt%syst%namespace, g_opt%syst%gr, &
915 g_opt%syst%space, g_opt%syst%hm%psolver, g_opt%syst%hm%kpoints, &
916 g_opt%syst%mc, g_opt%syst%st%qtot, g_opt%ions%latt)
917 end if
918
919 ! This is already set to zero for periodic systems
920 if (g_opt%ions%force_total_enforce) then
921 call forces_set_total_to_zero(g_opt%ions, g_opt%ions%tot_force)
922 end if
923
924 call scf_print_mem_use(g_opt%syst%namespace)
925
926 ! Select the calculator: Octopus or a ML force field
927 select case (g_opt%calculator)
928 case (go_calculator_internal)
929
930 call scf_mix_clear(g_opt%scfv)
931 call hamiltonian_elec_epot_generate(g_opt%hm, g_opt%syst%namespace, g_opt%syst%space, g_opt%syst%gr, &
932 g_opt%ions, g_opt%syst%ext_partners, g_opt%st)
933 call density_calc(g_opt%st, g_opt%syst%gr, g_opt%st%rho)
934 call v_ks_calc(g_opt%syst%ks, g_opt%syst%namespace, g_opt%syst%space, g_opt%hm, g_opt%st, &
935 g_opt%ions,g_opt%syst%ext_partners, calc_eigenval = .true.)
936 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)
937
938 ! do SCF calculation
939 call scf_run(g_opt%scfv, g_opt%syst%namespace, g_opt%syst%space, g_opt%syst%mc, g_opt%syst%gr, &
940 g_opt%ions, g_opt%syst%ext_partners, &
941 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)
942
943 call scf_print_mem_use(g_opt%syst%namespace)
944
946 call mattersim_paths(mattersim_share, mattersim_python, g_opt%syst%namespace)
947 if (mpi_world%is_root()) then
948 ! Execute a system call for the current geometry
949 ! -I isolates the venv python from any external PYTHONPATH/PYTHONHOME
950 cmd = trim(mattersim_python) // " -I " // trim(mattersim_share) &
951 // "/scripts/run_mattersim.py work-geom.xyz ml_forces.xyz " // trim(mattersim_share)
952 call execute_command_line(trim(cmd), exitstat=command_exit, cmdstat=command_status)
953 if (command_status == 0) command_status = command_exit
954 end if
955 call mpi_world%bcast(command_status, 1, mpi_integer, 0)
956 if (command_status /= 0) then
957 write(message(1), '(a,i0)') 'MatterSim force calculation failed with exit status ', command_status
958 call messages_fatal(1, namespace=g_opt%syst%namespace)
959 end if
960 call mpi_world%barrier()
961
962 ! Read the result from MatterSim
963 iunit = io_open('ml_forces.xyz', global_namespace, action='read')
964 read(iunit, *) g_opt%hm%energy%total
965 do iatom = 1, g_opt%ions%natoms
966 read(iunit,*) g_opt%ions%tot_force(:, iatom)
967 end do
968 read(iunit, *) ! skip comment line
969 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0) then
970 do idir = 1, 3
971 read(iunit,*) g_opt%syst%st%stress_tensors%total(:, idir)
972 end do
973 end if
974 call io_close(iunit)
975
976 end select
977
978 ! Convert stress into cell force
979 ! This is the Parrinello-Rahman equation of motion of the cell,
980 ! see Parrinello and Rahman, J. Appl. Pys. 52, 7182 (1981), Eq. 2.10.
981 ! Here we use a slightly different definition, in which we evolve the right stretch tensor
982 ! instead of h, because this is a symmetric matrix.
983 ! The deformation tensor is defined as F = (1+\epsilon) = h h_0^{-1},
984 ! where \epsilon is the infinitesimal strain tensor
985 ! Using the polar decomposition F = R U, we can request to have \ddot{U} that remains symmetric
986 ! in order to kill all the rotation
987 if (bitand(g_opt%type, go_cell) /= 0) then
988 stress = -g_opt%syst%st%stress_tensors%total(1:g_opt%periodic_dim, 1:g_opt%periodic_dim)
989
990 ! Replace \sigma = sym(R^T \sigma R)
991 ! We first compute R from the right polar decomposition R = F U^-1
992 strain = matmul(g_opt%ions%latt%rlattice(1:g_opt%periodic_dim,1:g_opt%periodic_dim), g_opt%inv_initial_rlattice)
993 right_stretch = lalg_remove_rotation(g_opt%periodic_dim, strain)
994 inv_right_stretch = right_stretch
995 call lalg_inverse(g_opt%periodic_dim, inv_right_stretch, 'dir')
996 rotation = matmul(strain, inv_right_stretch)
997 ! In some cases, R can contain a reflection. To guarantee that U is SPD, we multiply by the determinant of R
998 det = lalg_determinant(g_opt%periodic_dim, rotation, preserve_mat=.true.)
999
1000 ! Compute the symmetrized stress
1001 sym_stress = matmul(transpose(rotation), matmul(stress, rotation))
1002 sym_stress = m_half*(sym_stress + transpose(sym_stress)) * det
1003
1004 ! The external hydrostatic pressure enters as a full -P on each diagonal component of the
1005 ! stress, such that at equilibrium the internal stress balances the pressure (\sigma = -P I).
1006 do idir = 1, g_opt%periodic_dim
1007 sym_stress(idir, idir) = sym_stress(idir, idir) - g_opt%pressure
1008 end do
1009 g_opt%cell_force = sym_stress * g_opt%ions%latt%rcell_volume
1010
1011 g_opt%cell_force = matmul(g_opt%cell_force, inv_right_stretch)
1012 ! The cell force is the gradient with respect to the symmetric right stretch tensor U,
1013 ! so we symmetrize it.
1014 g_opt%cell_force = m_half*(g_opt%cell_force + transpose(g_opt%cell_force))
1015 end if
1016
1017 ! Convert stress into cell force
1018 if (bitand(g_opt%type, go_volume) /= 0) then
1019 stress = g_opt%syst%st%stress_tensors%total(1:g_opt%periodic_dim, 1:g_opt%periodic_dim)
1020 do idir = 1, g_opt%periodic_dim
1021 g_opt%cell_force(idir, 1) = -(g_opt%pressure + stress(idir, idir)) * g_opt%ions%latt%rcell_volume
1022 end do
1023 end if
1024
1025 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0) then
1026 write(message(1),'(a,3a,a)') ' Stress tensor [', trim(units_abbrev(units_out%length)), ']'
1027 do idir = 1, g_opt%periodic_dim
1028 write(message(1+idir),'(9e18.10)') (units_from_atomic(units_out%length, g_opt%syst%st%stress_tensors%total(jdir, idir)), &
1029 jdir = 1, g_opt%periodic_dim)
1030 end do
1031 call messages_info(1+g_opt%periodic_dim, namespace=g_opt%ions%namespace, debug_only=.true.)
1032 write(message(1),'(a,3a,a)') ' Cell force tensor [', trim(units_abbrev(units_out%length)), ']'
1033 do idir = 1, ubound(g_opt%cell_force, 2)
1034 write(message(1+idir),'(9e18.10)') (units_from_atomic(units_out%length, g_opt%cell_force(jdir, idir)), &
1035 jdir = 1, g_opt%periodic_dim)
1036 end do
1037 call messages_info(1+g_opt%periodic_dim, namespace=g_opt%ions%namespace, debug_only=.true.)
1038 end if
1039
1040
1041 ! store results
1042 if (getgrad == 1) call to_grad(g_opt, df)
1043
1044 if (g_opt%what2minimize == minwhat_forces) then
1045 objective = m_zero
1046 do iatom = 1, g_opt%ions%natoms
1047 if (g_opt%ions%fixed(iatom)) cycle
1048 objective = objective + sum(g_opt%ions%tot_force(:, iatom)**2)
1049 end do
1050 if (bitand(g_opt%type, go_cell) /= 0) then
1051 do idir = 1, g_opt%periodic_dim
1052 objective = objective + sum(g_opt%cell_force(:, idir)**2)
1053 end do
1054 end if
1055 if (bitand(g_opt%type, go_volume) /= 0) then
1056 objective = objective + sum(g_opt%cell_force(:,1)**2)
1057 end if
1058 objective = sqrt(objective)
1059 else
1060 objective = g_opt%hm%energy%total
1061 end if
1062
1063 pop_sub(calc_point)
1064 end subroutine calc_point
1065
1066
1067 ! ---------------------------------------------------------
1072 subroutine calc_point_ng(size, coords, objective)
1073 integer :: size
1074 real(real64) :: coords(size)
1075 real(real64) :: objective
1076
1077 integer :: getgrad
1078 real(real64), allocatable :: df(:)
1079
1080 push_sub(calc_point_ng)
1081
1082 assert(size == g_opt%size)
1083
1084 getgrad = 0
1085 safe_allocate(df(1:size))
1086 df = m_zero
1087
1088 call calc_point(size, coords, objective, getgrad, df)
1089 safe_deallocate_a(df)
1090
1091 pop_sub(calc_point_ng)
1092 end subroutine calc_point_ng
1093
1094
1095 ! ---------------------------------------------------------
1097 subroutine write_iter_info(geom_iter, size, energy, maxdx, maxdf, coords)
1098 integer, intent(in) :: geom_iter
1099 integer, intent(in) :: size
1100 real(real64), intent(in) :: energy, maxdx, maxdf
1101 real(real64), intent(in) :: coords(size)
1102
1103 character(len=256) :: c_geom_iter, title, c_forces_iter
1104 integer :: iunit
1105
1106 push_sub(write_iter_info)
1107
1108 write(c_geom_iter, '(a,i4.4)') "go.", geom_iter
1109 write(title, '(f16.10,2x,a)') units_from_atomic(units_out%energy, energy), trim(units_abbrev(units_out%energy))
1110 call g_opt%ions%write_xyz('geom/'//trim(c_geom_iter), comment = trim(title))
1111 call g_opt%ions%write_xyz('./last')
1112
1113 if(g_opt%periodic_dim > 0) then
1114 call g_opt%ions%write_xyz('geom/'//trim(c_geom_iter), comment = 'Reduced coordinates', reduce_coordinates = .true.)
1115 call write_xsf_geometry_file('geom', trim(c_geom_iter), g_opt%ions%space, g_opt%ions%latt, &
1116 g_opt%ions%pos, g_opt%ions%atom, g_opt%syst%gr, g_opt%syst%namespace)
1117 end if
1118
1119 if (g_opt%syst%outp%what(option__output__forces)) then
1120 write(c_forces_iter, '(a,i4.4)') "forces.", geom_iter
1121 if (bitand(g_opt%syst%outp%how(option__output__forces), option__outputformat__bild) /= 0) then
1122 call g_opt%ions%write_bild_forces_file('forces', trim(c_forces_iter))
1123 else
1124 call write_xsf_geometry_file('forces', trim(c_forces_iter), g_opt%ions%space, g_opt%ions%latt, &
1125 g_opt%ions%pos, g_opt%ions%atom, g_opt%syst%gr, g_opt%syst%namespace, total_forces=g_opt%ions%tot_force)
1126 end if
1127 end if
1128
1129 if (g_opt%syst%st%system_grp%is_root()) then
1130 iunit = io_open(trim('geom/optimization.log'), g_opt%syst%namespace, &
1131 action = 'write', position = 'append')
1132
1133 if (geom_iter == 1) then
1134 if (bitand(g_opt%type, go_cell) /= 0) then
1135 write(iunit, '(a10,5(5x,a20),a)') '# iter','energy [' // trim(units_abbrev(units_out%energy)) // ']', &
1136 'max_force [' // trim(units_abbrev(units_out%force)) // ']',&
1137 ' max_dr [' // trim(units_abbrev(units_out%length)) // ']', &
1138 ' a, b, c ['// trim(units_abbrev(units_out%length)) // ']', &
1139 ' volume ['// trim(units_abbrev(units_out%length**3)) // ']',&
1140 ' alpha, beta, gamma [degrees]'
1141 else
1142 write(iunit, '(a10,3(5x,a20))') '# iter','energy [' // trim(units_abbrev(units_out%energy)) // ']', &
1143 'max_force [' // trim(units_abbrev(units_out%force)) // ']',&
1144 ' max_dr [' // trim(units_abbrev(units_out%length)) // ']'
1145 end if
1146 end if
1147
1148 if (bitand(g_opt%type, go_cell) /= 0) then
1149 write(iunit, '(i10,10f25.15)') geom_iter, units_from_atomic(units_out%energy, energy), &
1150 units_from_atomic(units_out%force,maxdf), &
1151 units_from_atomic(units_out%length,maxdx), &
1152 units_from_atomic(units_out%length,norm2(g_opt%ions%latt%rlattice(1:3, 1))),&
1153 units_from_atomic(units_out%length,norm2(g_opt%ions%latt%rlattice(1:3, 2))),&
1154 units_from_atomic(units_out%length,norm2(g_opt%ions%latt%rlattice(1:3, 3))),&
1155 units_from_atomic(units_out%length**3, g_opt%ions%latt%rcell_volume), &
1156 g_opt%ions%latt%alpha, g_opt%ions%latt%beta, g_opt%ions%latt%gamma
1157 else
1158 write(iunit, '(i10,3f25.15)') geom_iter, units_from_atomic(units_out%energy, energy), &
1159 units_from_atomic(units_out%force,maxdf), &
1160 units_from_atomic(units_out%length,maxdx)
1161 end if
1162
1163 call io_close(iunit)
1164 end if
1165
1166 call messages_new_line()
1168
1169 call messages_write("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", new_line = .true.)
1170
1171 call messages_write("+++++++++++++++++++++ MINIMIZATION ITER #:")
1172 call messages_write(geom_iter, fmt = "I5")
1173 call messages_write(" ++++++++++++++++++++++", new_line = .true.)
1174
1175 call messages_write(" Energy = ")
1176 call messages_write(energy, units = units_out%energy, fmt = "es15.8,1x", print_units = .true., new_line = .true.)
1177
1178 if (g_opt%periodic_dim == 0) then
1179 if (maxdf > m_zero) then
1180 call messages_write(" Max force = ")
1181 call messages_write(maxdf, units = units_out%force, fmt = "f18.10,1x", print_units = .true., new_line = .true.)
1182 end if
1183
1184 call messages_write(" Max dr = ")
1185 call messages_write(maxdx, units = units_out%length, fmt = "f18.10,1x", print_units = .true., new_line = .true.)
1186 else
1187 if (maxdf > m_zero) then
1188 call messages_write(" Max reduced force = ")
1189 call messages_write(maxdf, fmt = "f16.10,1x", print_units = .false., new_line = .true.)
1190 end if
1191
1192 call messages_write(" Max reduced dr = ")
1193 call messages_write(maxdx, fmt = "f16.10,1x", print_units = .false., new_line = .true.)
1194 end if
1195
1196 call messages_write("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", new_line = .true.)
1197 call messages_write("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", new_line = .true.)
1198 call messages_new_line()
1199 call messages_new_line()
1200 call messages_info()
1201
1202 pop_sub(write_iter_info)
1203 end subroutine write_iter_info
1204
1205 ! ---------------------------------------------------------
1207 subroutine to_coords(gopt, coords)
1208 type(geom_opt_t), intent(in) :: gopt
1209 real(real64), intent(out) :: coords(:)
1210
1211 integer :: iatom, idir, jdir, icoord
1212 real(real64) :: tmp_pos(gopt%dim), strain(g_opt%periodic_dim,g_opt%periodic_dim)
1213
1214 push_sub(to_coords)
1215
1216 icoord = 1
1217 ! Ion dynamics
1218 if (bitand(g_opt%type, go_ions) /= 0) then
1219 do iatom = 1, gopt%ions%natoms
1220 if (gopt%fixed_atom == iatom) cycle
1221 if (gopt%ions%fixed(iatom)) cycle
1222 tmp_pos = gopt%ions%pos(1:gopt%dim, iatom)
1223 if (gopt%fixed_atom > 0) tmp_pos = tmp_pos - gopt%ions%pos(1:gopt%dim, gopt%fixed_atom)
1224 tmp_pos = gopt%ions%latt%cart_to_red(tmp_pos)
1225 do idir = 1, gopt%dim
1226 coords(icoord) = tmp_pos(idir)
1227 icoord = icoord + 1
1228 end do
1229 end do
1230 end if
1231
1232 ! Cell dynamics
1233 if (bitand(g_opt%type, go_cell) /= 0) then
1234 ! We compute the change in the right stretch tensor U, defined as h = U h_0.
1235 ! Only the periodic block of the lattice is relaxed; the non-periodic (e.g. vacuum)
1236 ! direction is left untouched, which is essential for 2D systems.
1237 strain = matmul(gopt%ions%latt%rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim), g_opt%inv_initial_rlattice)
1238 do idir = 1, g_opt%periodic_dim
1239 do jdir = idir, g_opt%periodic_dim
1240 coords(icoord) = strain(idir, jdir)
1241 icoord = icoord + 1
1242 end do
1243 end do
1244 end if
1245
1246 ! Volume dynamics
1247 if (bitand(g_opt%type, go_volume) /= 0) then
1248 do idir = 1, g_opt%periodic_dim
1249 coords(icoord) = norm2(gopt%ions%latt%rlattice(1:g_opt%periodic_dim, idir))/g_opt%initial_length(idir)
1250 icoord = icoord + 1
1251 end do
1252 end if
1253
1254
1255 pop_sub(to_coords)
1256 end subroutine to_coords
1257
1258 ! ---------------------------------------------------------
1260 subroutine to_grad(gopt, grad)
1261 type(geom_opt_t), intent(in) :: gopt
1262 real(real64), intent(out) :: grad(:)
1263
1264 integer :: iatom, idir, jdir, icoord
1265 real(real64) :: tmp_force(1:gopt%dim)
1266
1267 push_sub(to_grad)
1268
1269 icoord = 1
1270 ! Ion dynamics
1271 if (bitand(g_opt%type, go_ions) /= 0) then
1272 do iatom = 1, gopt%ions%natoms
1273 if (gopt%fixed_atom == iatom) cycle
1274 if (gopt%ions%fixed(iatom)) cycle
1275 do idir = 1, gopt%dim
1276 if (abs(gopt%ions%atom(iatom)%c(idir)) <= m_epsilon) then
1277 tmp_force(idir) = -gopt%ions%tot_force(idir, iatom)
1278 else
1279 tmp_force(idir) = m_zero
1280 end if
1281 if (gopt%fixed_atom > 0) then
1282 tmp_force(idir) = tmp_force(idir) + gopt%ions%tot_force(idir, gopt%fixed_atom)
1283 end if
1284 end do
1285 tmp_force = gopt%ions%latt%cart_to_red(tmp_force)
1286 do idir = 1, gopt%dim
1287 grad(icoord) = tmp_force(idir)
1288 icoord = icoord + 1
1289 end do
1290 end do
1291 end if
1292
1293 ! Cell dynamics
1294 if (bitand(g_opt%type, go_cell) /= 0) then
1295 do idir = 1, g_opt%periodic_dim
1296 do jdir = idir, g_opt%periodic_dim
1297 grad(icoord) = -g_opt%cell_force(idir, jdir)
1298 icoord = icoord + 1
1299 end do
1300 end do
1301 end if
1303 ! Volume dynamics
1304 if (bitand(g_opt%type, go_volume) /= 0) then
1305 do idir = 1, g_opt%periodic_dim
1306 grad(icoord) = -g_opt%cell_force(idir, 1)
1307 icoord = icoord + 1
1308 end do
1309 end if
1310
1311
1312 pop_sub(to_grad)
1313 end subroutine to_grad
1314
1315 ! ---------------------------------------------------------
1317 subroutine from_coords(gopt, coords)
1318 type(geom_opt_t), intent(inout) :: gopt
1319 real(real64), intent(in) :: coords(:)
1320
1321 integer :: iatom, idir, jdir, icoord
1322 real(real64) :: tmp_pos(gopt%dim, gopt%ions%natoms), strain(g_opt%periodic_dim,g_opt%periodic_dim)
1323 real(real64) :: eigenvalues(g_opt%periodic_dim)
1324
1325 push_sub(from_coords)
1326
1327 ! Get the new reduced atomic coordinates
1328 tmp_pos = m_zero
1329 icoord = 1
1330 ! Ion dynamics
1331 if (bitand(g_opt%type, go_ions) /= 0) then
1332 do iatom = 1, gopt%ions%natoms
1333 if (gopt%fixed_atom == iatom) cycle
1334 if (gopt%ions%fixed(iatom)) cycle
1335 do idir = 1, gopt%dim
1336 tmp_pos(idir, iatom) = coords(icoord)
1337 icoord = icoord + 1
1338 end do
1339 end do
1340 else
1341 do iatom = 1, gopt%ions%natoms
1342 tmp_pos(:, iatom) = gopt%ions%latt%cart_to_red(gopt%ions%pos(:, iatom))
1343 end do
1344 end if
1345
1346 ! Updating the lattice vectors
1347 if (bitand(g_opt%type, go_cell) /= 0) then
1348 do idir = 1, g_opt%periodic_dim
1349 do jdir = idir, g_opt%periodic_dim
1350 strain(idir, jdir) = coords(icoord)
1351 icoord = icoord + 1
1352 end do
1353 end do
1354 call upper_triangular_to_hermitian(g_opt%periodic_dim, strain)
1356 ! Get the new lattice vectors from the new right stretch tensor U
1357 ! The strain tensor is defined as A = U * A_0.
1358 ! Only the periodic block is updated; the non-periodic (e.g. vacuum) lattice
1359 ! direction is preserved, which is essential for 2D systems (otherwise the
1360 ! vacuum direction would be corrupted/collapse).
1361 gopt%ions%latt%rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim) = matmul(strain, g_opt%initial_rlattice)
1362
1363 ! Sanity check: the right stretch tensor U must remain symmetric positive-definite.
1364 ! Note: lalg_eigensolve overwrites strain with the eigenvectors, but strain is no longer
1365 ! needed below, so this is safe.
1366 call lalg_eigensolve(g_opt%periodic_dim, strain, eigenvalues)
1367 assert(all(eigenvalues > m_zero))
1368 end if
1369
1370 ! Updating the lattice vectors
1371 if (bitand(g_opt%type, go_volume) /= 0) then
1372 do idir = 1, g_opt%periodic_dim
1373 gopt%ions%latt%rlattice(1:g_opt%periodic_dim, idir) = coords(icoord) &
1374 * gopt%initial_rlattice(1:g_opt%periodic_dim, idir)
1375 icoord = icoord + 1
1376 end do
1377 end if
1378
1379 ! Symmetrize and update the lattice vectors
1380 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0) then
1381 call g_opt%syst%gr%symmetrizer%symmetrize_lattice_vectors(g_opt%periodic_dim, g_opt%initial_rlattice, &
1382 gopt%ions%latt%rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim), gopt%symmetrize)
1383 call gopt%ions%update_lattice_vectors(gopt%ions%latt, gopt%symmetrize)
1384 end if
1385
1386 ! Ion dynamics
1387 if (bitand(g_opt%type, go_ions) /= 0) then
1388 ! To Cartesian coordinates
1389 do iatom = 1, gopt%ions%natoms
1390 if (gopt%fixed_atom == iatom) cycle
1391 if (gopt%ions%fixed(iatom)) cycle
1392 tmp_pos(:, iatom) = gopt%ions%latt%red_to_cart(tmp_pos(:, iatom))
1393 do idir = 1, gopt%dim
1394 if (abs(gopt%ions%atom(iatom)%c(idir)) <= m_epsilon) then
1395 gopt%ions%pos(idir, iatom) = tmp_pos(idir, iatom)
1396 end if
1397 end do
1398 if (gopt%fixed_atom > 0) then
1399 gopt%ions%pos(:, iatom) = gopt%ions%pos(:, iatom) + gopt%ions%pos(:, gopt%fixed_atom)
1400 end if
1401 end do
1402 else
1403 do iatom = 1, gopt%ions%natoms
1404 gopt%ions%pos(:, iatom) = gopt%ions%latt%red_to_cart(tmp_pos(:, iatom))
1405 end do
1406 end if
1407
1408 if (gopt%symmetrize) then
1409 call gopt%ions%symmetrize_atomic_coord()
1410 end if
1411
1412 if (bitand(g_opt%type, go_cell) /= 0) then
1413 call gopt%ions%print_spacegroup()
1414 end if
1415
1416 pop_sub(from_coords)
1417 end subroutine from_coords
1418
1419 ! ---------------------------------------------------------
1421 subroutine write_iter_info_ng(geom_iter, size, energy, maxdx, coords)
1422 integer, intent(in) :: geom_iter
1423 integer, intent(in) :: size
1424 real(real64), intent(in) :: energy, maxdx
1425 real(real64), intent(in) :: coords(size)
1426
1427 push_sub(write_iter_info_ng)
1428 call write_iter_info(geom_iter, size, energy, maxdx, -m_one, coords)
1429
1430 pop_sub(write_iter_info_ng)
1431 end subroutine write_iter_info_ng
1432
1433
1434 ! ---------------------------------------------------------
1436 subroutine ml_preopt(g_opt)
1437 type(geom_opt_t), intent(inout) :: g_opt
1438
1439 integer :: iunit, iatom, idir, command_status, command_exit
1440 logical :: has_constrains
1441 character(len=MAX_PATH_LEN) :: cmd, mattersim_share, mattersim_python
1442 character(len=64) :: constrains_arg
1443
1444 push_sub(ml_preopt)
1445 command_status = 0
1446 command_exit = 0
1447
1448 call io_rm('ml_cell.xyz', g_opt%syst%namespace)
1449
1450 if (g_opt%ions%space%is_periodic()) then
1451 call write_extended_xyz_file('.', 'work-geom', g_opt%ions%space, g_opt%ions%latt, g_opt%ions%pos, g_opt%ions%atom, &
1452 g_opt%syst%gr%box, g_opt%syst%namespace)
1453 else
1454 call g_opt%ions%write_xyz('./work-geom', append = .false.)
1455 end if
1456
1457 ! MatterSim relaxes every atom, so the fixed coordinates (GOConstrains, GOCenter
1458 ! and fixed species) have to be passed explicitly to the pre-optimizer.
1459 has_constrains = any(g_opt%ions%fixed) .or. g_opt%fixed_atom > 0
1460 do iatom = 1, g_opt%ions%natoms
1461 has_constrains = has_constrains .or. any(g_opt%ions%atom(iatom)%c /= 0)
1462 end do
1463
1464 constrains_arg = ''
1465 if (has_constrains) then
1466 constrains_arg = ' --constrains ml_constrains.dat'
1467 if (mpi_world%is_root()) then
1468 iunit = io_open('ml_constrains.dat', global_namespace, action='write')
1469 do iatom = 1, g_opt%ions%natoms
1470 if (g_opt%ions%fixed(iatom) .or. iatom == g_opt%fixed_atom) then
1471 write(iunit, '(3(1x,i1))') (1, idir = 1, g_opt%ions%space%dim)
1472 else
1473 write(iunit, '(3(1x,i1))') (g_opt%ions%atom(iatom)%c(idir), idir = 1, g_opt%ions%space%dim)
1474 end if
1475 end do
1476 call io_close(iunit)
1477 end if
1478 end if
1479
1480 call mattersim_paths(mattersim_share, mattersim_python, g_opt%syst%namespace)
1481 if (mpi_world%is_root()) then
1482 ! Execute a system call for the current geometry
1483 ! -I isolates the venv python from any external PYTHONPATH/PYTHONHOME
1484 write(cmd, '(a,1x,es24.16,1x,i0,1x,l1,a)') &
1485 trim(mattersim_python) // " -I " // trim(mattersim_share) &
1486 // "/scripts/run_mattersim_preopt.py work-geom.xyz ml_cell.xyz " // trim(mattersim_share), &
1487 g_opt%pressure, g_opt%type, g_opt%symmetrize, trim(constrains_arg)
1488 call execute_command_line(trim(cmd), exitstat=command_exit, cmdstat=command_status)
1489 if (command_status == 0) command_status = command_exit
1490 end if
1491
1492 call mpi_world%bcast(command_status, 1, mpi_integer, 0)
1493 if (command_status /= 0) then
1494 write(message(1), '(a,i0)') 'MatterSim pre-optimization failed with exit status ', command_status
1495 call messages_fatal(1, namespace=g_opt%syst%namespace)
1496 end if
1497
1498 call mpi_world%barrier()
1499
1500 ! Read the result from MatterSim
1501 iunit = io_open('ml_cell.xyz', global_namespace, action='read')
1502 do iatom = 1, g_opt%ions%natoms
1503 read(iunit,*) g_opt%ions%pos(:, iatom)
1504 end do
1505 read(iunit, *) ! skip comment line
1506 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0) then
1507 do idir = 1, 3
1508 read(iunit,*) g_opt%ions%latt%rlattice(:, idir)
1509 end do
1510 end if
1511 call io_close(iunit)
1512
1513 call g_opt%ions%update_lattice_vectors(g_opt%ions%latt, g_opt%symmetrize)
1514
1515 if (debug%info) then
1516 call g_opt%ions%print_spacegroup()
1517 end if
1518
1519 call g_opt%ions%fold_atoms_into_cell()
1520
1521 ! Update lattice vectors and regenerate grid
1522 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0 ) then
1523 call electrons_lattice_vectors_update(g_opt%syst%namespace, g_opt%syst%gr, &
1524 g_opt%syst%space, g_opt%syst%hm%psolver, g_opt%syst%hm%kpoints, &
1525 g_opt%syst%mc, g_opt%syst%st%qtot, g_opt%ions%latt)
1526 end if
1527
1528 call hamiltonian_elec_epot_generate(g_opt%hm, g_opt%syst%namespace, g_opt%syst%space, g_opt%syst%gr, &
1529 g_opt%ions, g_opt%syst%ext_partners, g_opt%st)
1530
1531 call g_opt%ions%print_spacegroup()
1532
1533 pop_sub(ml_preopt)
1534 end subroutine ml_preopt
1535
1536end module geom_opt_oct_m
1537
1538!! Local Variables:
1539!! mode: f90
1540!! coding: utf-8
1541!! End:
subroutine init_(fromscratch)
Definition: geom_opt.F90:405
subroutine end_()
Definition: geom_opt.F90:927
Note that lalg_determinant and lalg_inverse are just wrappers over the same routine.
Definition: lalg_adv.F90:202
type(debug_t), save, public debug
Definition: debug.F90:156
This module implements a calculator for the density and defines related functions.
Definition: density.F90:122
subroutine, public density_calc(st, gr, density, istin)
Computes the density from the orbitals in st.
Definition: density.F90:653
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)
Definition: forces.F90:546
subroutine, public geom_opt_run(system, from_scratch)
Definition: geom_opt.F90:243
integer, parameter go_calculator_mattersim
Definition: geom_opt.F90:211
subroutine calc_point_ng(size, coords, objective)
Same as calc_point, but without the gradients. No intents here is unfortunately required because the ...
Definition: geom_opt.F90:1168
subroutine to_grad(gopt, grad)
Transfer data from the forces to the work array for the gradients (grad)
Definition: geom_opt.F90:1356
integer, parameter go_cell
Definition: geom_opt.F90:206
integer, parameter minwhat_forces
Definition: geom_opt.F90:202
subroutine write_iter_info_ng(geom_iter, size, energy, maxdx, coords)
Same as write_iter_info, but without the gradients.
Definition: geom_opt.F90:1517
subroutine ml_preopt(g_opt)
Calls a python script to do a pre-optimization based on machine-learned interatomic potential.
Definition: geom_opt.F90:1532
subroutine write_iter_info(geom_iter, size, energy, maxdx, maxdf, coords)
Output the information after each iteration of the geometry optimization.
Definition: geom_opt.F90:1193
subroutine calc_point(size, coords, objective, getgrad, df)
Note: you might think it would be better to change the arguments with '(size)' below to '(:)'....
Definition: geom_opt.F90:951
subroutine to_coords(gopt, coords)
Transfer the data from the data structures to the work array (coords)
Definition: geom_opt.F90:1303
integer, parameter go_volume
Definition: geom_opt.F90:206
subroutine from_coords(gopt, coords)
Transfer the data from the work array (coords) to the actual data structures.
Definition: geom_opt.F90:1413
subroutine geom_opt_run_legacy(sys, fromscratch)
Definition: geom_opt.F90:261
subroutine mattersim_paths(mattersim_share, mattersim_python, namespace)
Definition: geom_opt.F90:219
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_epsilon
Definition: global.F90:216
type(conf_t), public conf
Global instance of Octopus configuration.
Definition: global.F90:190
real(real64), parameter, public m_half
Definition: global.F90:206
real(real64), parameter, public m_one
Definition: global.F90:201
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, namespace, total_forces)
Definition: io.F90:116
subroutine, public io_close(iunit, grp)
Definition: io.F90:467
subroutine, public io_rm(fname, namespace)
Definition: io.F90:392
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:361
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:402
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 ...
Definition: lalg_adv.F90:521
subroutine, public lcao_run(namespace, space, gr, ions, ext_partners, st, ks, hm, st_start, lmm_r, known_lower_bound)
Definition: lcao.F90:769
System information (time, memory, sysname)
Definition: loct.F90:117
subroutine, public loct_strerror(errno, res)
Definition: loct.F90:384
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1068
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1000
subroutine, public messages_new_line()
Definition: messages.F90:1089
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:691
subroutine, public messages_experimental(name, namespace)
Definition: messages.F90:1040
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
integer, parameter, public minmethod_nmsimplex
Definition: minimizer.F90:139
integer, parameter, public minmethod_fire
Definition: minimizer.F90:139
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:276
This module implements the basic mulsisystem class, a container system for other systems.
type(namespace_t), public global_namespace
Definition: namespace.F90:135
logical function, public parse_is_defined(namespace, name)
Definition: parser.F90:463
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
Definition: restart.F90:156
integer, parameter, public restart_type_dump
Definition: restart.F90:184
integer, parameter, public restart_type_load
Definition: restart.F90:184
subroutine, public scf_set_lower_bound_is_known(scf, known_lower_bound)
Set the flag lower_bound_is_known.
Definition: scf.F90:1692
subroutine, public scf_print_mem_use(namespace)
Definition: scf.F90:1572
subroutine, public scf_mix_clear(scf)
Definition: scf.F90:592
integer, parameter, public verb_compact
Definition: scf.F90:206
subroutine, public scf_init(scf, namespace, gr, ions, st, mc, hm, space)
Definition: scf.F90:259
subroutine, public scf_end(scf)
Definition: scf.F90:562
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.
Definition: scf.F90:843
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.
Definition: unit.F90:134
character(len=20) pure function, public units_abbrev(this)
Definition: unit.F90:225
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)
Definition: v_ks.F90:719
subroutine, public v_ks_h_setup(namespace, space, gr, ions, ext_partners, st, ks, hm, calc_eigenval, calc_current)
Definition: v_ks.F90:665
An abstract type for all electron species.
Class describing the electron system.
Definition: electrons.F90:222
Container class for lists of system_oct_m::system_t.
int true(void)