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
97
98 logical :: poscar_output = .false.
99
100 end type geom_opt_t
101
102 type(geom_opt_t), save :: g_opt
103
104 integer, parameter :: &
105 MINWHAT_ENERGY = 1, &
107
108 integer, parameter :: &
109 GO_IONS = 1, &
110 go_cell = 2, &
111 go_volume = 4
112
113contains
114
115 ! ---------------------------------------------------------
116 subroutine geom_opt_run(system, from_scratch)
117 class(*), intent(inout) :: system
118 logical, intent(inout) :: from_scratch
119
120 push_sub(geom_opt_run)
121
122 select type (system)
123 class is (multisystem_basic_t)
124 message(1) = "CalculationMode = go not implemented for multi-system calculations"
125 call messages_fatal(1, namespace=system%namespace)
126 type is (electrons_t)
127 call geom_opt_run_legacy(system, from_scratch)
128 end select
129
130 pop_sub(geom_opt_run)
131 end subroutine geom_opt_run
132
133 ! ---------------------------------------------------------
134 subroutine geom_opt_run_legacy(sys, fromscratch)
135 type(electrons_t), target, intent(inout) :: sys
136 logical, intent(inout) :: fromscratch
137
138 integer :: ierr
139 real(real64), allocatable :: coords(:)
140 real(real64) :: energy
141
142 real(real64), allocatable :: mass(:)
143 integer :: iatom, imass
144 type(restart_t) :: restart_load
145 logical :: known_lower_bound
146
147 push_sub(geom_opt_run_legacy)
148
149 ! For 1D-periodic systems the ion-ion interaction (hence the forces) and the stress
150 ! tensor are not implemented.
151 if (sys%space%periodic_dim == 1) then
152 message(1) = "Geometry optimization is not allowed for systems periodic in 1D, "
153 message(2) = "as the ion-ion interaction and the stress tensor are not available."
154 call messages_fatal(2, namespace=sys%namespace)
155 end if
156
157 if (sys%space%periodic_dim == 2) then
158 call messages_experimental("Geometry optimization for 2D-periodic systems", namespace=sys%namespace)
159 end if
160
162 if (sys%hm%pcm%run_pcm) then
163 call messages_not_implemented("PCM for CalculationMode /= gs or td", namespace=sys%namespace)
164 end if
166 if (sys%kpoints%use_symmetries) then
167 call messages_experimental("KPoints symmetries with CalculationMode = go", namespace=sys%namespace)
168 end if
170 call init_(fromscratch)
172 ! load wavefunctions
173 if (.not. fromscratch) then
174 call restart_load%init(sys%namespace, restart_gs, restart_type_load, sys%mc, ierr, mesh=sys%gr)
175 if (ierr == 0) then
176 call states_elec_load(restart_load, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
177 fixed_occ=.false., ierr=ierr)
178 end if
179 call restart_load%end()
180 if (ierr /= 0) then
181 message(1) = "Unable to read wavefunctions: Starting from scratch."
182 call messages_warning(1, namespace=sys%namespace)
183 fromscratch = .true.
184 end if
185 end if
187 call scf_init(g_opt%scfv, sys%namespace, sys%gr, sys%ions, sys%st, sys%mc, sys%hm, sys%space)
189 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0) then
190 if (.not. g_opt%scfv%calc_stress) then
191 message(1) = "In order to optimize the cell, one needs to set SCFCalculateStress = yes."
192 call messages_fatal(1, namespace=sys%namespace)
193 end if
194 end if
195
196 if (fromscratch) then
197 call lcao_run(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm, &
198 lmm_r = g_opt%scfv%lmm_r, known_lower_bound=known_lower_bound)
199 call scf_set_lower_bound_is_known(g_opt%scfv, known_lower_bound)
200 else
201 ! setup Hamiltonian
202 message(1) = 'Info: Setting up Hamiltonian.'
203 call messages_info(1, namespace=sys%namespace)
204 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
205 call scf_set_lower_bound_is_known(g_opt%scfv, .true.)
206 end if
207
208 g_opt%symmetrize = sys%kpoints%use_symmetries .or. sys%st%symmetrize_density
209
210 !Initial point
211 safe_allocate(coords(1:g_opt%size))
212 call to_coords(g_opt, coords)
213
214 if (sys%st%pack_states .and. sys%hm%apply_packed()) call sys%st%pack()
215
216 !Minimize
217 select case (g_opt%method)
219 call minimize_multidim_nograd(g_opt%method, g_opt%size, coords, g_opt%step,&
220 g_opt%toldr, g_opt%max_iter, &
221 calc_point_ng, write_iter_info_ng, energy, ierr)
222 case (minmethod_fire)
223
224 safe_allocate(mass(1:g_opt%size))
225 mass = g_opt%fire_mass
226 imass = 1
227 do iatom = 1, sys%ions%natoms
228 if (g_opt%fixed_atom == iatom) cycle
229 if (g_opt%ions%fixed(iatom)) cycle
230 if (g_opt%fire_mass <= m_zero) mass(imass:imass + 2) = sys%ions%mass(iatom)
231 imass = imass + g_opt%dim
232 end do
233
234 !TODO: add variable to use Euler integrator
235 call minimize_fire(g_opt%size, g_opt%ions%space%dim, coords, g_opt%step, g_opt%tolgrad, &
236 g_opt%max_iter, calc_point, write_iter_info, energy, ierr, mass, integrator=g_opt%fire_integrator)
237 safe_deallocate_a(mass)
238
239 case default
240 call minimize_multidim(g_opt%method, g_opt%size, coords, g_opt%step ,&
241 g_opt%line_tol , g_opt%tolgrad, g_opt%toldr, g_opt%max_iter, &
242 calc_point, write_iter_info, energy, ierr)
243 end select
244
245 if (ierr == 1025) then
246 ! not a GSL error, set by our minimize routines, so we must handle it separately
247 message(1) = "Reached maximum number of iterations allowed by GOMaxIter."
248 call messages_info(1, namespace=sys%namespace)
249 else if (ierr /= 0 .and. g_opt%method /= minmethod_fire) then
250 message(1) = "Error occurred during the GSL minimization procedure:"
251 call loct_strerror(ierr, message(2))
252 call messages_fatal(2, namespace=sys%namespace)
253 end if
254
255 if (sys%st%pack_states .and. sys%hm%apply_packed()) call sys%st%unpack()
256
257
258 ! print out geometry
259 message(1) = "Writing final coordinates to min.xyz"
260 call messages_info(1, namespace=sys%namespace)
261 call from_coords(g_opt, coords)
262 call g_opt%ions%write_xyz('./min')
263
264 safe_deallocate_a(coords)
265 call scf_end(g_opt%scfv)
266 ! Because g_opt has the "save" attribute, we need to explicitly empty the criteria list here, or there will be a memory leak.
267 call g_opt%scfv%criterion_list%empty()
268 call end_()
269
270 pop_sub(geom_opt_run_legacy)
271 contains
272
273 ! ---------------------------------------------------------
274 subroutine init_(fromscratch)
275 logical, intent(inout) :: fromscratch
276
277 logical :: center, does_exist
278 integer :: iter, iatom, idir
279 character(len=100) :: filename
280 real(real64) :: default_toldr
281 real(real64) :: default_step
282 type(read_coords_info) :: xyz
283
284 push_sub(geom_opt_run_legacy.init_)
285
286 if (sys%space%is_periodic()) then
287 call messages_experimental('Geometry optimization for periodic systems', namespace=sys%namespace)
288 end if
289
290 !%Variable GOType
291 !%Type flag
292 !%Default ions
293 !%Section Calculation Modes::Geometry Optimization
294 !%Description
295 !% This variable defines which parameters are allowed to change during the optimization.
296 !% Multiple options can be chosen e.g. “ion_positions + cell_shape”.
297 !% Only one type of lattice vectors relaxation is possible.
298 !%Option ion_positions 1
299 !% Relax position of ions based on the forces acting on the ions.
300 !%Option cell_shape 2
301 !% Relax cell shape. This changes lattice vector lengths and directions
302 !% based on the stress acting on the lattice vectors.
303 !% See for instance Wentzcovitch, PRB 44, 2358 (1991).
304 !%Option cell_volume 4
305 !% Relax cell volume. Only allow for rescaling the lengths of lattice vectors.
306 !% This is a simplication of the option cell_shape, where only a diagonal strain is allowed.
307 !%End
308
309 call parse_variable(sys%namespace, 'GOType', go_ions, g_opt%type)
310 if (.not. varinfo_valid_option('GOType', g_opt%type, is_flag=.true.)) then
311 call messages_input_error(sys%namespace, 'GOType')
312 end if
313
314 write(message(1),'(a)') 'Input: [GOType = '
315 if (bitand(g_opt%type, go_ions) /= 0) then
316 write(message(1),'(a,1x,a)') trim(message(1)), 'ion_positions'
317 end if
318 if (bitand(g_opt%type, go_cell) /= 0) then
319 if (len_trim(message(1)) > 16) then
320 write(message(1),'(a,1x,a)') trim(message(1)), '+'
321 end if
322 write(message(1),'(a,1x,a)') trim(message(1)), 'cell_shape'
323 end if
324 if (bitand(g_opt%type, go_volume) /= 0) then
325 if (len_trim(message(1)) > 16) then
326 write(message(1),'(a,1x,a)') trim(message(1)), '+'
327 end if
328 write(message(1),'(a,1x,a)') trim(message(1)), 'cell_volume'
329 end if
330 write(message(1),'(2a)') trim(message(1)), ']'
331 call messages_info(1, namespace=sys%namespace)
332
333 if (bitand(g_opt%type, go_volume) /= 0 .and. bitand(g_opt%type, go_cell) /= 0) then
334 message(1) = "Cell and volume optimization cannot be used simultaneously."
335 call messages_fatal(1, namespace=sys%namespace)
336 end if
337
338
339 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0) then
340 if (parse_is_defined(sys%namespace, 'TDMomentumTransfer') .or. &
341 parse_is_defined(sys%namespace, 'TDReducedMomentumTransfer')) then
342 call messages_not_implemented("Cell dynamics with TDMomentumTransfer and TDReducedMomentumTransfer")
343 end if
344 end if
345
346 do iatom = 1, sys%ions%natoms
347 select type(spec=>sys%ions%atom(iatom)%species)
348 class is(allelectron_t)
349 write(message(1),'(a)') "Geometry optimization for all-electron potential is not implemented."
350 call messages_fatal(1)
351 end select
352 end do
353
354
355 call states_elec_allocate_wfns(sys%st, sys%gr, packed=.true.)
356
357 ! shortcuts
358 g_opt%mesh => sys%gr
359 g_opt%ions => sys%ions
360 g_opt%st => sys%st
361 g_opt%hm => sys%hm
362 g_opt%syst => sys
363 g_opt%dim = sys%space%dim
364 g_opt%periodic_dim = sys%space%periodic_dim
365
366 g_opt%size = 0
367 ! Ion dyamics
368 if (bitand(g_opt%type, go_ions) /= 0) then
369 g_opt%size = g_opt%dim * g_opt%ions%natoms
370 end if
371
372 ! Cell dynamics
373 if (bitand(g_opt%type, go_cell) /= 0) then
374 g_opt%size = g_opt%size + (g_opt%periodic_dim +1) * g_opt%periodic_dim / 2
375 safe_allocate(g_opt%cell_force(1:g_opt%periodic_dim, 1:g_opt%periodic_dim))
376 end if
377
378 ! Volume dynamics
379 if (bitand(g_opt%type, go_volume) /= 0) then
380 g_opt%size = g_opt%size + g_opt%periodic_dim
381 safe_allocate(g_opt%cell_force(1:g_opt%periodic_dim, 1:1))
382 ! Store the length of the original lattic vectors, to work with reduced lengthes
383 safe_allocate(g_opt%initial_length(1:g_opt%periodic_dim))
384 do idir = 1, g_opt%periodic_dim
385 g_opt%initial_length(idir) = norm2(g_opt%ions%latt%rlattice(1:g_opt%periodic_dim, idir))
386 end do
387 end if
388
389 ! Store the initial lattice vectors and the inverse matrix
390 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0) then
391 safe_allocate(g_opt%initial_rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim))
392 g_opt%initial_rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim) &
393 = g_opt%ions%latt%rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim)
394 safe_allocate(g_opt%inv_initial_rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim))
395 g_opt%inv_initial_rlattice(:, :) = g_opt%initial_rlattice(:, :)
396 call lalg_inverse(g_opt%periodic_dim, g_opt%inv_initial_rlattice, 'dir')
397 end if
398
399 if(g_opt%ions%space%is_periodic()) then
400 call parse_variable(sys%namespace, 'HydrostaticPressure', m_zero, g_opt%pressure)
401 end if
402
403 !%Variable GOCenter
404 !%Type logical
405 !%Default no
406 !%Section Calculation Modes::Geometry Optimization
407 !%Description
408 !% (Experimental) If set to yes, Octopus centers the geometry at
409 !% every optimization step. It also reduces the degrees of
410 !% freedom of the optimization by using the translational
411 !% invariance.
412 !%End
413 call parse_variable(sys%namespace, 'GOCenter', .false., center)
414
415 if (center .and. bitand(g_opt%type, go_ions) /= 0) then
416 g_opt%fixed_atom = 1
417 g_opt%size = g_opt%size - g_opt%dim
418 call messages_experimental('GOCenter', namespace=sys%namespace)
419 end if
420
421 !Check if atoms are allowed to move and redifine g_opt%size
422 do iatom = 1, g_opt%ions%natoms
423 if (g_opt%ions%fixed(iatom) .and. bitand(g_opt%type, go_ions) /= 0) then
424 g_opt%size = g_opt%size - g_opt%dim
425 end if
426 end do
427
428 assert(g_opt%size > 0)
429
430 !%Variable GOMethod
431 !%Type integer
432 !%Default fire
433 !%Section Calculation Modes::Geometry Optimization
434 !%Description
435 !% Method by which the minimization is performed. For more information see the
436 !% <a href=http://www.gnu.org/software/gsl/manual/html_node/Multidimensional-Minimization.html>
437 !% GSL documentation</a>.
438 !%Option steep 1
439 !% Simple steepest descent.
440 !%Option steep_native -1
441 !% (Experimental) Non-gsl implementation of steepest descent.
442 !%Option cg_fr 2
443 !% Fletcher-Reeves conjugate-gradient algorithm. The
444 !% conjugate-gradient algorithm proceeds as a succession of line
445 !% minimizations. The sequence of search directions is used to build
446 !% up an approximation to the curvature of the function in the
447 !% neighborhood of the minimum.
448 !%Option cg_pr 3
449 !% Polak-Ribiere conjugate-gradient algorithm.
450 !%Option cg_bfgs 4
451 !% Vector Broyden-Fletcher-Goldfarb-Shanno (BFGS) conjugate-gradient algorithm.
452 !% It is a quasi-Newton method which builds up an approximation to the second
453 !% derivatives of the function <i>f</i> using the difference between successive gradient
454 !% vectors. By combining the first and second derivatives, the algorithm is able
455 !% to take Newton-type steps towards the function minimum, assuming quadratic
456 !% behavior in that region.
457 !%Option cg_bfgs2 5
458 !% The bfgs2 version of this minimizer is the most efficient version available,
459 !% and is a faithful implementation of the line minimization scheme described in
460 !% Fletcher, <i>Practical Methods of Optimization</i>, Algorithms 2.6.2 and 2.6.4.
461 !%Option simplex 6
462 !% This is experimental, and in fact, <b>not</b> recommended unless you just want to
463 !% fool around. It is the Nead-Melder simplex algorithm, as implemented in the
464 !% GNU Scientific Library (GSL). It does not make use of the gradients (<i>i.e.</i>, the
465 !% forces) which makes it less efficient than other schemes. It is included here
466 !% for completeness, since it is free.
467 !%Option fire 8
468 !% The FIRE algorithm. See also <tt>GOFireMass</tt> and <tt>GOFireIntegrator</tt>.
469 !% Ref: E. Bitzek, P. Koskinen, F. Gahler, M. Moseler, and P. Gumbsch, <i>Phys. Rev. Lett.</i> <b>97</b>, 170201 (2006).
470 !%End
471 call parse_variable(sys%namespace, 'GOMethod', minmethod_fire, g_opt%method)
472 if (.not. varinfo_valid_option('GOMethod', g_opt%method)) call messages_input_error(sys%namespace, 'GOMethod')
473
474
475 call messages_print_var_option("GOMethod", g_opt%method, namespace=sys%namespace)
476
477 !%Variable GOTolerance
478 !%Type float
479 !%Default 0.001 H/b (0.051 eV/A)
480 !%Section Calculation Modes::Geometry Optimization
481 !%Description
482 !% Convergence criterion, for stopping the minimization. In
483 !% units of force; minimization is stopped when all forces on
484 !% ions are smaller than this criterion, or the
485 !% <tt>GOMinimumMove</tt> is satisfied. If <tt>GOTolerance < 0</tt>,
486 !% this criterion is ignored.
487 !%End
488 call parse_variable(sys%namespace, 'GOTolerance', 0.001_real64, g_opt%tolgrad, units_inp%force)
489
490 !%Variable GOMinimumMove
491 !%Type float
492 !%Section Calculation Modes::Geometry Optimization
493 !%Description
494 !% Convergence criterion, for stopping the minimization. In
495 !% units of length; minimization is stopped when the coordinates
496 !% of all species change less than <tt>GOMinimumMove</tt>, or the
497 !% <tt>GOTolerance</tt> criterion is satisfied.
498 !% If <tt>GOMinimumMove < 0</tt>, this criterion is ignored.
499 !% Default is -1, except 0.001 b with <tt>GOMethod = simplex</tt>.
500 !% Note that if you use <tt>GOMethod = simplex</tt>,
501 !% then you must supply a non-zero <tt>GOMinimumMove</tt>.
502 !%End
503 if (g_opt%method == minmethod_nmsimplex) then
504 default_toldr = 0.001_real64
505 else
506 default_toldr = -m_one
507 end if
508 call parse_variable(sys%namespace, 'GOMinimumMove', default_toldr, g_opt%toldr, units_inp%length)
509
510 if (g_opt%method == minmethod_nmsimplex .and. g_opt%toldr <= m_zero) call messages_input_error(sys%namespace, 'GOMinimumMove')
511
512 !%Variable GOStep
513 !%Type float
514 !%Section Calculation Modes::Geometry Optimization
515 !%Description
516 !% Initial step for the geometry optimizer. The default is 0.5.
517 !% WARNING: in some weird units.
518 !% For the FIRE minimizer, default value is 0.1 fs,
519 !% and corresponds to the initial time-step for the MD.
520 !%End
521 if (g_opt%method /= minmethod_fire) then
522 default_step = m_half
523 call parse_variable(sys%namespace, 'GOStep', default_step, g_opt%step)
524 else
525 default_step = 0.1_real64*unit_femtosecond%factor
526 call parse_variable(sys%namespace, 'GOStep', default_step, g_opt%step, unit = units_inp%time)
527 end if
528
529 !%Variable GOLineTol
530 !%Type float
531 !%Default 0.1
532 !%Section Calculation Modes::Geometry Optimization
533 !%Description
534 !% Tolerance for line-minimization. Applies only to GSL methods
535 !% that use the forces.
536 !% WARNING: in some weird units.
537 !%End
538 call parse_variable(sys%namespace, 'GOLineTol', 0.1_real64, g_opt%line_tol)
539
540 !%Variable GOMaxIter
541 !%Type integer
542 !%Default 200
543 !%Section Calculation Modes::Geometry Optimization
544 !%Description
545 !% Even if the convergence criterion is not satisfied, the minimization will stop
546 !% after this number of iterations.
547 !%End
548 call parse_variable(sys%namespace, 'GOMaxIter', 200, g_opt%max_iter)
549 if (g_opt%max_iter <= 0) then
550 message(1) = "GOMaxIter has to be larger than 0"
551 call messages_fatal(1, namespace=sys%namespace)
552 end if
553
554 !%Variable GOFireMass
555 !%Type float
556 !%Default 1.0 amu
557 !%Section Calculation Modes::Geometry Optimization
558 !%Description
559 !% The Fire algorithm (<tt>GOMethod = fire</tt>) assumes that all degrees of freedom
560 !% are comparable. All the velocities should be on the same
561 !% scale, which for heteronuclear systems can be roughly
562 !% achieved by setting all the atom masses equal, to the value
563 !% specified by this variable.
564 !% By default the mass of a proton is selected (1 amu).
565 !% However, a selection of <tt>GOFireMass = 0.01</tt> can, in manys systems,
566 !% speed up the geometry optimization procedure.
567 !% If <tt>GOFireMass</tt> <= 0, the masses of each
568 !% species will be used.
569 !%End
570 call parse_variable(sys%namespace, 'GOFireMass', m_one*unit_amu%factor, g_opt%fire_mass, unit = unit_amu)
571
572 !%Variable GOFireIntegrator
573 !%Type integer
574 !%Default verlet
575 !%Section Calculation Modes::Geometry Optimization
576 !%Description
577 !% The Fire algorithm (<tt>GOMethod = fire</tt>) uses a molecular dynamics
578 !% integrator to compute new geometries and velocities.
579 !% Currently, two integrator schemes can be selected
580 !%Option euler 0
581 !% The Explicit Euler method.
582 !%Option verlet 1
583 !% The Velocity Verlet algorithm.
584 !%Option semi_implicit_euler 2
585 !% Semi-implicit Euler integration, see J. Guénolé, et al. Computational Materials Science 175 (2020) 109584.
586 !%End
587 call parse_variable(sys%namespace, 'GOFireIntegrator', option__gofireintegrator__verlet, g_opt%fire_integrator)
588
589 call messages_obsolete_variable(sys%namespace, 'GOWhat2Minimize', 'GOObjective')
590
591 !%Variable GOObjective
592 !%Type integer
593 !%Default minimize_energy
594 !%Section Calculation Modes::Geometry Optimization
595 !%Description
596 !% This rather esoteric option allows one to choose which
597 !% objective function to minimize during a geometry
598 !% minimization. The use of this variable may lead to
599 !% inconsistencies, so please make sure you know what you are
600 !% doing.
601 !%Option minimize_energy 1
602 !% Use the total energy as objective function.
603 !%Option minimize_forces 2
604 !% Use <math>\sqrt{\sum_i \left| f_i \right|^2}</math> as objective function.
605 !% Note that in this case one still uses the forces as the gradient of the objective function.
606 !% This is, of course, inconsistent, and may lead to very strange behavior.
607 !%End
608 call parse_variable(sys%namespace, 'GOObjective', minwhat_energy, g_opt%what2minimize)
609 if (.not. varinfo_valid_option('GOObjective', g_opt%what2minimize)) call messages_input_error(sys%namespace, 'GOObjective')
610 call messages_print_var_option("GOObjective", g_opt%what2minimize, namespace=sys%namespace)
611
612
613 !%Variable XYZGOConstrains
614 !%Type string
615 !%Section Calculation Modes::Geometry Optimization
616 !%Description
617 !% <tt>Octopus</tt> will try to read the coordinate-dependent constrains from the XYZ file
618 !% specified by the variable <tt>XYZGOConstrains</tt>.
619 !% Note: It is important for the contrains to maintain the ordering
620 !% in which the atoms were defined in the coordinates specifications.
621 !% Moreover, constrains impose fixed absolute coordinates, therefore
622 !% constrains are not compatible with GOCenter = yes
623 !%End
624
625 !%Variable XSFGOConstrains
626 !%Type string
627 !%Section Calculation Modes::Geometry Optimization
628 !%Description
629 !% Like <tt>XYZGOConstrains</tt> but in XCrySDen format, as in <tt>XSFCoordinates</tt>.
630 !%End
631
632 !%Variable PDBGOConstrains
633 !%Type string
634 !%Section Calculation Modes::Geometry Optimization
635 !%Description
636 !% Like <tt>XYZGOConstrains</tt> but in PDB format, as in <tt>PDBCoordinates</tt>.
637 !%End
638
639 !%Variable GOConstrains
640 !%Type block
641 !%Section Calculation Modes::Geometry Optimization
642 !%Description
643 !% If <tt>XYZGOConstrains</tt>, <tt>PDBConstrains</tt>, and <tt>XSFGOConstrains</tt>
644 !% are not present, <tt>Octopus</tt> will try to fetch the geometry optimization
645 !% contrains from this block. If this block is not present, <tt>Octopus</tt>
646 !% will not set any constrains. The format of this block can be
647 !% illustrated by this example:
648 !%
649 !% <tt>%GOConstrains
650 !% <br>&nbsp;&nbsp;'C' | 1 | 0 | 0
651 !% <br>&nbsp;&nbsp;'O' | &nbsp;1 | 0 | 0
652 !% <br>%</tt>
653 !%
654 !% Coordinates with a constrain value of 0 will be optimized, while
655 !% coordinates with a constrain different from zero will be kept fixed. So,
656 !% in this example the x coordinates of both atoms will remain fixed and the
657 !% distance between the two atoms along the x axis will be constant.
658 !%
659 !% Note: It is important for the constrains to maintain the ordering
660 !% in which the atoms were defined in the coordinates specifications.
661 !% Moreover, constrains impose fixed absolute coordinates, therefore
662 !% constrains are not compatible with GOCenter = yes
663 !%End
664
665 call read_coords_init(xyz)
666 call read_coords_read('GOConstrains', xyz, g_opt%ions%space, sys%namespace)
667 if (xyz%source /= read_coords_err) then
668 !Sanity check
669 if (g_opt%ions%natoms /= xyz%n) then
670 write(message(1), '(a,i4,a,i4)') 'I need exactly ', g_opt%ions%natoms, ' constrains, but I found ', xyz%n
671 call messages_fatal(1, namespace=sys%namespace)
672 end if
673 ! copy information and adjust units
674 do iatom = 1, g_opt%ions%natoms
675 where(abs(xyz%atom(iatom)%x) <= m_epsilon)
676 g_opt%ions%atom(iatom)%c = m_zero
677 elsewhere
678 g_opt%ions%atom(iatom)%c = m_one
679 end where
680 end do
681
682 call read_coords_end(xyz)
683
684
685 if (g_opt%fixed_atom > 0) then
686 call messages_not_implemented("GOCenter with constrains", namespace=sys%namespace)
687 end if
688 else
689 do iatom = 1, g_opt%ions%natoms
690 g_opt%ions%atom(iatom)%c = m_zero
691 end do
692 end if
693
694
695 call io_rm("geom/optimization.log", sys%namespace)
696
697 call io_rm("work-geom.xyz", sys%namespace)
698
699 if (.not. fromscratch) then
700 inquire(file = './last.xyz', exist = does_exist)
701 if (.not. does_exist) fromscratch = .true.
702 end if
703
704 if (.not. fromscratch) call g_opt%ions%read_xyz('./last')
705
706 ! clean out old geom/go.XXXX.xyz files. must be consistent with write_iter_info
707 iter = 1
708 do
709 write(filename, '(a,i4.4,a)') "geom/go.", iter, ".xyz"
710 inquire(file = trim(filename), exist = does_exist)
711 if (does_exist) then
712 call io_rm(trim(filename), sys%namespace)
713 iter = iter + 1
714 else
715 exit
716 end if
717 ! TODO: clean forces directory
718 end do
719
720 call g_opt%scfv%restart_dump%init(sys%namespace, restart_gs, restart_type_dump, sys%mc, ierr, mesh=sys%gr)
721
723 end subroutine init_
724
725
726 ! ---------------------------------------------------------
727 subroutine end_()
728 push_sub(geom_opt_run_legacy.end_)
729
730 call states_elec_deallocate_wfns(sys%st)
731
732 call g_opt%scfv%restart_dump%end()
733
734 nullify(g_opt%mesh)
735 nullify(g_opt%ions)
736 nullify(g_opt%st)
737 nullify(g_opt%hm)
738 nullify(g_opt%syst)
739
740 safe_deallocate_a(g_opt%cell_force)
741
743 end subroutine end_
744
745 end subroutine geom_opt_run_legacy
746
747
748 ! ---------------------------------------------------------
751 subroutine calc_point(size, coords, objective, getgrad, df)
752 integer, intent(in) :: size
753 real(real64), intent(in) :: coords(size)
754 real(real64), intent(inout) :: objective
755 integer, intent(in) :: getgrad
756 real(real64), intent(inout) :: df(size)
757
758 integer :: iatom, idir, jdir
759 real(real64), dimension(g_opt%periodic_dim, g_opt%periodic_dim) :: stress, strain, right_stretch, inv_right_stretch, &
760 rotation, sym_stress
761 real(real64) :: det
762
763 push_sub(calc_point)
764
765 assert(size == g_opt%size)
766
767 call from_coords(g_opt, coords)
768
769 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0 ) then
770 call ion_dynamics_box_update(g_opt%syst%namespace, g_opt%syst%gr, g_opt%syst%space, g_opt%ions%latt)
771 end if
772
773 if (g_opt%fixed_atom /= 0) then
774 call g_opt%ions%translate(g_opt%ions%center())
775 end if
776
777 ! When the system is periodic in some directions, the atoms might have moved to a an adjacent cell,
778 ! so we need to move them back to the original cell
779 call g_opt%ions%fold_atoms_into_cell()
780
781 ! Some atoms might have moved outside the simulation box. We stop if this happens.
782 do iatom = 1, g_opt%ions%natoms
783 if (.not. g_opt%syst%gr%box%contains_point(g_opt%syst%ions%pos(:, iatom))) then
784 if (g_opt%syst%space%periodic_dim /= g_opt%syst%space%dim) then
785 ! FIXME: This could fail for partial periodicity systems
786 ! because contains_point is too strict with atoms close to
787 ! the upper boundary to the cell.
788 write(message(1), '(a,i5,a)') "Atom ", iatom, " has moved outside the box during the geometry optimization."
789 call messages_fatal(1, namespace=g_opt%syst%namespace)
790 end if
791 end if
792 end do
793
794 call g_opt%ions%write_xyz('./work-geom', append = .true.)
795
796 call scf_mix_clear(g_opt%scfv)
797
798 ! Update lattice vectors and regenerate grid
799 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0 ) then
800 call electrons_lattice_vectors_update(g_opt%syst%namespace, g_opt%syst%gr, &
801 g_opt%syst%space, g_opt%syst%hm%psolver, g_opt%syst%hm%kpoints, &
802 g_opt%syst%mc, g_opt%syst%st%qtot, g_opt%ions%latt)
803 end if
804
805 call hamiltonian_elec_epot_generate(g_opt%hm, g_opt%syst%namespace, g_opt%syst%space, g_opt%syst%gr, &
806 g_opt%ions, g_opt%syst%ext_partners, g_opt%st)
807 call density_calc(g_opt%st, g_opt%syst%gr, g_opt%st%rho)
808 call v_ks_calc(g_opt%syst%ks, g_opt%syst%namespace, g_opt%syst%space, g_opt%hm, g_opt%st, &
809 g_opt%ions,g_opt%syst%ext_partners, calc_eigenval = .true.)
810 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)
811
812 ! do SCF calculation
813 call scf_run(g_opt%scfv, g_opt%syst%namespace, g_opt%syst%space, g_opt%syst%mc, g_opt%syst%gr, &
814 g_opt%ions, g_opt%syst%ext_partners, &
815 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)
816
817 ! This is already set to zero for periodic systems
818 if (g_opt%ions%force_total_enforce) then
819 call forces_set_total_to_zero(g_opt%ions, g_opt%ions%tot_force)
820 end if
821
822 call scf_print_mem_use(g_opt%syst%namespace)
823
824 ! Convert stress into cell force
825 ! This is the Parrinello-Rahman equation of motion of the cell,
826 ! see Parrinello and Rahman, J. Appl. Pys. 52, 7182 (1981), Eq. 2.10.
827 ! Here we use a slightly different definition, in which we evolve the right stretch tensor
828 ! instead of h, because this is a symmetric matrix.
829 ! The deformation tensor is defined as F = (1+\epsilon) = h h_0^{-1},
830 ! where \epsilon is the infinitesimal strain tensor
831 ! Using the polar decomposition F = R U, we can request to have \ddot{U} that remains symmetric
832 ! in order to kill all the rotation
833 if (bitand(g_opt%type, go_cell) /= 0) then
834 stress = -g_opt%syst%st%stress_tensors%total(1:g_opt%periodic_dim, 1:g_opt%periodic_dim)
835
836 ! Replace \sigma = sym(R^T \sigma R)
837 ! We first compute R from the right polar decomposition R = F U^-1
838 strain = matmul(g_opt%ions%latt%rlattice(1:g_opt%periodic_dim,1:g_opt%periodic_dim), g_opt%inv_initial_rlattice)
839 right_stretch = lalg_remove_rotation(g_opt%periodic_dim, strain)
840 inv_right_stretch = right_stretch
841 call lalg_inverse(g_opt%periodic_dim, inv_right_stretch, 'dir')
842 rotation = matmul(strain, inv_right_stretch)
843 ! In some cases, R can contain a reflection. To guarantee that U is SPD, we multiply by the determinant of R
844 det = lalg_determinant(g_opt%periodic_dim, rotation, preserve_mat=.true.)
845
846 ! Compute the symmetrized stress
847 sym_stress = matmul(transpose(rotation), matmul(stress, rotation))
848 sym_stress = m_half*(sym_stress + transpose(sym_stress)) * det
849
850 ! The external hydrostatic pressure enters as a full -P on each diagonal component of the
851 ! stress, such that at equilibrium the internal stress balances the pressure (\sigma = -P I).
852 do idir = 1, g_opt%periodic_dim
853 sym_stress(idir, idir) = sym_stress(idir, idir) - g_opt%pressure
854 end do
855 g_opt%cell_force = sym_stress * g_opt%ions%latt%rcell_volume
856
857 g_opt%cell_force = matmul(g_opt%cell_force, inv_right_stretch)
858 ! The cell force is the gradient with respect to the symmetric right stretch tensor U,
859 ! so we symmetrize it.
860 g_opt%cell_force = m_half*(g_opt%cell_force + transpose(g_opt%cell_force))
861 end if
862
863 ! Convert stress into cell force
864 if (bitand(g_opt%type, go_volume) /= 0) then
865 stress = g_opt%syst%st%stress_tensors%total(1:g_opt%periodic_dim, 1:g_opt%periodic_dim)
866 do idir = 1, g_opt%periodic_dim
867 g_opt%cell_force(idir, 1) = -(g_opt%pressure + stress(idir, idir)) * g_opt%ions%latt%rcell_volume
868 end do
869 end if
870
871 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0) then
872 write(message(1),'(a,3a,a)') ' Stress tensor [', trim(units_abbrev(units_out%length)), ']'
873 do idir = 1, g_opt%periodic_dim
874 write(message(1+idir),'(9e18.10)') (units_from_atomic(units_out%length, g_opt%syst%st%stress_tensors%total(jdir, idir)), &
875 jdir = 1, g_opt%periodic_dim)
876 end do
877 call messages_info(1+g_opt%periodic_dim, namespace=g_opt%ions%namespace, debug_only=.true.)
878 write(message(1),'(a,3a,a)') ' Cell force tensor [', trim(units_abbrev(units_out%length)), ']'
879 do idir = 1, ubound(g_opt%cell_force, 2)
880 write(message(1+idir),'(9e18.10)') (units_from_atomic(units_out%length, g_opt%cell_force(jdir, idir)), &
881 jdir = 1, g_opt%periodic_dim)
882 end do
883 call messages_info(1+g_opt%periodic_dim, namespace=g_opt%ions%namespace, debug_only=.true.)
884 end if
885
886
887 ! store results
888 if (getgrad == 1) call to_grad(g_opt, df)
889
890 if (g_opt%what2minimize == minwhat_forces) then
891 objective = m_zero
892 do iatom = 1, g_opt%ions%natoms
893 if (g_opt%ions%fixed(iatom)) cycle
894 objective = objective + sum(g_opt%ions%tot_force(:, iatom)**2)
895 end do
896 if (bitand(g_opt%type, go_cell) /= 0) then
897 do idir = 1, g_opt%periodic_dim
898 objective = objective + sum(g_opt%cell_force(:, idir)**2)
899 end do
900 end if
901 if (bitand(g_opt%type, go_volume) /= 0) then
902 objective = objective + sum(g_opt%cell_force(:,1)**2)
903 end if
904 objective = sqrt(objective)
905 else
906 objective = g_opt%hm%energy%total
907 end if
908
909 pop_sub(calc_point)
910 end subroutine calc_point
911
912
913 ! ---------------------------------------------------------
918 subroutine calc_point_ng(size, coords, objective)
919 integer :: size
920 real(real64) :: coords(size)
921 real(real64) :: objective
922
923 integer :: getgrad
924 real(real64), allocatable :: df(:)
925
926 push_sub(calc_point_ng)
927
928 assert(size == g_opt%size)
929
930 getgrad = 0
931 safe_allocate(df(1:size))
932 df = m_zero
933
934 call calc_point(size, coords, objective, getgrad, df)
935 safe_deallocate_a(df)
936
937 pop_sub(calc_point_ng)
938 end subroutine calc_point_ng
939
940
941 ! ---------------------------------------------------------
943 subroutine write_iter_info(geom_iter, size, energy, maxdx, maxdf, coords)
944 integer, intent(in) :: geom_iter
945 integer, intent(in) :: size
946 real(real64), intent(in) :: energy, maxdx, maxdf
947 real(real64), intent(in) :: coords(size)
948
949 character(len=256) :: c_geom_iter, title, c_forces_iter
950 integer :: iunit
951
952 push_sub(write_iter_info)
953
954 write(c_geom_iter, '(a,i4.4)') "go.", geom_iter
955 write(title, '(f16.10,2x,a)') units_from_atomic(units_out%energy, energy), trim(units_abbrev(units_out%energy))
956 call io_mkdir('geom', g_opt%ions%namespace)
957 call g_opt%ions%write_xyz('geom/'//trim(c_geom_iter), comment = trim(title))
958 call g_opt%ions%write_xyz('./last')
959
960 if(g_opt%periodic_dim > 0) then
961 call g_opt%ions%write_xyz('geom/'//trim(c_geom_iter), comment = 'Reduced coordinates', reduce_coordinates = .true.)
962 call write_xsf_geometry_file('geom', trim(c_geom_iter), g_opt%ions%space, g_opt%ions%latt, &
963 g_opt%ions%pos, g_opt%ions%atom, g_opt%syst%gr, g_opt%syst%namespace)
964 end if
965
966 if (g_opt%syst%outp%what(option__output__forces)) then
967 write(c_forces_iter, '(a,i4.4)') "forces.", geom_iter
968 if (bitand(g_opt%syst%outp%how(option__output__forces), option__outputformat__bild) /= 0) then
969 call g_opt%ions%write_bild_forces_file('forces', trim(c_forces_iter))
970 else
971 call write_xsf_geometry_file('forces', trim(c_forces_iter), g_opt%ions%space, g_opt%ions%latt, &
972 g_opt%ions%pos, g_opt%ions%atom, g_opt%syst%gr, g_opt%syst%namespace, total_forces=g_opt%ions%tot_force)
973 end if
974 end if
975
976 if (g_opt%syst%st%system_grp%is_root()) then
977 iunit = io_open(trim('geom/optimization.log'), g_opt%syst%namespace, &
978 action = 'write', position = 'append')
979
980 if (geom_iter == 1) then
981 if (bitand(g_opt%type, go_cell) /= 0) then
982 write(iunit, '(a10,5(5x,a20),a)') '# iter','energy [' // trim(units_abbrev(units_out%energy)) // ']', &
983 'max_force [' // trim(units_abbrev(units_out%force)) // ']',&
984 ' max_dr [' // trim(units_abbrev(units_out%length)) // ']', &
985 ' a, b, c ['// trim(units_abbrev(units_out%length)) // ']', &
986 ' volume ['// trim(units_abbrev(units_out%length**3)) // ']',&
987 ' alpha, beta, gamma [degrees]'
988 else
989 write(iunit, '(a10,3(5x,a20))') '# iter','energy [' // trim(units_abbrev(units_out%energy)) // ']', &
990 'max_force [' // trim(units_abbrev(units_out%force)) // ']',&
991 ' max_dr [' // trim(units_abbrev(units_out%length)) // ']'
992 end if
993 end if
994
995 if (bitand(g_opt%type, go_cell) /= 0) then
996 write(iunit, '(i10,10f25.15)') geom_iter, units_from_atomic(units_out%energy, energy), &
997 units_from_atomic(units_out%force,maxdf), &
998 units_from_atomic(units_out%length,maxdx), &
999 units_from_atomic(units_out%length,norm2(g_opt%ions%latt%rlattice(1:3, 1))),&
1000 units_from_atomic(units_out%length,norm2(g_opt%ions%latt%rlattice(1:3, 2))),&
1001 units_from_atomic(units_out%length,norm2(g_opt%ions%latt%rlattice(1:3, 3))),&
1002 units_from_atomic(units_out%length**3, g_opt%ions%latt%rcell_volume), &
1003 g_opt%ions%latt%alpha, g_opt%ions%latt%beta, g_opt%ions%latt%gamma
1004 else
1005 write(iunit, '(i10,3f25.15)') geom_iter, units_from_atomic(units_out%energy, energy), &
1006 units_from_atomic(units_out%force,maxdf), &
1007 units_from_atomic(units_out%length,maxdx)
1008 end if
1009
1010 call io_close(iunit)
1011 end if
1012
1014 call messages_new_line()
1015
1016 call messages_write("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", new_line = .true.)
1017
1018 call messages_write("+++++++++++++++++++++ MINIMIZATION ITER #:")
1019 call messages_write(geom_iter, fmt = "I5")
1020 call messages_write(" ++++++++++++++++++++++", new_line = .true.)
1021
1022 call messages_write(" Energy = ")
1023 call messages_write(energy, units = units_out%energy, fmt = "f16.10,1x", print_units = .true., new_line = .true.)
1024
1025 if (g_opt%periodic_dim == 0) then
1026 if (maxdf > m_zero) then
1027 call messages_write(" Max force = ")
1028 call messages_write(maxdf, units = units_out%force, fmt = "f16.10,1x", print_units = .true., new_line = .true.)
1029 end if
1030
1031 call messages_write(" Max dr = ")
1032 call messages_write(maxdx, units = units_out%length, fmt = "f16.10,1x", print_units = .true., new_line = .true.)
1033 else
1034 if (maxdf > m_zero) then
1035 call messages_write(" Max reduced force = ")
1036 call messages_write(maxdf, fmt = "f16.10,1x", print_units = .false., new_line = .true.)
1037 end if
1039 call messages_write(" Max reduced dr = ")
1040 call messages_write(maxdx, fmt = "f16.10,1x", print_units = .false., new_line = .true.)
1041 end if
1042
1043 call messages_write("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", new_line = .true.)
1044 call messages_write("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", new_line = .true.)
1045 call messages_new_line()
1046 call messages_new_line()
1047 call messages_info()
1048
1049 pop_sub(write_iter_info)
1050 end subroutine write_iter_info
1051
1052 ! ---------------------------------------------------------
1054 subroutine to_coords(gopt, coords)
1055 type(geom_opt_t), intent(in) :: gopt
1056 real(real64), intent(out) :: coords(:)
1057
1058 integer :: iatom, idir, jdir, icoord
1059 real(real64) :: tmp_pos(gopt%dim), strain(g_opt%periodic_dim,g_opt%periodic_dim)
1060
1061 push_sub(to_coords)
1062
1063 icoord = 1
1064 ! Ion dynamics
1065 if (bitand(g_opt%type, go_ions) /= 0) then
1066 do iatom = 1, gopt%ions%natoms
1067 if (gopt%fixed_atom == iatom) cycle
1068 if (gopt%ions%fixed(iatom)) cycle
1069 tmp_pos = gopt%ions%pos(1:gopt%dim, iatom)
1070 if (gopt%fixed_atom > 0) tmp_pos = tmp_pos - gopt%ions%pos(1:gopt%dim, gopt%fixed_atom)
1071 tmp_pos = gopt%ions%latt%cart_to_red(tmp_pos)
1072 do idir = 1, gopt%dim
1073 coords(icoord) = tmp_pos(idir)
1074 icoord = icoord + 1
1075 end do
1076 end do
1077 end if
1078
1079 ! Cell dynamics
1080 if (bitand(g_opt%type, go_cell) /= 0) then
1081 ! We compute the change in the right stretch tensor U, defined as h = U h_0.
1082 ! Only the periodic block of the lattice is relaxed; the non-periodic (e.g. vacuum)
1083 ! direction is left untouched, which is essential for 2D systems.
1084 strain = matmul(gopt%ions%latt%rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim), g_opt%inv_initial_rlattice)
1085 do idir = 1, g_opt%periodic_dim
1086 do jdir = idir, g_opt%periodic_dim
1087 coords(icoord) = strain(idir, jdir)
1088 icoord = icoord + 1
1089 end do
1090 end do
1091 end if
1092
1093 ! Volume dynamics
1094 if (bitand(g_opt%type, go_volume) /= 0) then
1095 do idir = 1, g_opt%periodic_dim
1096 coords(icoord) = norm2(gopt%ions%latt%rlattice(1:g_opt%periodic_dim, idir))/g_opt%initial_length(idir)
1097 icoord = icoord + 1
1098 end do
1099 end if
1100
1101
1102 pop_sub(to_coords)
1103 end subroutine to_coords
1104
1105 ! ---------------------------------------------------------
1107 subroutine to_grad(gopt, grad)
1108 type(geom_opt_t), intent(in) :: gopt
1109 real(real64), intent(out) :: grad(:)
1110
1111 integer :: iatom, idir, jdir, icoord
1112 real(real64) :: tmp_force(1:gopt%dim)
1113
1114 push_sub(to_grad)
1115
1116 icoord = 1
1117 ! Ion dynamics
1118 if (bitand(g_opt%type, go_ions) /= 0) then
1119 do iatom = 1, gopt%ions%natoms
1120 if (gopt%fixed_atom == iatom) cycle
1121 if (gopt%ions%fixed(iatom)) cycle
1122 do idir = 1, gopt%dim
1123 if (abs(gopt%ions%atom(iatom)%c(idir)) <= m_epsilon) then
1124 tmp_force(idir) = -gopt%ions%tot_force(idir, iatom)
1125 else
1126 tmp_force(idir) = m_zero
1127 end if
1128 if (gopt%fixed_atom > 0) then
1129 tmp_force(idir) = tmp_force(idir) + gopt%ions%tot_force(idir, gopt%fixed_atom)
1130 end if
1131 end do
1132 tmp_force = gopt%ions%latt%cart_to_red(tmp_force)
1133 do idir = 1, gopt%dim
1134 grad(icoord) = tmp_force(idir)
1135 icoord = icoord + 1
1136 end do
1137 end do
1138 end if
1139
1140 ! Cell dynamics
1141 if (bitand(g_opt%type, go_cell) /= 0) then
1142 do idir = 1, g_opt%periodic_dim
1143 do jdir = idir, g_opt%periodic_dim
1144 grad(icoord) = -g_opt%cell_force(idir, jdir)
1145 icoord = icoord + 1
1146 end do
1147 end do
1148 end if
1150 ! Volume dynamics
1151 if (bitand(g_opt%type, go_volume) /= 0) then
1152 do idir = 1, g_opt%periodic_dim
1153 grad(icoord) = -g_opt%cell_force(idir, 1)
1154 icoord = icoord + 1
1155 end do
1156 end if
1157
1158
1159 pop_sub(to_grad)
1160 end subroutine to_grad
1161
1162 ! ---------------------------------------------------------
1164 subroutine from_coords(gopt, coords)
1165 type(geom_opt_t), intent(inout) :: gopt
1166 real(real64), intent(in) :: coords(:)
1167
1168 integer :: iatom, idir, jdir, icoord
1169 real(real64) :: tmp_pos(gopt%dim, gopt%ions%natoms), strain(g_opt%periodic_dim,g_opt%periodic_dim)
1170 real(real64) :: eigenvalues(g_opt%periodic_dim)
1171
1172 push_sub(from_coords)
1173
1174 ! Get the new reduced atomic coordinates
1175 tmp_pos = m_zero
1176 icoord = 1
1177 ! Ion dynamics
1178 if (bitand(g_opt%type, go_ions) /= 0) then
1179 do iatom = 1, gopt%ions%natoms
1180 if (gopt%fixed_atom == iatom) cycle
1181 if (gopt%ions%fixed(iatom)) cycle
1182 do idir = 1, gopt%dim
1183 tmp_pos(idir, iatom) = coords(icoord)
1184 icoord = icoord + 1
1185 end do
1186 end do
1187 else
1188 do iatom = 1, gopt%ions%natoms
1189 tmp_pos(:, iatom) = gopt%ions%latt%cart_to_red(gopt%ions%pos(:, iatom))
1190 end do
1191 end if
1192
1193 ! Updating the lattice vectors
1194 if (bitand(g_opt%type, go_cell) /= 0) then
1195 do idir = 1, g_opt%periodic_dim
1196 do jdir = idir, g_opt%periodic_dim
1197 strain(idir, jdir) = coords(icoord)
1198 icoord = icoord + 1
1199 end do
1200 end do
1201 call upper_triangular_to_hermitian(g_opt%periodic_dim, strain)
1203 ! Get the new lattice vectors from the new right stretch tensor U
1204 ! The strain tensor is defined as A = U * A_0.
1205 ! Only the periodic block is updated; the non-periodic (e.g. vacuum) lattice
1206 ! direction is preserved, which is essential for 2D systems (otherwise the
1207 ! vacuum direction would be corrupted/collapse).
1208 gopt%ions%latt%rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim) = matmul(strain, g_opt%initial_rlattice)
1209
1210 ! Sanity check: the right stretch tensor U must remain symmetric positive-definite.
1211 ! Note: lalg_eigensolve overwrites strain with the eigenvectors, but strain is no longer
1212 ! needed below, so this is safe.
1213 call lalg_eigensolve(g_opt%periodic_dim, strain, eigenvalues)
1214 assert(all(eigenvalues > m_zero))
1215 end if
1216
1217 ! Updating the lattice vectors
1218 if (bitand(g_opt%type, go_volume) /= 0) then
1219 do idir = 1, g_opt%periodic_dim
1220 gopt%ions%latt%rlattice(1:g_opt%periodic_dim, idir) = coords(icoord) &
1221 * gopt%initial_rlattice(1:g_opt%periodic_dim, idir)
1222 icoord = icoord + 1
1223 end do
1224 end if
1225
1226 ! Symmetrize and update the lattice vectors
1227 if (bitand(g_opt%type, go_cell) /= 0 .or. bitand(g_opt%type, go_volume) /= 0) then
1228 call g_opt%syst%gr%symmetrizer%symmetrize_lattice_vectors(g_opt%periodic_dim, g_opt%initial_rlattice, &
1229 gopt%ions%latt%rlattice(1:g_opt%periodic_dim, 1:g_opt%periodic_dim), gopt%symmetrize)
1230 call gopt%ions%update_lattice_vectors(gopt%ions%latt, gopt%symmetrize)
1231 end if
1232
1233 ! Ion dynamics
1234 if (bitand(g_opt%type, go_ions) /= 0) then
1235 ! To Cartesian coordinates
1236 do iatom = 1, gopt%ions%natoms
1237 if (gopt%fixed_atom == iatom) cycle
1238 if (gopt%ions%fixed(iatom)) cycle
1239 tmp_pos(:, iatom) = gopt%ions%latt%red_to_cart(tmp_pos(:, iatom))
1240 do idir = 1, gopt%dim
1241 if (abs(gopt%ions%atom(iatom)%c(idir)) <= m_epsilon) then
1242 gopt%ions%pos(idir, iatom) = tmp_pos(idir, iatom)
1243 end if
1244 end do
1245 if (gopt%fixed_atom > 0) then
1246 gopt%ions%pos(:, iatom) = gopt%ions%pos(:, iatom) + gopt%ions%pos(:, gopt%fixed_atom)
1247 end if
1248 end do
1249 else
1250 do iatom = 1, gopt%ions%natoms
1251 gopt%ions%pos(:, iatom) = gopt%ions%latt%red_to_cart(tmp_pos(:, iatom))
1252 end do
1253 end if
1254
1255 if (gopt%symmetrize) then
1256 call gopt%ions%symmetrize_atomic_coord()
1257 end if
1258
1259 if (debug%info) then
1260 call gopt%ions%print_spacegroup()
1261 end if
1262
1263 pop_sub(from_coords)
1264 end subroutine from_coords
1265
1266 ! ---------------------------------------------------------
1268 subroutine write_iter_info_ng(geom_iter, size, energy, maxdx, coords)
1269 integer, intent(in) :: geom_iter
1270 integer, intent(in) :: size
1271 real(real64), intent(in) :: energy, maxdx
1272 real(real64), intent(in) :: coords(size)
1273
1274 push_sub(write_iter_info_ng)
1275 call write_iter_info(geom_iter, size, energy, maxdx, -m_one, coords)
1276
1277 pop_sub(write_iter_info_ng)
1278 end subroutine write_iter_info_ng
1279
1280end module geom_opt_oct_m
1281
1282!! Local Variables:
1283!! mode: f90
1284!! coding: utf-8
1285!! End:
subroutine init_(fromscratch)
Definition: geom_opt.F90:370
subroutine end_()
Definition: geom_opt.F90:823
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:212
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:1014
subroutine to_grad(gopt, grad)
Transfer data from the forces to the work array for the gradients (grad)
Definition: geom_opt.F90:1203
integer, parameter go_cell
Definition: geom_opt.F90:203
integer, parameter minwhat_forces
Definition: geom_opt.F90:199
subroutine write_iter_info_ng(geom_iter, size, energy, maxdx, coords)
Same as write_iter_info, but without the gradients.
Definition: geom_opt.F90:1364
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:1039
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:847
subroutine to_coords(gopt, coords)
Transfer the data from the data structures to the work array (coords)
Definition: geom_opt.F90:1150
integer, parameter go_volume
Definition: geom_opt.F90:203
subroutine from_coords(gopt, coords)
Transfer the data from the work array (coords) to the actual data structures.
Definition: geom_opt.F90:1260
subroutine geom_opt_run_legacy(sys, fromscratch)
Definition: geom_opt.F90:230
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_epsilon
Definition: global.F90:216
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_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
This module implements the basic mulsisystem class, a container system for other systems.
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)