Octopus
convert.F90
Go to the documentation of this file.
1!! Copyright (C) 2013 J. Alberdi-Rodriguez, J. Jornet-Somoza
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
20
21#include "global.h"
22
23program oct_convert
24 use batch_oct_m
27 use debug_oct_m
29 use fft_oct_m
31 use global_oct_m
32 use io_oct_m
35 use ions_oct_m
36 use kick_oct_m
38 use loct_oct_m
40 use mesh_oct_m
41 use mpi_oct_m
44 use output_oct_m
46 use parser_oct_m
50 use space_oct_m
52 use string_oct_m
53 use unit_oct_m
55 use utils_oct_m
56
57 implicit none
58
59 character(len=256) :: config_str
60 integer :: ierr
61
62 call getopt_init(ierr)
63 config_str = trim(get_config_opts()) // trim(get_optional_libraries())
64 if (ierr == 0) call getopt_octopus(config_str)
65 call getopt_end()
66
67 call global_init()
68
69 call parser_init()
70
71 call messages_init()
72
73 call io_init()
75 call messages_experimental("oct-convert utility")
76
77 call print_header()
78
79 call messages_print_with_emphasis(msg="Convert mode", namespace=global_namespace)
81
85
86 call convert()
87
88 call fft_all_end()
90 call io_end()
91 call print_date("Calculation ended on ")
92 call messages_end()
93
94 call parser_end()
95
96 call global_end()
97
98contains
99
100 ! -------------
105 subroutine convert()
106 type(electrons_t), pointer :: sys
107
108 character(MAX_PATH_LEN) :: basename, folder, ref_name, ref_folder, folder_default
109 integer :: c_start, c_end, c_step, c_start_default, length, c_how
110 logical :: iterate_folder, subtract_file
111 integer, parameter :: CONVERT_FORMAT = 1, fourier_transform = 2, operation = 3
112
113 push_sub(convert)
114
115 call calc_mode_par%set_parallelization(p_strategy_states, default = .false.)
116 sys => electrons_t(global_namespace, generate_epot=.false.)
117 call sys%init_parallelization(mpi_world)
118
119 message(1) = 'Info: Converting files'
120 message(2) = ''
121 call messages_info(2)
122
123 !%Variable ConvertFilename
124 !%Type string
125 !%Default "density"
126 !%Section Utilities::oct-convert
127 !%Description
128 !% Input filename. The original filename which is going to be converted in the format
129 !% specified in <tt>OutputFormat</tt>. It is going to convert various files, it should
130 !% only contain the beginning of the name. For instance, in the case of the restart
131 !% files, it should be one space ' '.
132 !%End
133 call parse_variable(global_namespace, 'ConvertFilename', 'density', basename)
134 if (basename == " ") basename = ""
135 ! Delete the extension if present
136 length = len_trim(basename)
137 if (length > 4) then
138 if (basename(length-3:length) == '.obf') then
139 basename = trim(basename(1:length-4))
140 end if
141 end if
142
143 !%Variable ConvertHow
144 !%Type integer
145 !%Default convert_format
146 !%Section Utilities::oct-convert
147 !%Description
148 !% Select how the mesh function will be converted.
149 !%Option format 1
150 !% The format of the mesh function will be convert from the binary file.obf.
151 !% The format of the output function is set by OutputHow variable.
152 !%Option fourier_transform 2
153 !% A fourier transform of the mesh function will be computed.
154 !% It requieres that ConvertStart and ConvertEnd have to be set.
155 !%Option operation 3
156 !% Convert utility will generate a new mesh function constructed by linear
157 !% combination of scalar function of different mesh functions,
158 !%End
159 call parse_variable(global_namespace, 'ConvertHow', convert_format, c_how)
160
161 !%Variable ConvertIterateFolder
162 !%Type logical
163 !%Default true
164 !%Section Utilities::oct-convert
165 !%Description
166 !% This variable decides if a folder is going to be iterated or the
167 !% filename is going to be iterated.
168 !%End
169 call parse_variable(global_namespace, 'ConvertIterateFolder', .true., iterate_folder)
170
171 if (iterate_folder) then
172 folder_default = 'output_iter/td.'
173 c_start_default = 0
174 else
175 folder_default = 'restart'
176 c_start_default = 1
177 end if
178
179 !%Variable ConvertFolder
180 !%Type string
181 !%Section Utilities::oct-convert
182 !%Description
183 !% The folder name where the input files are. The default is
184 !% <tt>output_iter/td.</tt> if <tt>ConvertIterateFolder = true</tt>, otherwise <tt>restart</tt>.
185 !%End
186 call parse_variable(global_namespace, 'ConvertFolder', folder_default, folder)
187 call add_last_slash(folder)
188
189 !%Variable ConvertStart
190 !%Type integer
191 !%Section Utilities::oct-convert
192 !%Description
193 !% The starting number of the filename or folder.
194 !% Default is 0 if <tt>ConvertIterateFolder = true</tt>, otherwise 1.
195 !%End
196 call parse_variable(global_namespace, 'ConvertStart', c_start_default, c_start)
197
198 !%Variable ConvertEnd
199 !%Type integer
200 !%Default 1
201 !%Section Utilities::oct-convert
202 !%Description
203 !% The last number of the filename or folder.
204 !%End
205 call parse_variable(global_namespace, 'ConvertEnd', 1, c_end)
206
207 !%Variable ConvertStep
208 !%Type integer
209 !%Default 1
210 !%Section Utilities::oct-convert
211 !%Description
212 !% The padding between the filenames or folder.
213 !%End
214 call parse_variable(global_namespace, 'ConvertStep', 1, c_step)
215
216 !%Variable ConvertSubtractFilename
217 !%Type string
218 !%Default density
219 !%Section Utilities::oct-convert
220 !%Description
221 !% Input filename. The file which is going to subtracted to rest of the files.
222 !%End
223 call parse_variable(global_namespace, 'ConvertSubtractFilename', 'density', ref_name)
224 if (ref_name == " ") ref_name = ""
225 ! Delete the extension if present
226 length = len_trim(ref_name)
227 if (length > 4) then
228 if (ref_name(length-3:length) == '.obf') then
229 ref_name = trim(ref_name(1:length-4))
230 end if
231 end if
232
233 !%Variable ConvertSubtract
234 !%Type logical
235 !%Default false
236 !%Section Utilities::oct-convert
237 !%Description
238 !% Decides if a reference file is going to be subtracted.
239 !%End
240 call parse_variable(global_namespace, 'ConvertSubtract', .false., subtract_file)
241
242 !%Variable ConvertSubtractFolder
243 !%Type string
244 !%Default .
245 !%Section Utilities::oct-convert
246 !%Description
247 !% The folder name which is going to be subtracted.
248 !%End
249 call parse_variable(global_namespace, 'ConvertSubtractFolder', '.', ref_folder)
250 call add_last_slash(folder)
251
252 select case (c_how)
253 CASE(operation)
254 call convert_operate(sys%gr, global_namespace, sys%space, sys%ions, sys%mc, sys%outp)
255
256 CASE(fourier_transform)
257 ! Compute Fourier transform
258 call convert_transform(sys%gr, global_namespace, sys%space, sys%ions, sys%mc, sys%kpoints, basename, folder, &
259 c_start, c_end, c_step, sys%outp, subtract_file, &
260 ref_name, ref_folder)
261
262 CASE(convert_format)
263 call convert_low(sys%gr, global_namespace, sys%space, sys%ions, sys%hm%psolver, sys%mc, basename, folder, &
264 c_start, c_end, c_step, sys%outp, iterate_folder, &
265 subtract_file, ref_name, ref_folder)
266 end select
267
268 safe_deallocate_p(sys)
269
270 pop_sub(convert)
271 end subroutine convert
272
273 ! ---------------------------------------------------------
276 subroutine convert_low(mesh, namespace, space, ions, psolver, mc, basename, in_folder, c_start, c_end, c_step, outp, &
277 iterate_folder, subtract_file, ref_name, ref_folder)
278 class(mesh_t), intent(in) :: mesh
279 type(namespace_t), intent(in) :: namespace
280 class(space_t), intent(in) :: space
281 type(ions_t), intent(in) :: ions
282 type(poisson_t), intent(in) :: psolver
283 type(multicomm_t), intent(in) :: mc
284 character(len=*), intent(inout) :: basename
285 character(len=*), intent(in) :: in_folder
286 integer, intent(in) :: c_start
287 integer, intent(in) :: c_end
288 integer, intent(in) :: c_step
289 type(output_t), intent(in) :: outp
290 logical, intent(in) :: iterate_folder
292 logical, intent(in) :: subtract_file
293 character(len=*), intent(inout) :: ref_name
294 character(len=*), intent(inout) :: ref_folder
295
296 type(restart_t) :: restart
297 integer :: ierr, ii, folder_index, output_i
298 character(MAX_PATH_LEN) :: filename, out_name, folder, frmt, restart_folder
299 real(real64), allocatable :: read_ff(:), read_rff(:), pot(:)
300
301 push_sub(convert_low)
302
303 safe_allocate(read_ff(1:mesh%np))
304 safe_allocate(read_rff(1:mesh%np))
305 safe_allocate(pot(1:mesh%np))
306 read_rff(:) = m_zero
307
308 write(message(1),'(5a,i5,a,i5,a,i5)') "Converting '", trim(in_folder), "/", trim(basename), &
309 "' from ", c_start, " to ", c_end, " every ", c_step
310 call messages_info(1)
311
312 if (subtract_file) then
313 write(message(1),'(a,a,a,a)') "Reading ref-file from ", trim(ref_folder), trim(ref_name),".obf"
314 call restart_init(restart, namespace, restart_undefined, restart_type_load, mc, ierr, &
315 dir=trim(ref_folder), mesh = mesh)
316 ! FIXME: why only real functions? Please generalize.
317 if (ierr == 0) then
318 call restart_read_mesh_function(restart, space, trim(ref_name), mesh, read_rff, ierr)
319 call restart_end(restart)
320 else
321 write(message(1),'(2a)') "Failed to read from ref-file ", trim(ref_name)
322 write(message(2), '(2a)') "from folder ", trim(ref_folder)
323 call messages_fatal(2)
324 end if
325 end if
326
327 ! Initialize the restart directory from <tt>ConvertFolder</tt> value.
328 ! This directory has to have the files 'grid' and 'lxyz.obf'
329 ! and the files that are going to be converged, must be inside this folder
330 if (iterate_folder) then
331 ! Delete the last / and find the previous /, if any
332 folder = in_folder(1:len_trim(in_folder)-1)
333 folder_index = index(folder, '/', .true.)
334 restart_folder = folder(1:folder_index)
335 else
336 restart_folder = in_folder
337 end if
338 call restart_init(restart, namespace, restart_undefined, restart_type_load, mc, ierr, &
339 dir=trim(restart_folder), mesh = mesh)
340 call loct_progress_bar(-1, c_end-c_start)
341 do ii = c_start, c_end, c_step
342 if (iterate_folder) then
343 ! Delete the last / and add the corresponding folder number
344 write(folder,'(a,i0.7,a)') in_folder(folder_index+1:len_trim(in_folder)-1),ii,"/"
345 write(filename, '(a,a,a)') trim(folder), trim(basename)
346 out_name = trim(basename)
347 else
348 folder = ""
349 if (c_start /= c_end) then
350 ! Here, we are only considering 10 character long filenames.
351 ! Subtract the initial part given at 'ConvertFilename' from the format and pad
352 ! with zeros.
353 write(frmt,'(a,i0,a)')"(a,i0.",10-len_trim(basename),")"
354 write(filename, fmt=trim(frmt)) trim(basename), ii
355 write(out_name, '(a)') trim(filename)
356 else
357 ! Assuming filename is given complete in the 'ConvertFilename'
358 write(filename, '(a,a,a,a)') trim(folder),"/", trim(basename)
359 filename = basename
360 write(out_name, '(a)') trim(basename)
361 end if
362 end if
363
364 ! Read the obf file
365 call restart_read_mesh_function(restart, space, trim(filename), mesh, read_ff, ierr)
366
367 if (ierr /= 0) then
368 write(message(1), '(a,a)') "Error reading the file ", trim(filename)
369 write(message(2), '(a,i4)') "Error code: ",ierr
370 write(message(3), '(a)') "Skipping...."
371 call messages_warning(3)
372 cycle
373 end if
374 if (subtract_file) then
375 read_ff(:) = read_ff(:) - read_rff(:)
376 write(out_name, '(a,a)') trim(out_name),"-ref"
377 end if
378 ! Write the corresponding output
379 do output_i = lbound(outp%how, 1), ubound(outp%how, 1)
380 if (outp%how(output_i) /= 0) then
381 call dio_function_output(outp%how(output_i), trim(restart_folder)//trim(folder), &
382 trim(out_name), namespace, space, mesh, read_ff, units_out%length**(-space%dim), ierr, &
383 pos=ions%pos, atoms=ions%atom)
384 end if
385 end do
386 if (outp%what(option__output__potential)) then
387 write(out_name, '(a)') "potential"
388 call dpoisson_solve(psolver, namespace, pot, read_ff)
389 call dio_function_output(outp%how(option__output__potential), trim(restart_folder)//trim(folder), &
390 trim(out_name), namespace, space, mesh, pot, units_out%energy, ierr, pos=ions%pos, atoms=ions%atom)
391 end if
392 call loct_progress_bar(ii-c_start, c_end-c_start)
393 ! It does not matter if the current write has failed for the next iteration
394 ierr = 0
395 end do
396 call restart_end(restart)
397
398 safe_deallocate_a(read_ff)
399 safe_deallocate_a(read_rff)
400 safe_deallocate_a(pot)
401 pop_sub(convert_low)
402 end subroutine convert_low
403
404 ! ---------------------------------------------------------
407 subroutine convert_transform(mesh, namespace, space, ions, mc, kpoints, basename, in_folder, c_start, c_end, c_step, outp, &
408 subtract_file, ref_name, ref_folder)
409 class(mesh_t), intent(in) :: mesh
410 type(namespace_t), intent(in) :: namespace
411 class(space_t), intent(in) :: space
412 type(ions_t), intent(in) :: ions
413 type(multicomm_t), intent(in) :: mc
414 type(kpoints_t), intent(in) :: kpoints
415 character(len=*), intent(inout) :: basename
416 character(len=*), intent(in) :: in_folder
417 integer, intent(in) :: c_start
418 integer, intent(in) :: c_end
419 integer, intent(in) :: c_step
420 type(output_t), intent(in) :: outp
421 logical, intent(in) :: subtract_file
422 character(len=*), intent(inout) :: ref_name
423 character(len=*), intent(inout) :: ref_folder
424
425 integer :: ierr, i_space, i_time, nn(1:3), optimize_parity(1:3), wd_info, output_i
426 integer :: i_energy, e_end, e_start, e_point, chunk_size, read_count, t_point
427 logical :: optimize(1:3)
428 integer :: folder_index
429 character(MAX_PATH_LEN) :: filename, folder, restart_folder
430 real(real64) :: fdefault, w_max
431 real(real64), allocatable :: read_ft(:), read_rff(:), point_tmp(:,:)
432
433 integer, parameter :: FAST_FOURIER = 1, standard_fourier = 2
434 type(kick_t) :: kick
435 integer :: ft_method
436 type(spectrum_t) :: spectrum
437 type(batch_t) :: tdrho_b, wdrho_b
438 real(real64), allocatable :: tdrho_a(:,:,:), wdrho_a(:,:,:)
439 type(fft_t) :: fft
440
441 type(restart_t) :: restart
442 complex(real64), allocatable :: out_fft(:)
443
444 real(real64) :: start_time
445 integer :: time_steps
446 real(real64) :: dt
447 real(real64) :: dw
448 real(real64) :: max_energy
449 real(real64) :: min_energy
450
451 push_sub(convert_transform)
452
453 ! set default time_step as dt from TD section
454 fdefault = m_zero
455 call parse_variable(namespace, 'TDTimeStep', fdefault, dt, unit = units_inp%time)
456 if (dt <= m_zero) then
457 write(message(1),'(a)') 'Input: TDTimeStep must be positive.'
458 write(message(2),'(a)') 'Input: TDTimeStep reset to 0. Check input file'
459 call messages_info(2)
460 end if
461
462 call io_mkdir('wd.general', namespace)
463 wd_info = io_open('wd.general/wd.info', global_namespace, action='write')
464 call messages_print_with_emphasis(msg="Fourier Transform Options", iunit=wd_info)
465
466 !%Variable ConvertEnergyMin
467 !%Type float
468 !%Default 0.0
469 !%Section Utilities::oct-convert
470 !%Description
471 !% Minimum energy to output from Fourier transform.
472 !%End
473 call parse_variable(namespace, 'ConvertEnergyMin', m_zero, min_energy, units_inp%energy)
474 call messages_print_var_value('ConvertEnergyMin', min_energy, unit = units_out%energy, iunit=wd_info)
475
476 !%Variable ConvertReadSize
477 !%Type integer
478 !%Default mesh%np
479 !%Section Utilities::oct-convert
480 !%Description
481 !% How many points are read at once. For the parallel run this has not been
482 !% yet tested, so it should be one. For the serial run, a number
483 !% of 100-1000 will speed-up the execution time by this factor.
484 !%End
485 call parse_variable(namespace, 'ConvertReadSize', mesh%np, chunk_size)
486 call messages_print_var_value('ConvertReadSize', chunk_size, iunit=wd_info)
487 !Check that default value is set when ConvertReadSize = 0
488 if (chunk_size == 0) chunk_size = mesh%np
489 ! Parallel version just work in domains and chunk_size equal to mesh%np
490 if (mesh%mpi_grp%size > 1 .and. chunk_size /= mesh%np) then
491 write(message(1),*)'Incompatible value for ConvertReadSize and Parallelizaion in Domains'
492 write(message(2),*)'Use the default value for ConvertReadSize (or set it to 0)'
493 call messages_fatal(2)
494 end if
495
496 ! Calculate the limits in frequency space.
497 start_time = c_start * dt
498 dt = dt * c_step
499 time_steps = (c_end - c_start) / c_step
500 dw = m_two * m_pi / (dt * time_steps)
501 w_max = m_two * m_pi / dt
502
503 !%Variable ConvertEnergyMax
504 !%Type float
505 !%Default w_max
506 !%Section Utilities::oct-convert
507 !%Description
508 !% Maximum energy to output from Fourier transform.
509 !%End
510 fdefault = units_from_atomic(units_inp%energy, w_max)
511 call parse_variable(namespace, 'ConvertEnergyMax',fdefault, max_energy, units_inp%energy)
512 if (max_energy > w_max) then
513 write(message(1),'(a,f12.7)')'Impossible to set ConvertEnergyMax to ', &
514 units_from_atomic(units_inp%energy, max_energy)
515 write(message(2),'(a)')'ConvertEnergyMax is too large.'
516 write(message(3),'(a,f12.7,a)')'ConvertEnergyMax reset to ', &
517 units_from_atomic(units_inp%energy, w_max),'[' // trim(units_abbrev(units_out%energy)) // ']'
518 call messages_info(3)
519 max_energy = w_max
520 end if
521 call messages_print_var_value('ConvertEnergyMax', max_energy, unit = units_out%energy, iunit=wd_info)
522
523 !%Variable ConvertFTMethod
524 !%Type integer
525 !%Default FAST_FOURIER
526 !%Section Utilities::oct-convert
527 !%Description
528 !% Describes the method used to perform the Fourier Transform
529 !%Option fast_fourier 1
530 !% Uses Fast Fourier Transform as implemented in the external library.
531 !%Option standard_fourier 2
532 !% Uses polinomial approach to the computation of discrete Fourier Transform.
533 !% It uses the same variable described in how to obtain spectrum from
534 !% a time-propagation calculation.
535 !%End
536 call parse_variable(namespace, 'ConvertFTMethod', 1, ft_method)
537 call messages_print_var_option('ConvertFTMethod', ft_method, iunit=wd_info)
538
539 !TODO: check if e_point can be used instead of e_point+1
540 safe_allocate(read_ft(0:time_steps))
541 read_ft = m_zero
542 safe_allocate(read_rff(1:mesh%np))
543
544 select case (ft_method)
545 case (fast_fourier)
546 nn(1) = time_steps + 1
547 nn(2) = 1
548 nn(3) = 1
549 safe_allocate(out_fft(0:time_steps))
550 optimize = .false.
551 optimize_parity = -1
552 call fft_init(fft, nn, 1, fft_real, fftlib_fftw, optimize, optimize_parity)
553 case (standard_fourier)
554 !%Variable ConvertEnergyStep
555 !%Type float
556 !%Default <math>2 \pi / T</math>, where <math>T</math> is the total propagation time
557 !%Section Utilities::oct-convert
558 !%Description
559 !% Energy step to output from Fourier transform.
560 !% Sampling rate for the Fourier transform. If you supply a number equal or smaller than zero, then
561 !% the sampling rate will be <math>2 \pi / T</math>, where <math>T</math> is the total propagation time.
562 !%End
563 fdefault = m_two * m_pi / (dt * time_steps)
564 call parse_variable(namespace, 'ConvertEnergyStep',fdefault, dw, units_inp%energy)
565 if (dw <= m_zero) dw = m_two * m_pi / (dt * time_steps)
566
567 call spectrum_init(spectrum, namespace, dw, w_max)
568 ! Manually setting already defined variables on spectrum.
569 spectrum%start_time = c_start * dt
570 spectrum%end_time = c_end * dt
571 spectrum%energy_step = dw
572 spectrum%max_energy = max_energy
573 safe_allocate(tdrho_a(0:time_steps, 1, 1))
574 safe_allocate(wdrho_a(0:time_steps, 1, 1))
575 end select
576 call messages_print_var_value('ConvertEnergyStep', dw, unit = units_out%energy, iunit=wd_info)
577
578 !TODO: set system variable common for all the program in
579 ! order to use call kick_init(kick, sy%st%d%nspin, sys%space%dim, sys%ions%periodic_dim)
580 call kick_init(kick, namespace, space, kpoints, 1)
581
582 e_start = nint(min_energy / dw)
583 e_end = nint(max_energy / dw)
584 write(message(1),'(a,1x,i0.7,a,f12.7,a,i0.7,a,f12.7,a)')'Frequency index:',e_start,'(',&
585 units_from_atomic(units_out%energy, e_start * dw),')-',e_end,'(',units_from_atomic(units_out%energy, e_end * dw),')'
586 write(message(2),'(a,f12.7,a)')'Frequency Step, dw: ', units_from_atomic(units_out%energy, dw), &
587 '[' // trim(units_abbrev(units_out%energy)) // ']'
588 call messages_info(2)
589
590 if (subtract_file) then
591 write(message(1),'(a,a,a,a)') "Reading ref-file from ", trim(ref_folder), trim(ref_name),".obf"
592 call messages_info(1)
593 call restart_init(restart, namespace, restart_undefined, restart_type_load, mc, ierr, &
594 dir=trim(ref_folder), mesh = mesh)
595 ! FIXME: why only real functions? Please generalize.
596 if (ierr == 0) then
597 call restart_read_mesh_function(restart, space, trim(ref_name), mesh, read_rff, ierr)
598 call restart_end(restart)
599 else
600 write(message(1),'(2a)') "Failed to read from ref-file ", trim(ref_name)
601 write(message(2), '(2a)') "from folder ", trim(ref_folder)
602 call messages_fatal(2)
603 end if
604 end if
605
606 call messages_print_with_emphasis(msg="File Information", iunit=wd_info)
607 do i_energy = e_start, e_end
608 write(filename,'(a14,i0.7,a1)')'wd.general/wd.',i_energy,'/'
609 write(message(1),'(a,a,f12.7,a,1x,i7,a)')trim(filename),' w =', &
610 units_from_atomic(units_out%energy,(i_energy) * dw), &
611 '[' // trim(units_abbrev(units_out%energy)) // ']'
612 if (mpi_world%rank == 0) write(wd_info,'(a)') message(1)
613 call messages_info(1)
614 call io_mkdir(trim(filename), namespace)
615 end do
616 call io_close(wd_info)
617
618 if (mesh%parallel_in_domains) then
619 ! Delete the last / and find the previous /, if any
620 folder = in_folder(1:len_trim(in_folder)-1)
621 folder_index = index(folder, '/', .true.)
622 restart_folder = folder(1:folder_index)
623 call restart_init(restart, namespace, restart_undefined, restart_type_load, mc, ierr, &
624 dir=trim(restart_folder), mesh = mesh)
625 end if
626
627 !For each mesh point, open density file and read corresponding point.
628 if (mpi_world%rank == 0) call loct_progress_bar(-1, mesh%np)
629
630 safe_allocate(point_tmp(1:chunk_size, 0:time_steps))
631 read_count = 0
632 ! Space
633 do i_space = 1, mesh%np
634 ! Time
635 t_point = 0
636 do i_time = c_start, c_end, c_step
637
638 if (mesh%parallel_in_domains .and. i_space == 1) then
639 write(folder,'(a,i0.7,a)') in_folder(folder_index+1:len_trim(in_folder)-1),i_time,"/"
640 write(filename, '(a,a,a)') trim(folder), trim(basename)
641 call restart_read_mesh_function(restart, space, trim(filename), mesh, point_tmp(:, t_point), ierr)
642 else
643 ! Here, we always iterate folders
644 ! Delete the last / and add the corresponding folder number
645 write(folder,'(a,i0.7,a)') in_folder(1:len_trim(in_folder)-1),i_time,"/"
646 write(filename, '(a,a,a,a)') trim(folder), trim(basename), ".obf"
647 if (mod(i_space-1, chunk_size) == 0) then
648 call profiling_in("READING")
649 !TODO: check for any error on the whole file before reading by parts.
650 call io_binary_read(trim(filename), i4_to_i8(chunk_size), point_tmp(1:chunk_size, t_point), &
651 ierr, offset=i4_to_i8(i_space-1))
652 call profiling_out("READING")
653 if (i_time == c_start) read_count = 0
654 end if
655 end if
656
657 if (ierr /= 0 .and. i_space == 1) then
658 write(message(1), '(a,a,2i10)') "Error reading the file ", trim(filename), i_space, i_time
659 write(message(2), '(a)') "Skipping...."
660 write(message(3), '(a,i0)') "Error :", ierr
661 call messages_warning(3)
662 cycle
663 end if
664
665 if (i_time == c_start) read_count = read_count + 1
666 if (subtract_file) then
667 read_ft(t_point) = point_tmp(read_count, t_point) - read_rff(i_space)
668 else
669 read_ft(t_point) = point_tmp(read_count, t_point)
670 end if
671
672 t_point = t_point + 1
673 end do ! Time
674
675 select case (ft_method)
676 case (fast_fourier)
677 call profiling_in("CONVERT_FFTW")
678 call dfft_forward(fft, read_ft, out_fft)
679 call profiling_out("CONVERT_FFTW")
680 ! Should the value be multiplied by dt ??? as in standard discrete Fourier Transform ?
681 point_tmp(read_count, 0:time_steps) = aimag(out_fft(0:time_steps)) * dt
682 case (standard_fourier)
683 tdrho_a(0:time_steps, 1, 1) = read_ft(0:time_steps)
684 call batch_init(tdrho_b, 1, 1, 1, tdrho_a)
685 call batch_init(wdrho_b, 1, 1, 1, wdrho_a)
686 call spectrum_signal_damp(spectrum%damp, spectrum%damp_factor, c_start + 1, c_start + time_steps + 1, &
687 kick%time, dt, tdrho_b)
688 call spectrum_fourier_transform(spectrum%method, spectrum%transform, spectrum%noise, &
689 c_start + 1, c_start + time_steps + 1, kick%time, dt, tdrho_b, min_energy, max_energy, &
690 spectrum%energy_step, wdrho_b)
691 call tdrho_b%end()
692 call wdrho_b%end()
693 do e_point = e_start, e_end
694 point_tmp(read_count, e_point) = - wdrho_a(e_point, 1, 1)
695 end do
696 end select
697
698 if (mod(i_space-1, 1000) == 0 .and. mpi_world%rank == 0) then
699 call loct_progress_bar(i_space-1, mesh%np)
700 end if
701
702 !print out wd densities from (ii-chunksize,ii] if running in serial
703 if (mesh%mpi_grp%size == 1) then
704 if (mod(i_space, chunk_size) == 0) then
705 write(message(1),'(a)') ""
706 write(message(2),'(a,i0)') "Writing binary output: step ", i_space/chunk_size
707 call messages_info(2)
708 do i_energy = e_start, e_end
709 write(filename,'(a14,i0.7,a12)')'wd.general/wd.',i_energy,'/density.obf'
710 ! If it is the first time entering here, write the header. But, only once
711 if (i_space == chunk_size) then
712 call dwrite_header(trim(filename), mesh%np_global, ierr)
713 end if
714 call io_binary_write(trim(filename), i4_to_i8(chunk_size), point_tmp(1:chunk_size, i_energy), ierr, &
715 nohead = .true.)
716 end do
717 end if
718 end if
719 end do ! Space
720
721 if (mpi_world%rank == 0) call loct_progress_bar(mesh%np, mesh%np)
722 call mesh%mpi_grp%barrier()
723
724 if (mesh%parallel_in_domains) then
725 do i_energy = e_start, e_end
726 write(filename,'(a14,i0.7,a1)')'wd.general/wd.',i_energy,'/'
727 do output_i = lbound(outp%how, 1), ubound(outp%how, 1)
728 if (outp%how(output_i) /= 0) then
729 call dio_function_output(0_8, trim(filename), &
730 trim('density'), namespace, space, mesh, point_tmp(:, i_energy), &
731 units_out%length**(-space%dim), ierr, pos=ions%pos, atoms=ions%atom)
732 end if
733 end do
734 end do
735 call restart_end(restart)
736 else
737 ! write the output files
738 if (any(outp%how /= option__outputformat__binary)) then
739 do i_energy = e_start, e_end
740 write(filename,'(a14,i0.7,a1)')'wd.general/wd.',i_energy,'/'
741 call io_binary_read(trim(filename)//'density.obf', i4_to_i8(mesh%np), read_rff, ierr)
742 do output_i = lbound(outp%how, 1), ubound(outp%how, 1)
743 if ((outp%how(output_i) /= 0) .and. (outp%how(output_i) /= option__outputformat__binary)) then
744 call dio_function_output(outp%how(output_i), trim(filename), &
745 trim('density'), namespace, space, mesh, read_rff, &
746 units_out%length**(-space%dim), ierr, pos=ions%pos, atoms=ions%atom)
747 end if
748 end do
749 end do
750 end if
751 end if
752
753 safe_deallocate_a(point_tmp)
754 safe_deallocate_a(read_ft)
755 safe_deallocate_a(read_rff)
756
757 select case (ft_method)
758 case (fast_fourier)
759 safe_deallocate_a(out_fft)
760 case (standard_fourier)
761 call kick_end(kick)
762 safe_deallocate_a(tdrho_a)
763 safe_deallocate_a(wdrho_a)
764 end select
765
766 pop_sub(convert_transform)
767 end subroutine convert_transform
768 ! ---------------------------------------------------------
771 subroutine convert_operate(mesh, namespace, space, ions, mc, outp)
772 class(mesh_t), intent(in) :: mesh
773 type(namespace_t), intent(in) :: namespace
774 class(space_t), intent(in) :: space
775 type(ions_t), intent(in) :: ions
776 type(multicomm_t), intent(in) :: mc
777 type(output_t) , intent(in) :: outp
778
779 integer :: ierr, ip, i_op, length, n_operations, output_i
780 type(block_t) :: blk
781 type(restart_t) :: restart
782 type(unit_t) :: units
783 real(real64) :: f_re, f_im
784 real(real64), allocatable :: tmp_ff(:), scalar_ff(:)
785
786 character(len=200) :: var, scalar_expression
787 character(len=MAX_PATH_LEN) :: folder, filename, out_folder, out_filename
788
789 push_sub(convert_operate)
790
791 !%Variable ConvertScalarOperation
792 !%Type block
793 !%Section Utilities::oct-convert
794 !%Description
795 !% This variable is used to generate a new mesh function as a linear combination
796 !% different mesh function having the same mesh. Each row defines an operation for
797 !% for a single mesh function.
798 !% The format of the block is the following: <br>
799 !% 'variable name' | 'folder' | 'file' | 'operation'
800 !%End
801 ! First, find out if there is a ConvertScalarOperation block.
802 n_operations = 0
803 if (parse_block(namespace, 'ConvertScalarOperation', blk) == 0) then
804 n_operations = parse_block_n(blk)
805 end if
806
807 if (n_operations == 0) then
808 write(message(1),'(a)')'No operations found. Check the input file'
809 call messages_fatal(1)
810 end if
811
812 !%Variable ConvertOutputFolder
813 !%Type string
814 !%Section Utilities::oct-convert
815 !%Description
816 !% The folder name where the output files will be write. The default is
817 !% <tt>convert</tt>.
818 !%End
819 call parse_variable(namespace, 'ConvertOutputFolder', "convert", out_folder)
820 call add_last_slash(out_folder)
821 call io_mkdir(out_folder, namespace)
822
823 !%Variable ConvertOutputFilename
824 !%Type string
825 !%Default "density"
826 !%Section Utilities::oct-convert
827 !%Description
828 !% Output filename. The name of the file in which the converted mesh function will be
829 !% written in the format specified in <tt>OutputFormat</tt>.
830 !%End
831 call parse_variable(namespace, 'ConvertOutputFilename', 'density', out_filename)
832
833 safe_allocate(tmp_ff(1:mesh%np))
834 safe_allocate(scalar_ff(1:mesh%np))
835 scalar_ff = m_zero
836
837 do i_op = 1, n_operations
838 !read variable name
839 call parse_block_string(blk, i_op-1, 0, var)
840 !read folder path
841 call parse_block_string(blk, i_op-1, 1, folder)
842 call add_last_slash(folder)
843 !read file
844 call parse_block_string(blk, i_op-1, 2, filename)
845 ! Delete the extension if present
846 length = len_trim(filename)
847 if (length > 4) then
848 if (filename(length-3:length) == '.obf') then
849 filename = trim(filename(1:length-4))
850 end if
851 end if
852 ! FIXME: why only real functions? Please generalize.
853 ! TODO: check if mesh function are real or complex.
854 call restart_init(restart, namespace, restart_undefined, restart_type_load, mc, ierr, &
855 dir=trim(folder), mesh = mesh, exact=.true.)
856 if (ierr == 0) then
857 call restart_read_mesh_function(restart, space, trim(filename), mesh, tmp_ff, ierr)
858 else
859 write(message(1),'(2a)') "Failed to read from file ", trim(filename)
860 write(message(2), '(2a)') "from folder ", trim(folder)
861 call messages_fatal(2)
862 end if
863 !read scalar expression
864 call parse_block_string(blk, i_op-1, 3, scalar_expression)
865
866 do ip = 1, mesh%np
867 call parse_expression(f_re, f_im, trim(var), real(tmp_ff(ip), real64), trim(scalar_expression))
868 !TODO: implement use of complex functions.
869 scalar_ff(ip) = scalar_ff(ip) + f_re
870 end do
871
872 call restart_end(restart)
873
874 end do
875
876 call parse_block_end(blk)
877
878 call mesh%mpi_grp%barrier()
879 ! Write the corresponding output
880 !TODO: add variable ConvertFunctionType to select the type(density, wfs, potential, ...)
881 ! and units of the conversion.
882 units = units_out%length**(-space%dim)
883 do output_i = lbound(outp%how, 1), ubound(outp%how, 1)
884 if (outp%how(output_i) /= 0) then
885 call dio_function_output(outp%how(output_i), trim(out_folder), trim(out_filename), namespace, space, mesh, &
886 scalar_ff, units, ierr, pos=ions%pos, atoms=ions%atom)
887 end if
888 end do
889
890 safe_deallocate_a(tmp_ff)
891 safe_deallocate_a(scalar_ff)
892
893 pop_sub(convert_operate)
894 end subroutine convert_operate
895end program
896
897!! Local Variables:
898!! mode: f90
899!! coding: utf-8
900!! End:
program oct_convert
This utility runs in parallel and can be used for post-processing of the results of Output.
Definition: convert.F90:116
subroutine convert_low(mesh, namespace, space, ions, psolver, mc, basename, in_folder, c_start, c_end, c_step, outp, iterate_folder, subtract_file, ref_name, ref_folder)
Giving a range of input files, it writes the corresponding output files.
Definition: convert.F90:371
subroutine convert_operate(mesh, namespace, space, ions, mc, outp)
Given a set of mesh function operations it computes a a resulting mesh function from linear combinati...
Definition: convert.F90:865
subroutine convert_transform(mesh, namespace, space, ions, mc, kpoints, basename, in_folder, c_start, c_end, c_step, outp, subtract_file, ref_name, ref_folder)
Giving a range of input files, it computes the Fourier transform of the file.
Definition: convert.F90:502
initialize a batch with existing memory
Definition: batch.F90:267
Each program/utility that needs to use the getopt features should have an interface here – the defini...
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
Definition: messages.F90:180
static void convert(multi *in, multi *out, int t_in, int t_out)
Definition: io_binary.c:5135
This module implements batches of mesh functions.
Definition: batch.F90:133
This module handles the calculation mode.
type(calc_mode_par_t), public calc_mode_par
Singleton instance of parallel calculation mode.
integer, parameter, public p_strategy_states
parallelization in states
subroutine, public getopt_init(ierr)
Initializes the getopt machinery. Must be called before attempting to parse the options....
subroutine, public getopt_end
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
Definition: fft.F90:118
subroutine, public fft_init(this, nn, dim, type, library, optimize, optimize_parity, comm, mpi_grp, use_aligned)
Definition: fft.F90:418
subroutine, public fft_all_init(namespace)
initialize the table
Definition: fft.F90:278
subroutine, public fft_all_end()
delete all plans
Definition: fft.F90:391
integer, parameter, public fft_real
Definition: fft.F90:178
integer, parameter, public fftlib_fftw
Definition: fft.F90:183
real(real64), parameter, public m_two
Definition: global.F90:190
subroutine, public global_end()
Finalise parser varinfo file, and MPI.
Definition: global.F90:382
real(real64), parameter, public m_zero
Definition: global.F90:188
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:186
subroutine, public global_init(communicator)
Initialise Octopus.
Definition: global.F90:325
subroutine, public dwrite_header(fname, np_global, ierr)
subroutine, public dio_function_output(how, dir, fname, namespace, space, mesh, ff, unit, ierr, pos, atoms, grp, root)
Top-level IO routine for functions defined on the mesh.
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:161
subroutine, public io_close(iunit, grp)
Definition: io.F90:418
subroutine, public io_end()
Definition: io.F90:258
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:311
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:352
subroutine, public kick_end(kick)
Definition: kick.F90:795
subroutine, public kick_init(kick, namespace, space, kpoints, nspin)
Definition: kick.F90:223
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_end()
Definition: messages.F90:277
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:920
character(len=512), private msg
Definition: messages.F90:165
subroutine, public messages_init(output_dir)
Definition: messages.F90:224
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:537
subroutine, public print_date(str)
Definition: messages.F90:1005
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:414
subroutine, public messages_experimental(name, namespace)
Definition: messages.F90:1085
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:616
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:266
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:145
type(namespace_t), public global_namespace
Definition: namespace.F90:132
this module contains the low-level part of the output system
Definition: output_low.F90:115
this module contains the output system
Definition: output.F90:115
subroutine, public parser_init()
Initialise the Octopus parser.
Definition: parser.F90:450
subroutine, public parser_end()
End the Octopus parser.
Definition: parser.F90:481
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:618
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel, reset)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:892
subroutine, public profiling_end(namespace)
Definition: profiling.F90:413
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:623
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:552
subroutine, public profiling_init(namespace)
Create profiling subdirectory.
Definition: profiling.F90:255
subroutine, public restart_module_init(namespace)
Definition: restart.F90:308
integer, parameter, public restart_undefined
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_load
Definition: restart.F90:245
subroutine, public restart_end(restart)
Definition: restart.F90:722
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:2637
subroutine, public spectrum_init(spectrum, namespace, default_energy_step, default_max_energy)
Definition: spectrum.F90:213
integer default
Definition: spectrum.F90:207
subroutine, public spectrum_signal_damp(damp_type, damp_factor, time_start, time_end, t0, time_step, time_function)
Definition: spectrum.F90:2551
subroutine, public add_last_slash(str)
Adds a '/' in the end of the string, only if it missing. Useful for directories.
Definition: string.F90:161
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_system_t), public units_out
subroutine, public unit_system_init(namespace)
type(unit_system_t), public units_inp
the units systems for reading and writing
This module is intended to contain simple general-purpose utility functions and procedures.
Definition: utils.F90:118
character(len=256) function, public get_config_opts()
Definition: utils.F90:360
character(len=256) function, public get_optional_libraries()
Definition: utils.F90:383
subroutine, public print_header()
This subroutine prints the logo followed by information about the compilation and the system....
Definition: utils.F90:301
Class defining batches of mesh functions.
Definition: batch.F90:159
Class describing the electron system.
Definition: electrons.F90:218
Describes mesh distribution to nodes.
Definition: mesh.F90:186
Stores all communicators and groups.
Definition: multicomm.F90:206
output handler class
Definition: output_low.F90:164
int true(void)