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