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