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