Octopus
propagation_spectrum.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
23 use debug_oct_m
24 use global_oct_m
25 use io_oct_m
26 use iso_c_binding
27 use kick_oct_m
30 use parser_oct_m
33 use string_oct_m
35
36 implicit none
37
38 integer :: in_file(3), out_file(3), ref_file, eq_axes, nspin, &
39 lmax, time_steps, ierr
40 logical :: calculate_tensor, reference_multipoles
41 type(spectrum_t) :: spectrum
42 type(unit_system_t) :: file_units
43 character(len=80) :: refmultipoles
44
45 ! Initialize stuff
47
48 call getopt_init(ierr)
49 refmultipoles = ""
50 if (ierr == 0) call getopt_propagation_spectrum(refmultipoles)
51 call getopt_end()
52
53 call parser_init()
54
55 call messages_init()
56
57 call io_init()
59
61
62 call spectrum_init(spectrum, global_namespace)
63
64 select case (spectrum%spectype)
66 call read_files('multipoles', refmultipoles)
67 call calculate_absorption('cross_section', global_namespace)
68 case (spectrum_p_power)
69 call calculate_dipole_power("multipoles", 'dipole_power')
71 call calculate_ftchd('ftchd', 'dynamic_structure_factor')
73 call calculate_rotatory_strength("angular", "rotatory_strength")
74 case default
75 write(message(1), '(a)') 'No PropagationSpectrumType defined,'
76 write(message(2), '(a)') 'cannot calculate the spectrum.'
77 call messages_warning(2)
78 end select
79
81 call io_end()
82 call messages_end()
83
84 call parser_end()
85
86 call global_end()
87
88contains
89
90 subroutine getopt_propagation_spectrum(str)
91 character(len=*), intent(inout) :: str
92
93 character(kind=c_char) :: cstr(len(str)+1)
94
95 interface getopt_propagation_spectrum_low
96 subroutine getopt_propagation_spectrum_low(str) bind(c, name='getopt_propagation_spectrum')
97 use iso_c_binding
98 character(kind=c_char) :: str(*)
99 end subroutine getopt_propagation_spectrum_low
100 end interface getopt_propagation_spectrum_low
101
102 cstr = c_null_char
103 call getopt_propagation_spectrum_low(cstr)
104 call string_c_to_f(cstr, str)
105 end subroutine getopt_propagation_spectrum
106
139 subroutine read_files(fname, reffname)
140 character(len=*), intent(in) :: fname
141 character(len=*), intent(in) :: reffname
142
143 type(kick_t) :: kick
144 real(real64) :: dt
145
146 push_sub(read_files)
147
148 in_file(1) = io_open(trim(fname), global_namespace, action='read', status='old', die=.false.)
149 if (in_file(1) == -1) in_file(1) = io_open('td.general/'//trim(fname), global_namespace, &
150 action='read', status='old', die=.false.)
151 if (in_file(1) /= -1) then
152 write(message(1),'(3a)') 'File "', trim(fname), '" found. This will be the only file to be processed.'
153 write(message(2),'(a)') '(If more than one file is to be used, the files should be called'
154 write(message(3),'(5a)') '"', trim(fname), '.1", "', trim(fname), '.2", etc.)'
155 write(message(4),'(a)')
156 call messages_info(4)
157
158 ! OK, so we only have one file. Now we have to see what it has inside.
159 call spectrum_mult_info(global_namespace, in_file(1), nspin, kick, time_steps, dt, file_units, lmax=lmax)
160 eq_axes = kick%pol_equiv_axes
161 if (eq_axes == 3) then
162 calculate_tensor = .true.
163 write(message(1),'(3a)') 'The file "', trim(fname), '" tells me that the system has three equivalent axes.'
164 write(message(2),'(a)') 'I will calculate the full tensor, written in file "XXXX_tensor".'
165 call messages_info(2)
166 else if (eq_axes == 2) then
167 write(message(1),'(3a)') 'The file "', trim(fname), '" tells me that the system has two equivalent axes.'
168 write(message(2),'(a)') 'However, I am only using this file; cannot calculate the full tensor.'
169 write(message(3),'(a)') 'A file "XXXX_vector" will be generated instead.'
170 call messages_warning(3)
171 calculate_tensor = .false.
172 else
173 write(message(1),'(3a)') 'The file "', trim(fname), '" tells me that the system has no usable symmetry. '
174 write(message(2),'(a)') 'However, I am only using this file; cannot calculate the full tensor.'
175 write(message(3),'(a)') 'A file "XXXX_vector" will be generated instead.'
176 call messages_warning(3)
177 calculate_tensor = .false.
178 end if
179
180 else ! We will try to load more fname.1 files...
181
182 ! In this case, we will always want the full tensor
183 calculate_tensor = .true.
184
185 in_file(1) = io_open(trim(fname)//'.1', global_namespace, action='read', &
186 status='old', die=.false.)
187 if (in_file(1) == -1) in_file(1) = io_open('td.general/'//trim(fname)//'.1', global_namespace, &
188 action='read', status='old', die=.false.)
189 if (in_file(1) == -1) then ! Could not find proper files. Die and complain.
190 write(message(1),'(5a)') 'No "', trim(fname), '" or "', trim(fname), '.1" file found. At least one of those'
191 write(message(2),'(a)') 'should be visible.'
192 call messages_fatal(2)
193 end if
194
195 call spectrum_mult_info(global_namespace, in_file(1), nspin, kick, time_steps, dt, file_units, lmax=lmax)
196 eq_axes = kick%pol_equiv_axes
197
198 if (eq_axes == 3) then
199 write(message(1),'(3a)') 'The file "', trim(fname), '.1" tells me that the system has three equivalent axes.'
200 write(message(2),'(a)') 'I will calculate the full tensor, written in file "cross_section_tensor".'
201 call messages_info(2)
202
203 else if (eq_axes == 2) then
204 in_file(2) = io_open(trim(fname)//'.2', global_namespace, action='read', status='old', die=.false.)
205 if (in_file(2) == -1) in_file(2) = io_open('td.general/'//trim(fname)//'.2', global_namespace, &
206 action='read', status='old', die=.false.)
207 if (in_file(2) == -1) then
208 write(message(1),'(3a)') 'The file "', trim(fname), '.1" tells me that the system has two equivalent axes,'
209 write(message(2),'(3a)') 'but I cannot find a "', trim(fname), '.2".'
210 call messages_fatal(2)
211 end if
212 write(message(1),'(5a)') 'Found two files, "', trim(fname), '.1" and "', trim(fname), '.2".'
213 write(message(2),'(a)') 'Two polarization axes are equivalent. I will generate the full tensor.'
214 call messages_info(2)
215
216 else ! No equivalent axes
217 in_file(2) = io_open(trim(fname)//'.2', global_namespace, action='read', &
218 status='old', die=.false.)
219 if (in_file(2) == -1) in_file(2) = io_open('td.general/'//trim(fname)//'.2', global_namespace, &
220 action='read', status='old', die=.false.)
221 if (in_file(2) == -1) then
222 write(message(1),'(3a)') 'The file "', trim(fname), '.1" tells me that the system has three inequivalent axes,'
223 write(message(2),'(3a)') 'but I cannot find a "', trim(fname), '.2".'
224 call messages_fatal(2)
225 end if
226 in_file(3) = io_open(trim(fname)//'.3', global_namespace, action='read', &
227 status='old', die=.false.)
228 if (in_file(3) == -1) in_file(3) = io_open('td.general/'//trim(fname)//'.3', global_namespace, &
229 action='read', status='old', die=.false.)
230 if (in_file(3) == -1) then
231 write(message(1),'(3a)') 'The file "', trim(fname), '.1" tells me that the system has three inequivalent axes,'
232 write(message(2),'(3a)') 'but I cannot find a "', trim(fname), '.3".'
233 call messages_fatal(2)
234 end if
235 write(message(1),'(7a)') 'Found three files, "', trim(fname), '.1", "', trim(fname), '.2" and "', trim(fname), '.3".'
236 write(message(2),'(a)') 'No symmetry information will be used.'
237 call messages_info(2)
238 end if
239
240 end if
241
242 if (reffname == "") then
243 reference_multipoles = .false.
244 else
245 reference_multipoles = .true.
246 ref_file = io_open(trim(reffname), global_namespace, action='read', status='old')
247 end if
248
249 pop_sub(read_files)
250 end subroutine read_files
251
252
253 !----------------------------------------------------------------------------
254 subroutine calculate_absorption(fname, namespace)
255 character(len=*), intent(in) :: fname
256 type(namespace_t), intent(in) :: namespace
257
258 integer :: ii, jj
259 character(len=150), allocatable :: filename(:)
260
261 push_sub(calculate_absorption)
262
263 if (.not. calculate_tensor) then
264
265 out_file(1) = io_open(trim(fname)//'_vector', global_namespace, action='write')
266 if (.not. reference_multipoles) then
267 call spectrum_cross_section(spectrum, namespace, in_file(1), out_file(1))
268 else
269 call spectrum_cross_section(spectrum, namespace, in_file(1), out_file(1), ref_file)
270 end if
271 call io_close(in_file(1))
272 call io_close(out_file(1))
273
274 else
275 select case (eq_axes)
276 case (0, 1)
277 jj = 3
278 case (2)
279 jj = 2
280 case (3)
281 jj = 1
282 end select
283
284 safe_allocate(filename(1:jj))
285 do ii = 1, jj
286 write(filename(ii),'(2a,i1)') trim(fname), '_vector.',ii
287 out_file(ii) = io_open(trim(filename(ii)), global_namespace, action='write')
288 if (.not. reference_multipoles) then
289 call spectrum_cross_section(spectrum, namespace, in_file(ii), out_file(ii))
290 else
291 call spectrum_cross_section(spectrum, namespace, in_file(ii), out_file(ii), ref_file)
292 end if
293 call io_close(in_file(ii))
294 call io_close(out_file(ii))
295 in_file(ii) = io_open(trim(filename(ii)), global_namespace, action='read', status='old')
296 end do
297
298 out_file(1) = io_open(trim(fname)//'_tensor', global_namespace, action='write')
299 call spectrum_cross_section_tensor(spectrum, namespace, out_file(1), in_file(1:jj))
300 do ii = 1, jj
301 call io_close(in_file(ii))
302 end do
303 call io_close(out_file(1))
304
305 end if
306
307 pop_sub(calculate_absorption)
308 end subroutine calculate_absorption
309
310 !----------------------------------------------------------------------------
311 subroutine calculate_dipole_power(fname_in, fname_out)
312 character(len=*), intent(in) :: fname_in, fname_out
313
314 push_sub(calculate_dipole_power)
315
316 in_file(1) = io_open(trim(fname_in), global_namespace, action='read', status='old', die=.false.)
317 if (in_file(1) < 0) in_file(1) = io_open('td.general/'//trim(fname_in), global_namespace, &
318 action='read', status='old', die=.false.)
319 if (in_file(1) >= 0) then
320 write(message(1),'(3a)') 'File "', trim(fname_in), '" found.'
321 write(message(2),'(a)')
322 call messages_info(2)
323 end if
324
325 out_file(1) = io_open(trim(fname_out), global_namespace, action='write')
326 call spectrum_dipole_power(spectrum, global_namespace, in_file(1), out_file(1))
327
328 call io_close(in_file(1))
329 call io_close(out_file(1))
330
332 end subroutine calculate_dipole_power
333
334 !----------------------------------------------------------------------------
335 subroutine calculate_rotatory_strength(fname_in, fname_out)
336 character(len=*), intent(in) :: fname_in, fname_out
337
339
340 in_file(1) = io_open(trim(fname_in), global_namespace, action='read', status='old', die=.false.)
341 if (in_file(1) < 0) in_file(1) = io_open('td.general/'//trim(fname_in), global_namespace, &
342 action='read', status='old', die=.false.)
343 if (in_file(1) >= 0) then
344 write(message(1),'(3a)') 'File "', trim(fname_in), '" found.'
345 write(message(2),'(a)')
346 call messages_info(2)
347 end if
348
349 out_file(1) = io_open(trim(fname_out), global_namespace, action='write')
350 call spectrum_rotatory_strength(spectrum, global_namespace, in_file(1), out_file(1))
351
352 call io_close(in_file(1))
353 call io_close(out_file(1))
354
356 end subroutine calculate_rotatory_strength
357
358
359 !----------------------------------------------------------------------------
360 subroutine calculate_ftchd(fname_in, fname_out)
361 character(len=*), intent(in) :: fname_in, fname_out
362
363 push_sub(calculate_ftchd)
364
365 ! read files
366 in_file(1) = io_open(trim(fname_in) // '.sin', global_namespace, action='read', status='old', die=.false.)
367 in_file(2) = io_open(trim(fname_in) // '.cos', global_namespace, action='read', status='old', die=.false.)
368
369 out_file(1) = io_open(trim(fname_out), global_namespace, action='write')
370 call spectrum_dyn_structure_factor(spectrum, global_namespace, in_file(1), in_file(2), out_file(1))
371 call io_close(in_file(1))
372 call io_close(out_file(1))
373
374 pop_sub(calculate_ftchd)
375 end subroutine calculate_ftchd
376
377end program propagation_spectrum
378
379!! Local Variables:
380!! mode: f90
381!! coding: utf-8
382!! End:
void getopt_propagation_spectrum(char *fname)
Definition: getopt_f.c:4075
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:421
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:280
subroutine, public init_octopus_globals(comm)
Initialise Octopus-specific global constants and files. This routine performs no initialisation calls...
Definition: global.F90:390
Definition: io.F90:116
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:165
subroutine, public io_close(iunit, grp)
Definition: io.F90:466
subroutine, public io_end()
Definition: io.F90:270
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:401
subroutine, public messages_end()
Definition: messages.F90:273
subroutine, public messages_init(output_dir)
Definition: messages.F90:220
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
type(namespace_t), public global_namespace
Definition: namespace.F90:134
subroutine, public parser_init()
Initialise the Octopus parser.
Definition: parser.F90:402
subroutine, public parser_end()
End the Octopus parser.
Definition: parser.F90:434
subroutine, public profiling_end(namespace)
Definition: profiling.F90:415
subroutine, public profiling_init(namespace)
Create profiling subdirectory.
Definition: profiling.F90:257
subroutine, public spectrum_cross_section(spectrum, namespace, in_file, out_file, ref_file)
Definition: spectrum.F90:712
subroutine, public spectrum_cross_section_tensor(spectrum, namespace, out_file, in_file)
Definition: spectrum.F90:432
subroutine, public spectrum_dyn_structure_factor(spectrum, namespace, in_file_sin, in_file_cos, out_file)
Definition: spectrum.F90:1264
subroutine, public spectrum_init(spectrum, namespace, default_energy_step, default_max_energy)
Definition: spectrum.F90:215
subroutine, public spectrum_mult_info(namespace, iunit, nspin, kick, time_steps, dt, file_units, lmax)
Definition: spectrum.F90:2341
subroutine, public spectrum_dipole_power(spectrum, namespace, in_file, out_file)
Definition: spectrum.F90:1156
integer, parameter, public spectrum_energyloss
Definition: spectrum.F90:178
integer, parameter, public spectrum_rotatory
Definition: spectrum.F90:178
subroutine, public spectrum_rotatory_strength(spectrum, namespace, in_file, out_file)
Definition: spectrum.F90:1417
integer, parameter, public spectrum_absorption
Definition: spectrum.F90:178
integer, parameter, public spectrum_p_power
Definition: spectrum.F90:178
subroutine, public string_c_to_f(c_string, f_string)
convert a C string to a Fortran string
Definition: string.F90:292
This module defines the unit system, used for input and output.
subroutine, public unit_system_init(namespace)
subroutine calculate_rotatory_strength(fname_in, fname_out)
subroutine read_files(fname, reffname)
subroutine calculate_ftchd(fname_in, fname_out)
subroutine calculate_absorption(fname, namespace)
subroutine calculate_dipole_power(fname_in, fname_out)
program propagation_spectrum
int true(void)