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