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