Octopus
vibrational.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
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
21program vibrational
22 use batch_oct_m
24 use debug_oct_m
25 use global_oct_m
26 use io_oct_m
27 use ions_oct_m
28 use, intrinsic :: iso_fortran_env
31 use parser_oct_m
34 use unit_oct_m
36
37 implicit none
38
39 integer :: iunit, ierr, ii, jj, iter, read_iter, ntime, nvaf, nvel, ivel
40 real(real64), allocatable :: vaf(:), time(:), velocities(:, :), ftvaf(:)
41 type(ions_t), pointer :: ions
42 type(spectrum_t) :: spectrum
43 type(batch_t) :: vafb, ftvafb
44 real(real64) :: ww, curtime, vaftime, deltat
45 integer :: ifreq, max_freq
46 integer :: skip
47
48 ! Initialize stuff
50
51 call getopt_init(ierr)
52 call getopt_end()
53
54 call parser_init()
55
56 call messages_init()
57
58 call io_init()
60
62
63 call spectrum_init(spectrum, global_namespace, &
64 default_energy_step = units_to_atomic(unit_invcm, 0.2_real64), &
65 default_max_energy = units_to_atomic(unit_invcm, 5000.0_real64))
66
67 !%Variable VibrationalSpectrumTimeStepFactor
68 !%Type integer
69 !%Default 10
70 !%Section Utilities::oct-vibrational_spectrum
71 !%Description
72 !% In the calculation of the vibrational spectrum, it is not necessary
73 !% to read the velocity at every time step. This variable controls
74 !% the integer factor between the simulation time step and the
75 !% time step used to calculate the vibrational spectrum.
76 !%End
77
78 call messages_obsolete_variable(global_namespace, 'PropagationSpectrumTimeStepFactor', 'VibrationalSpectrumTimeStepFactor')
79 call parse_variable(global_namespace, 'VibrationalSpectrumTimeStepFactor', 10, skip)
80 if (skip <= 0) call messages_input_error(global_namespace, 'VibrationalSpectrumTimeStepFactor')
81
82 max_freq = spectrum_nenergy_steps(spectrum)
83
84 if (spectrum%end_time < m_zero) spectrum%end_time = huge(spectrum%end_time)
85
87
88 ! Opens the coordinates files.
89 iunit = io_open('td.general/coordinates', global_namespace, action='read')
90
91 call io_skip_header(iunit)
92
93 ntime = 1
94 iter = 1
95
96 ! check the number of time steps we will read
97 do
98 read(unit = iunit, iostat = ierr, fmt = *) read_iter, curtime, &
99 ((ions%pos(jj, ii), jj = 1, 3), ii = 1, ions%natoms), &
100 ((ions%vel(jj, ii), jj = 1, 3), ii = 1, ions%natoms)
101
102 curtime = units_to_atomic(units_out%time, curtime)
103
104 if (ierr /= 0 .or. curtime >= spectrum%end_time) then
105 iter = iter - 1 ! last iteration is not valid
106 ntime = ntime - 1
107 exit
108 end if
109
110 if (iter /= read_iter + 1) then
111 call messages_write("Error while reading file 'td.general/coordinates',", new_line = .true.)
112 call messages_write('expected iteration ')
113 call messages_write(iter - 1)
114 call messages_write(', got iteration ')
115 call messages_write(read_iter)
116 call messages_write('.')
117 call messages_fatal()
118 end if
119
120 ! ntime counts how many steps are gonna be used
121 if (curtime >= spectrum%start_time .and. mod(iter, skip) == 0) ntime = ntime + 1
122
123 iter = iter + 1 !counts number of timesteps (with time larger than zero up to SpecEndTime)
124 end do
125
126 call io_close(iunit)
127
128 nvel = ions%natoms*ions%space%dim
129
130 safe_allocate(time(1:ntime))
131 safe_allocate(velocities(1:nvel, 1:ntime))
132
133 ! Opens the coordinates files.
134 iunit = io_open('td.general/coordinates', global_namespace, action='read')
135
136 call io_skip_header(iunit)
137
138 ntime = 1
139 iter = 1
140
141 do
142 read(unit = iunit, iostat = ierr, fmt = *) read_iter, curtime, &
143 ((ions%pos(jj, ii), jj = 1, 3), ii = 1, ions%natoms), &
144 ((ions%vel(jj, ii), jj = 1, 3), ii = 1, ions%natoms)
145
146 curtime = units_to_atomic(units_out%time, curtime)
147
148 if (ierr /= 0 .or. curtime >= spectrum%end_time) then
149 iter = iter - 1 ! last iteration is not valid
150 ntime = ntime - 1
151 exit
152 end if
153
154 assert(iter == read_iter + 1)
155
156 if (curtime >= spectrum%start_time .and. mod(iter, skip) == 0) then
157
158 time(ntime) = curtime
159 ivel = 1
160 do ii = 1, ions%natoms
161 do jj = 1, ions%space%dim
162 velocities(ivel, ntime) = units_to_atomic(units_out%velocity, ions%vel(jj, ii))
163 ivel = ivel + 1
164 end do
165 end do
166
167 ntime = ntime + 1
168 end if
169
170 iter = iter + 1 !counts number of timesteps (with time larger than zero up to SpecEndTime)
171 end do
172
173 call io_close(iunit)
174
175 deltat = time(2) - time(1)
176
177 !%Variable VibrationalSpectrumTime
178 !%Type integer
179 !%Section Utilities::oct-vibrational_spectrum
180 !%Description
181 !% This variable controls the maximum time for the calculation of
182 !% the velocity autocorrelation function. The default is the total
183 !% propagation time.
184 !%End
185 call parse_variable(global_namespace, 'VibrationalSpectrumTime', ntime*deltat, vaftime)
186
187 nvaf = int(vaftime/deltat)
188
189 safe_allocate(vaf(1:ntime))
190
191 call messages_write('Time step = ')
192 call messages_write(deltat, units = units_out%time)
193 call messages_info()
194
195 call messages_new_line()
196 call messages_write('Calculating the velocity autocorrelation function')
197 call messages_info()
198
199 call calculate_vaf(vaf)
200
201 !print the vaf
202 iunit = io_open('td.general/velocity_autocorrelation', global_namespace, action='write')
203
204800 FORMAT(80('#'))
205 write(unit = iunit, iostat = ierr, fmt = 800)
206 write(unit = iunit, iostat = ierr, fmt = '(8a)') '# HEADER'
207 write(unit = iunit, iostat = ierr, fmt = '(a,4x,a6,a7,a1,10x,a10)') &
208 '# Iter', 'time [',units_out%time%abbrev,']', 'VAF [a.u.]'
209 write(unit = iunit, iostat = ierr, fmt = 800)
210
211 do jj = 1, nvaf
212 write(unit = iunit, iostat = ierr, fmt = *) jj, units_from_atomic(units_out%time, (jj - 1)*deltat), vaf(jj)
213 end do
214
215 call io_close(iunit)
216
217
218 safe_allocate(ftvaf(1:max_freq))
219
220 ftvaf = m_one
221
222 call batch_init(vafb, vaf)
223
224 call spectrum_signal_damp(spectrum%damp, spectrum%damp_factor, 1, nvaf, m_zero, deltat, vafb)
225
226 call batch_init(ftvafb, ftvaf)
227
228 call spectrum_fourier_transform(spectrum%method, spectrum_transform_cos, spectrum%noise, &
229 1, nvaf, m_zero, deltat, vafb, spectrum%min_energy, spectrum%max_energy, spectrum%energy_step, ftvafb)
230
231 call vafb%end()
232 call ftvafb%end()
233
234
235 !and print the spectrum
236 iunit = io_open('td.general/vibrational_spectrum', global_namespace, action='write')
237
238 write(unit = iunit, iostat = ierr, fmt = 800)
239 write(unit = iunit, iostat = ierr, fmt = '(8a)') '# HEADER'
240 write(unit = iunit, iostat = ierr, fmt = '(a17,6x,a15)') '# Energy [1/cm]', 'Spectrum [a.u.]'
241 write(unit = iunit, iostat = ierr, fmt = 800)
242
243 do ifreq = 1, max_freq
244 ww = spectrum%energy_step*(ifreq - 1) + spectrum%min_energy
245 write(unit = iunit, iostat = ierr, fmt = '(2e20.10)') units_from_atomic(unit_invcm, ww), ftvaf(ifreq)
246 end do
247
248 call io_close(iunit)
249
250 safe_deallocate_a(vaf)
251
252 safe_deallocate_a(ftvaf)
253
254 safe_deallocate_p(ions)
255
256 safe_deallocate_a(time)
257
259 call io_end()
260 call messages_end()
261
262 call parser_end()
263 call global_end()
264
265contains
266
267 subroutine calculate_vaf(vaf)
268 real(real64), intent(out) :: vaf(:)
269 integer :: itm, itn
270
271 push_sub(calculate_vaf)
272
273 write (message(1), '(a)') "Read velocities from '"// &
274 trim(io_workpath('td.general/coordinates', global_namespace))//"'"
275 call messages_info(1)
276
277 !calculating the vaf, formula from
278 !
279 ! http://www.timteatro.net/2010/09/29/velocity-autocorrelation-and-vibrational-spectrum-calculation/
280
281 vaf = m_zero
282
283 do itm = 1, ntime
284 vaf(itm) = m_zero
285
286 do itn = 1, ntime - itm + 1
287
288 do ivel = 1, nvel
289 vaf(itm) = vaf(itm) + velocities(ivel, itm + itn - 1)*velocities(ivel, itn)
290 end do
291 end do
292
293 vaf(itm) = vaf(itm)/real(ntime - itm + 1, real64)
294
295 end do
296
297 do itm = 2, ntime
298 vaf(itm) = vaf(itm)/vaf(1)
299 end do
300 vaf(1) = m_one
301
302 pop_sub(calculate_vaf)
303 end subroutine calculate_vaf
304
305end program vibrational
306
307!! Local Variables:
308!! mode: f90
309!! coding: utf-8
310!! End:
initialize a batch with existing memory
Definition: batch.F90:267
This module implements batches of mesh functions.
Definition: batch.F90:133
subroutine, public getopt_init(ierr)
Initializes the getopt machinery. Must be called before attempting to parse the options....
subroutine, public getopt_end
subroutine, public global_end()
Finalise parser varinfo file, and MPI.
Definition: global.F90:381
real(real64), parameter, public m_zero
Definition: global.F90:187
type(mpi_comm), parameter, public serial_dummy_comm
Alias MPI_COMM_UNDEFINED for the specific use case of initialising Octopus utilities with no MPI supp...
Definition: global.F90:264
subroutine, public init_octopus_globals(comm)
Initialise Octopus-specific global constants and files. This routine performs no initialisation calls...
Definition: global.F90:353
real(real64), parameter, public m_one
Definition: global.F90:188
Definition: io.F90:114
subroutine, public io_init(defaults)
If the argument defaults is present and set to true, then the routine will not try to read anything f...
Definition: io.F90:166
subroutine, public io_close(iunit, grp)
Definition: io.F90:468
subroutine, public io_skip_header(iunit)
Definition: io.F90:679
subroutine, public io_end()
Definition: io.F90:265
character(len=max_path_len) function, public io_workpath(path, namespace)
Definition: io.F90:313
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:395
subroutine, public messages_end()
Definition: messages.F90:277
subroutine, public messages_init(output_dir)
Definition: messages.F90:224
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
type(namespace_t), public global_namespace
Definition: namespace.F90:132
subroutine, public parser_init()
Initialise the Octopus parser.
Definition: parser.F90:450
subroutine, public parser_end()
End the Octopus parser.
Definition: parser.F90:481
subroutine, public profiling_end(namespace)
Definition: profiling.F90:413
subroutine, public profiling_init(namespace)
Create profiling subdirectory.
Definition: profiling.F90:255
subroutine, public spectrum_fourier_transform(method, transform, noise, time_start, time_end, t0, time_step, time_function, energy_start, energy_end, energy_step, energy_function)
Computes the sine, cosine, (or "exponential") Fourier transform of the real function given in the tim...
Definition: spectrum.F90:2638
subroutine, public spectrum_init(spectrum, namespace, default_energy_step, default_max_energy)
Definition: spectrum.F90:213
subroutine, public spectrum_signal_damp(damp_type, damp_factor, time_start, time_end, t0, time_step, time_function)
Definition: spectrum.F90:2552
integer, parameter, public spectrum_transform_cos
Definition: spectrum.F90:171
pure integer function, public spectrum_nenergy_steps(spectrum)
Definition: spectrum.F90:2947
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
This module defines the unit system, used for input and output.
type(unit_t), public unit_invcm
For vibrational frequencies.
type(unit_system_t), public units_out
subroutine, public unit_system_init(namespace)
int true(void)
program vibrational
subroutine calculate_vaf(vaf)