Octopus
local_write.F90
Go to the documentation of this file.
1!! Copyright (C) 2014 M. Marques, A. Castro, A. Rubio, G. Bertsch, J.Jornet-Somoza
2!! Copyright (C) 2020 M. Oliveira
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
23 use iso_c_binding
24 use debug_oct_m
26 use global_oct_m
29 use io_oct_m
31 use ions_oct_m
32 use kick_oct_m
34 use mesh_oct_m
36 use mpi_oct_m
38 use parser_oct_m
41 use space_oct_m
43 use unit_oct_m
46 use v_ks_oct_m
48
49 implicit none
50
51 private
52 public :: &
58
59 integer, parameter :: &
60 LOCAL_OUT_MULTIPOLES = 1, &
63 local_out_energy = 8, &
65
67 private
68 type(c_ptr) :: handle
69 logical :: write = .false.
70 end type local_write_prop_t
71
72 type local_write_t
73 private
74 type(local_write_prop_t), allocatable :: out(:)
75 integer(int64) :: how
76 integer :: lmax
77 end type local_write_t
78
79contains
80
81 ! ---------------------------------------------------------
82 logical function local_write_check_hm(writ) result(check)
83 type(local_write_t), intent(in) :: writ
84
85 push_sub(local_write_check_hm)
86
87 check = writ%out(local_out_potential)%write .or. writ%out(local_out_energy)%write
88
90 end function local_write_check_hm
91
92 ! ---------------------------------------------------------
93 subroutine local_write_init(writ, namespace, lab, iter, dt)
94 type(local_write_t), intent(inout) :: writ
95 type(namespace_t), intent(in) :: namespace
96 character(len=15), intent(in) :: lab
97 integer, intent(in) :: iter
98 real(real64), intent(in) :: dt
99
100 integer :: first, flags, iout, default
101
102 push_sub(local_write_init)
103
104 ! FIXME: if and when these routines are called from a normal run, the Section can be Output.
105 ! but then it will need to be in a different folder, since src/util is not linked by the other folders.
106
107 !%Variable LDOutput
108 !%Type flag
109 !%Default multipoles
110 !%Section Utilities::oct-local_multipoles
111 !%Description
112 !% Defines what should be output during the local domains
113 !% simulation. Many of the options can increase the computational
114 !% cost of the simulation, so only use the ones that you need. In
115 !% most cases the default value is enough, as it is adapted to the
116 !% details.
117 !%Option multipoles 1
118 !% Outputs the (electric) multipole moments of the density to the file <tt>ld.general/multipoles</tt>.
119 !% This is required to, <i>e.g.</i>, calculate optical absorption spectra of finite systems. The
120 !% maximum value of <math>l</math> can be set with the variable <tt>LDMultipoleLmax</tt>.
121 !%Option density 2
122 !% If set, <tt>octopus</tt> outputs the densities corresponding to the local domains to
123 !% the folder <tt>ld.general/densities</tt>.
124 !% The output format is set by the <tt>LDOutputFormat</tt> input variable.
125 !%Option local_v 4
126 !% If set, <tt>octopus</tt> outputs the different components of the potential
127 !% to the folder <tt>ld.general/potential</tt>.
128 !% The output format is set by the <tt>LDOutputFormat</tt> input variable.
129 !%Option energy 8
130 !% If set, <tt>octopus</tt> outputs the different components of the energy of the local domains
131 !% to the folder <tt>ld.general/energy</tt>.
132 !%End
133
134 default = 2**(local_out_multipoles - 1)
135
136 call parse_variable(namespace, 'LDOutput', default, flags)
137
138 if (.not. varinfo_valid_option('LDOutput', flags, is_flag = .true.)) then
139 call messages_input_error(namespace, 'LDOutput')
140 end if
141
142 safe_allocate(writ%out(1:local_out_max))
143 do iout = 1, local_out_max
144 writ%out(iout)%write = (bitand(flags, 2**(iout - 1)) /= 0)
145 end do
146
147 call messages_obsolete_variable(namespace, 'LDOutputHow', 'LDOutputFormat')
148
149 !%Variable LDOutputFormat
150 !%Type flag
151 !%Default none
152 !%Section Utilities::oct-local_multipoles
153 !%Description
154 !% Describes the format of the output files (see <tt>LDOutput</tt>).
155 !% It can take the same values as <tt>OutputFormat</tt> flag.
156 !%End
157 call parse_variable(namespace, 'LDOutputFormat', 0, writ%how)
158 if (.not. varinfo_valid_option('OutputFormat', writ%how, is_flag=.true.)) then
159 call messages_input_error(namespace, 'LDOutputFormat')
160 end if
162 !%Variable LDMultipoleLmax
163 !%Type integer
164 !%Default 1
165 !%Section Utilities::oct-local_multipoles
166 !%Description
167 !% Maximum electric multipole of the density output to the file <tt>local.multipoles/<>domain%<>.multipoles</tt>
168 !% during a time-dependent simulation. Must be non-negative.
169 !%End
170 call parse_variable(namespace, 'LDMultipoleLmax', 1, writ%lmax)
171 if (writ%lmax < 0) then
172 write(message(1), '(a,i6,a)') "Input: '", writ%lmax, "' is not a valid LDMultipoleLmax."
173 message(2) = '(Must be LDMultipoleLmax >= 0)'
174 call messages_fatal(2, namespace=namespace)
175 end if
176
177 call io_mkdir('local.general', namespace)
178
179 if (mpi_grp_is_root(mpi_world)) then
180 if (writ%out(local_out_multipoles)%write) then
181 call io_mkdir('local.general/multipoles', namespace)
182 call write_iter_init(writ%out(local_out_multipoles)%handle, iter, units_from_atomic(units_out%time, dt), &
183 trim(io_workpath("local.general/multipoles/"//trim(lab)//".multipoles", namespace)))
184 end if
185
186 if (writ%out(local_out_potential)%write) then
187 call io_mkdir('local.general/potential', namespace)
188 call write_iter_init(writ%out(local_out_potential)%handle, first, units_from_atomic(units_out%time, dt), &
189 trim(io_workpath("local.general/potential/"//trim(lab)//".potential", namespace)))
190 end if
191
192 if (writ%out(local_out_density)%write) then
193 call io_mkdir('local.general/densities', namespace)
194 call write_iter_init(writ%out(local_out_density)%handle, first, units_from_atomic(units_out%time, dt), &
195 trim(io_workpath("local.general/densities/"//trim(lab)//".densities", namespace)))
196 end if
197
198 if (writ%out(local_out_energy)%write) then
199 call io_mkdir('local.general/energy', namespace)
200 call write_iter_init(writ%out(local_out_energy)%handle, iter, units_from_atomic(units_out%time, dt), &
201 trim(io_workpath("local.general/energy/"//trim(lab)//".energy", namespace)))
202 end if
203 end if
204
205 pop_sub(local_write_init)
206 end subroutine local_write_init
207
208 ! ---------------------------------------------------------
209 subroutine local_write_end(writ)
210 type(local_write_t), intent(inout) :: writ
211
212 integer :: iout
213
214 push_sub(local_write_end)
215
216 if (mpi_grp_is_root(mpi_world)) then
217 do iout = 1, local_out_max
218 if (writ%out(iout)%write) then
219 call write_iter_end(writ%out(iout)%handle)
220 end if
221 end do
222 end if
223 safe_deallocate_a(writ%out)
224
225 pop_sub(local_write_end)
226 end subroutine local_write_end
227
228 ! ---------------------------------------------------------
229 subroutine local_write_iter(writ, namespace, space, lab, ions_mask, mesh_mask, mesh, st, hm, ks, &
230 ions, ext_partners, kick, iter, l_start, ldoverwrite)
231 type(local_write_t), intent(inout) :: writ
232 type(namespace_t), intent(in) :: namespace
233 type(electron_space_t), intent(in) :: space
234 character(len=15), intent(in) :: lab
235 logical, intent(in) :: ions_mask(:)
236 logical, intent(in) :: mesh_mask(:)
237 class(mesh_t), intent(in) :: mesh
238 type(states_elec_t), intent(inout) :: st
239 type(hamiltonian_elec_t), intent(inout) :: hm
240 type(v_ks_t), intent(inout) :: ks
241 type(ions_t), intent(inout) :: ions
242 type(partner_list_t), intent(in) :: ext_partners
243 type(kick_t), intent(inout) :: kick
244 integer, intent(in) :: iter
245 integer, intent(in) :: l_start
246 logical, intent(in) :: ldoverwrite
247
248
249 push_sub(local_write_iter)
250 call profiling_in("LOCAL_WRITE_ITER")
251
252 if (writ%out(local_out_multipoles)%write) then
253 call local_write_multipole(writ%out(local_out_multipoles), namespace, lab, ions_mask, mesh_mask, mesh, ions, st, &
254 writ%lmax, kick, iter, l_start, ldoverwrite, writ%how)
255 if (mpi_grp_is_root(mpi_world)) then
256 call write_iter_flush(writ%out(local_out_multipoles)%handle)
257 end if
258 end if
259
260 if (writ%out(local_out_density)%write .or. writ%out(local_out_potential)%write) then
261 call local_write_density(writ%out(local_out_density), namespace, space, writ%out(local_out_potential), lab, mesh_mask, &
262 mesh, ions, ext_partners, st, hm, ks, iter, writ%how)
263 end if
264
265 if (writ%out(local_out_energy)%write) then
266 call local_write_energy(writ%out(local_out_energy), namespace, space, lab, mesh_mask, mesh, ions, &
267 ext_partners, st, hm, ks, iter, l_start, ldoverwrite)
268 if (mpi_grp_is_root(mpi_world)) then
269 call write_iter_flush(writ%out(local_out_energy)%handle)
270 end if
271 end if
272
273 call profiling_out("LOCAL_WRITE_ITER")
274 pop_sub(local_write_iter)
275 end subroutine local_write_iter
276
277 ! ---------------------------------------------------------
278 subroutine local_write_density(out_dens, namespace, space, out_pot, lab, mesh_mask, mesh, ions, &
279 ext_partners, st, hm, ks, iter, how)
280 type(local_write_prop_t), intent(inout) :: out_dens
281 type(namespace_t), intent(in) :: namespace
282 type(electron_space_t), intent(in) :: space
283 type(local_write_prop_t), intent(inout) :: out_pot
284 character(len=15), intent(in) :: lab
285 logical, intent(in) :: mesh_mask(:)
286 class(mesh_t), intent(in) :: mesh
287 type(ions_t), intent(inout) :: ions
288 type(partner_list_t), intent(in) :: ext_partners
289 type(states_elec_t), intent(inout) :: st
290 type(hamiltonian_elec_t), intent(inout) :: hm
291 type(v_ks_t), intent(inout) :: ks
292 integer, intent(in) :: iter
293 integer(int64), intent(in) :: how
294
295 integer :: is, ierr
296 character(len=120) :: folder, out_name
297 real(real64), allocatable :: tmp_rho(:), st_rho(:)
298 real(real64), allocatable :: tmp_vh(:)
299
300 push_sub(local_write_density)
301
302 safe_allocate(tmp_rho(1:mesh%np))
303 safe_allocate(st_rho(1:mesh%np_part))
304 safe_allocate(tmp_vh(1:mesh%np))
305
306 ! FIXME: use just v_ks_calc subroutine for either compute vhartree and vxc
307 do is = 1, st%d%nspin
308 st_rho(:) = st%rho(:, is)
309 where (mesh_mask)
310 tmp_rho = st_rho
311 elsewhere
312 tmp_rho = m_zero
313 end where
314
315 if (out_dens%write) then
316 folder = 'local.general/densities/'//trim(lab)//'.densities/'
317 write(out_name, '(a,a1,i0,a1,i7.7)') trim(lab), '.', is,'.', iter
318 call dio_function_output(how, trim(folder), trim(out_name), namespace, space, mesh, tmp_rho(1:mesh%np), &
319 units_out%length, ierr, pos=ions%pos, atoms=ions%atom)
320 end if
321
322 if (out_pot%write) then
323 !Computes Hartree potential just for n[r], r belongs to id domain.
324 tmp_vh = m_zero
325 call dpoisson_solve(hm%psolver, namespace, tmp_vh, tmp_rho)
326 folder = 'local.general/potential/'//trim(lab)//'.potential/'
327 write(out_name, '(a,i0,a1,i7.7)') 'vh.', is, '.', iter
328 call dio_function_output(how, trim(folder), trim(out_name), namespace, space, mesh, tmp_vh, units_out%length, ierr, &
329 pos=ions%pos, atoms=ions%atom)
330 !Computes XC potential
331 where (mesh_mask)
332 st%rho(:, is) = st_rho
333 elsewhere
334 st%rho(:, is) = m_zero
335 end where
336 call v_ks_calc(ks, namespace, space, hm, st, ions, ext_partners, calc_eigenval = .false. , calc_energy = .false.)
337 folder = 'local.general/potential/'//trim(lab)//'.potential/'
338 write(out_name, '(a,i0,a1,i7.7)') 'vxc.', is, '.', iter
339 call dio_function_output(how, trim(folder), trim(out_name), namespace, space, mesh, hm%vxc(:,is), units_out%length, ierr, &
340 pos=ions%pos, atoms=ions%atom)
341 st%rho(:,is) = st_rho(:)
342 end if
343 end do
344
345 if (out_pot%write) then
346 do is = 1, st%d%nspin
347 !Computes Hartree potential
348 call dpoisson_solve(hm%psolver, namespace, hm%vhartree, st%rho(1:mesh%np, is))
349 folder = 'local.general/potential/'
350 write(out_name, '(a,i0,a1,i7.7)') 'global-vh.', is, '.', iter
351 call dio_function_output(how, trim(folder), trim(out_name), namespace, space, mesh, hm%vhartree, units_out%length, ierr, &
352 pos=ions%pos, atoms=ions%atom)
353 !Computes global XC potential
354 call v_ks_calc(ks, namespace, space, hm, st, ions, ext_partners, calc_eigenval = .false. , calc_energy = .false.)
355 folder = 'local.general/potential/'
356 write(out_name, '(a,i0,a1,i7.7)') 'global-vxc.', is, '.', iter
357 call dio_function_output(how, trim(folder), trim(out_name), namespace, space, mesh, hm%vxc(:,is), units_out%length, ierr, &
358 pos=ions%pos, atoms=ions%atom)
359 end do
360 end if
361
362 safe_deallocate_a(tmp_vh)
363 safe_deallocate_a(st_rho)
364 safe_deallocate_a(tmp_rho)
365
366 pop_sub(local_write_density)
367 end subroutine local_write_density
368
369 ! ---------------------------------------------------------
370 subroutine local_write_energy(out_energy, namespace, space, lab, mesh_mask, mesh, ions, ext_partners, &
371 st, hm, ks, iter, l_start, start)
372 type(local_write_prop_t), intent(inout) :: out_energy
373 type(namespace_t), intent(in) :: namespace
374 type(electron_space_t), intent(in) :: space
375 character(len=15), intent(in) :: lab
376 logical, intent(in) :: mesh_mask(:)
377 class(mesh_t), intent(in) :: mesh
378 type(ions_t), intent(inout) :: ions
379 type(partner_list_t), intent(in) :: ext_partners
380 type(states_elec_t), intent(inout) :: st
381 type(hamiltonian_elec_t), intent(inout) :: hm
382 type(v_ks_t), intent(inout) :: ks
383 integer, intent(in) :: iter
384 integer, intent(in) :: l_start
385 logical, intent(in) :: start
386
387 !integer :: ix
388 integer :: ii, is
389 character(len=120) :: aux
390 real(real64) :: geh, gexc, leh, lexc
391 real(real64), allocatable :: tmp_rhoi(:), st_rho(:)
392 real(real64), allocatable :: hm_vxc(:), hm_vh(:)
393
394 push_sub(local_write_energy)
395
396 safe_allocate(tmp_rhoi(1:mesh%np))
397 safe_allocate(st_rho(1:mesh%np_part))
398 safe_allocate(hm_vxc(1:mesh%np))
399 safe_allocate(hm_vh(1:mesh%np_part))
400
401 if (mpi_grp_is_root(mpi_world)) then ! only first node outputs
402
403 if (iter == l_start .and. start) then
404 call local_write_print_header_init(out_energy%handle)
405
406 ! first line -> column names
407 write(aux,'(a,2x,a)')'# Domain ID:', trim(lab)
408 call write_iter_header(out_energy%handle, trim(aux))
409 write(aux,'(a)') trim(lab)
410 call write_iter_header(out_energy%handle, trim(aux))
411 call write_iter_nl(out_energy%handle)
412 call write_iter_header_start(out_energy%handle)
413 aux = 'Total Hartree'
414 call write_iter_header(out_energy%handle, trim(aux))
415 aux = 'Total Int[n*vxc]'
416 call write_iter_header(out_energy%handle, trim(aux))
417 write(aux,'(a)') 'Int[n*vh]'
418 call write_iter_header(out_energy%handle, trim(aux))
419 write(aux,'(a)')'Int[n*vxc]'
420 call write_iter_header(out_energy%handle, trim(aux))
421! Cross-terms between different domains are currently disabled
422! do jd = 1, nd
423! if (jd /= id) then
424! write(aux,'(a,i2.2,a,i2.2,a)')'Int[n(',id,')*vh(',jd,')]'
425! call write_iter_header(out_energy(id)%handle, trim(aux))
426! write(aux,'(a,i2.2,a,i2.2,a)')'Int[n(',id,')*vxc(',jd,')]'
427! call write_iter_header(out_energy(id)%handle, trim(aux))
428! end if
429! end do
430 call write_iter_nl(out_energy%handle)
431
432 ! units
433 call write_iter_string(out_energy%handle, '#[Iter n.]')
434 call write_iter_header(out_energy%handle, '[' // trim(units_abbrev(units_out%time)) // ']')
435 do ii = 1, 4
436 call write_iter_header(out_energy%handle, '[' // trim(units_abbrev(units_out%energy)) // ']')
437 end do
438 call write_iter_nl(out_energy%handle)
439
440 call local_write_print_header_end(out_energy%handle)
441 end if
442 end if
443
444 ! TODO: Make new files for each nspin value.
445 do is = 1, st%d%nspin
446 ! Compute Hartree potential
447 call dpoisson_solve(hm%psolver, namespace, hm%vhartree, st%rho(1:mesh%np, is))
448 ! Compute XC potential
449 call v_ks_calc(ks, namespace, space, hm, st, ions, ext_partners, calc_eigenval = .false. , calc_energy = .false.)
450
451 st_rho(:) = st%rho(:, is)
452 hm_vxc(:) = hm%vxc(:, is)
453 hm_vh(:) = hm%vhartree(:)
454 ! Compute Global Values
455 geh = dmf_integrate(mesh, st_rho(1:mesh%np)*hm%vhartree(1:mesh%np))
456 gexc = dmf_integrate(mesh, st_rho(1:mesh%np)*hm_vxc(1:mesh%np))
457 if (mpi_grp_is_root(mpi_world)) then
458 call write_iter_set(out_energy%handle, iter)
459 call write_iter_start(out_energy%handle)
460 call write_iter_double(out_energy%handle, units_from_atomic(units_out%energy, geh), 1)
461 call write_iter_double(out_energy%handle, units_from_atomic(units_out%energy, gexc), 1)
462 end if
464 !Compute Local Values
465 hm%vxc(:,is) = m_zero
466 hm%vhartree(:) = m_zero
467 where (mesh_mask)
468 st%rho(:, is) = st_rho
469 elsewhere
470 st%rho(:, is) = m_zero
471 end where
472
473 call v_ks_calc(ks, namespace, space, hm, st, ions, ext_partners, &
474 calc_eigenval = .false. , calc_energy = .false.)
475 tmp_rhoi(1:mesh%np) = st%rho(1:mesh%np, is)
476 !eh = Int[n*v_h]
477 leh = dmf_integrate(mesh, tmp_rhoi*hm%vhartree(1:mesh%np))
478 !exc = Int[n*v_xc]
479 lexc = dmf_integrate(mesh, tmp_rhoi*hm%vxc(1:mesh%np,is))
480 if (mpi_grp_is_root(mpi_world)) then
481 call write_iter_double(out_energy%handle, units_from_atomic(units_out%energy, leh), 1)
482 call write_iter_double(out_energy%handle, units_from_atomic(units_out%energy, lexc), 1)
483 end if
484
485! Cross-terms between different domains are currently disabled
486! do jd = 1, nd
487! if (jd /= id) then
488 ! TODO: Check for domains overlaping to avoid segmentation fault.
489 !eh = Int[n(id)*v_h(jd)]
490! st%rho(:,is) = M_ZERO
491! hm%vxc(:,is) = M_ZERO
492! hm%vhartree(:) = M_ZERO
493! do ix = 1, mesh%np
494! if (mesh_mask(ix, jd)) st%rho(ix, is) = st_rho(ix)
495! end do
496! call v_ks_calc(ks, namespace, hm, st, ions, calc_eigenval = .false. , calc_energy = .false.)
497! leh = dmf_integrate(mesh, tmp_rhoi*hm%vhartree(1:mesh%np))
498 !exc = Int[n(id)*v_xc(jd)]
499! lexc = dmf_integrate(mesh, tmp_rhoi*hm%vxc(1:mesh%np, is))
500! if (mpi_grp_is_root(mpi_world)) then
501! call write_iter_double(out_energy(id)%handle, units_from_atomic(units_out%energy, leh), 1)
502! call write_iter_double(out_energy(id)%handle, units_from_atomic(units_out%energy, lexc), 1)
503! end if
504! end if
505! end do
506 st%rho(:,is) = st_rho(:)
507 hm%vxc(:,is) = hm_vxc(:)
508 hm%vhartree(:) = hm_vh(:)
509 if (mpi_grp_is_root(mpi_world)) then
510 call write_iter_nl(out_energy%handle)
511 end if
512 end do
513
514 safe_deallocate_a(hm_vh)
515 safe_deallocate_a(hm_vxc)
516 safe_deallocate_a(st_rho)
517 safe_deallocate_a(tmp_rhoi)
518
519 pop_sub(local_write_energy)
520 end subroutine local_write_energy
521
522 ! ---------------------------------------------------------
523 subroutine local_write_multipole(out_multip, namespace, lab, ions_mask, mesh_mask, mesh, ions, st, lmax, kick, iter, l_start, &
524 start, how)
525 type(local_write_prop_t), intent(inout) :: out_multip
526 type(namespace_t), intent(in) :: namespace
527 character(len=15), intent(in) :: lab
528 logical, intent(in) :: ions_mask(:)
529 logical, intent(in) :: mesh_mask(:)
530 class(mesh_t), intent(in) :: mesh
531 type(ions_t), intent(in) :: ions
532 type(states_elec_t), intent(in) :: st
533 integer, intent(in) :: lmax
534 type(kick_t), intent(in) :: kick
535 integer, intent(in) :: iter
536 integer, intent(in) :: l_start
537 logical, intent(in) :: start
538 integer(int64), intent(in) :: how
539
540 integer :: is, ll, mm, add_lm
541 character(len=120) :: aux
542 real(real64) :: ionic_dipole(ions%space%dim), center(mesh%box%dim)
543 real(real64), allocatable :: multipole(:,:)
544 logical :: use_ionic_dipole
545
546 push_sub(local_write_multipole)
547
548 if (mpi_grp_is_root(mpi_world).and. iter == l_start .and. start) then
549 call local_write_print_header_init(out_multip%handle)
550
551 write(aux, '(a15,i2)') '# nspin ', st%d%nspin
552 call write_iter_string(out_multip%handle, aux)
553 call write_iter_nl(out_multip%handle)
554
555 write(aux, '(a15,i2)') '# lmax ', lmax
556 call write_iter_string(out_multip%handle, aux)
557 call write_iter_nl(out_multip%handle)
558
559 call kick_write(kick, out = out_multip%handle)
560
561 call write_iter_header_start(out_multip%handle)
562
563 do is = 1, st%d%nspin
564 write(aux,'(a18,i1,a1)') 'Electronic charge(', is,')'
565 call write_iter_header(out_multip%handle, aux)
566 if (lmax > 0) then
567 write(aux, '(a3,a1,i1,a1)') '<x>', '(', is,')'
568 call write_iter_header(out_multip%handle, aux)
569 write(aux, '(a3,a1,i1,a1)') '<y>', '(', is,')'
570 call write_iter_header(out_multip%handle, aux)
571 write(aux, '(a3,a1,i1,a1)') '<z>', '(', is,')'
572 call write_iter_header(out_multip%handle, aux)
573 end if
574 do ll = 2, lmax
575 do mm = -ll, ll
576 write(aux, '(a2,i2,a4,i2,a2,i1,a1)') 'l=', ll, ', m=', mm, ' (', is,')'
577 call write_iter_header(out_multip%handle, aux)
578 end do
579 end do
580 end do
581 call write_iter_nl(out_multip%handle)
582
583 ! units
584 call write_iter_string(out_multip%handle, '#[Iter n.]')
585 call write_iter_header(out_multip%handle, '[' // trim(units_abbrev(units_out%time)) // ']')
586
587 do is = 1, st%d%nspin
588 do ll = 0, lmax
589 do mm = -ll, ll
590 select case (ll)
591 case (0)
592 call write_iter_header(out_multip%handle, 'Electrons')
593 case (1)
594 call write_iter_header(out_multip%handle, '[' // trim(units_abbrev(units_out%length)) // ']')
595 case default
596 write(aux, '(a,a2,i1)') trim(units_abbrev(units_out%length)), "**", ll
597 call write_iter_header(out_multip%handle, '[' // trim(aux) // ']')
598 end select
599 end do
600 end do
601 end do
602 call write_iter_nl(out_multip%handle)
603
604 call local_write_print_header_end(out_multip%handle)
605 call write_iter_flush(out_multip%handle)
606 end if
607
608 center(1:ions%space%dim) = ions%center_of_mass(mask=ions_mask)
609
610 safe_allocate(multipole(1:(lmax + 1)**2, 1:st%d%nspin))
611 multipole = m_zero
612
613 do is = 1, st%d%nspin
614 call dmf_multipoles(mesh, st%rho(:,is), lmax, multipole(:,is), mask=mesh_mask)
615 end do
616 ! Setting center of mass as reference needed for non-neutral systems.
617 do is = 1, st%d%nspin
618 multipole(2:mesh%box%dim+1, is) = multipole(2:mesh%box%dim+1, is) - center(1:mesh%box%dim)*multipole(1, is)
619 end do
620
621 ! For transition densities or density differences there is no need to add the ionic dipole
622
623 !%Variable LDIonicDipole
624 !%Type logical
625 !%Default yes
626 !%Section Utilities::oct-local_multipoles
627 !%Description
628 !% Describes if the ionic dipole has to be take into account
629 !% when computing the multipoles.
630 !%End
631 call parse_variable(namespace, 'LDIonicDipole', .true., use_ionic_dipole)
632 if (use_ionic_dipole) then
633 ! Calculate ionic dipole, setting the center of mass as reference, as that is needed for non-neutral systems.
634 ionic_dipole(1:ions%space%dim) = ions%dipole(mask=ions_mask) + &
635 p_proton_charge*ions%val_charge(mask=ions_mask)*center(1:ions%space%dim)
636
637 do is = 1, st%d%nspin
638 multipole(2:ions%space%dim+1, is) = -ionic_dipole(1:ions%space%dim)/st%d%nspin - multipole(2:ions%space%dim+1, is)
639 end do
640 end if
641
642 if (mpi_grp_is_root(mpi_world)) then
643 call write_iter_set(out_multip%handle, iter)
644 call write_iter_start(out_multip%handle)
645 do is = 1, st%d%nspin
646 add_lm = 1
647 do ll = 0, lmax
648 do mm = -ll, ll
649 call write_iter_double(out_multip%handle, units_from_atomic(units_out%length**ll, multipole(add_lm, is)), 1)
650 add_lm = add_lm + 1
651 end do
652 end do
653 end do
654 call write_iter_nl(out_multip%handle)
655 end if
656
657 ! Write multipoles in BILD format
658 if (bitand(how, option__outputformat__bild) /= 0 .and. mpi_grp_is_root(mpi_world)) then
659 assert(mesh%box%dim == 3)
660 !FIXME: to include spin larger than 1.
661 is = 1
662 call out_bld_multipoles(namespace, multipole(2:4, is), center, lab, iter)
663 end if
664
665 safe_deallocate_a(multipole)
666
667 pop_sub(local_write_multipole)
668 end subroutine local_write_multipole
669
670 ! ---------------------------------------------------------
671 subroutine out_bld_multipoles(namespace, multipoles, center, label, iter)
672 type(namespace_t), intent(in) :: namespace
673 real(real64), intent(in) :: multipoles(:)
674 real(real64), intent(in) :: center(:)
675 character(15), intent(in) :: label
676 integer, intent(in) :: iter
677
678 integer :: ll, out_bld
679 character(len=80) :: filename, folder
680 real(real64) :: dipolearrow(3,2)
681
682 push_sub(out_bld_multipoles)
683
684 write(folder,'(a,a)')'local.general/multipoles/',trim(label)
685 call io_mkdir(folder, namespace)
686 write(filename,'(a,a,a,a,i7.7,a)')trim(folder),'/',trim(label),'.',iter,'.bld'
687 out_bld = io_open(trim(filename), namespace, action='write')
688
689 write(out_bld,'(a,a,a,i7)')'.comment ** Arrow for the dipole moment centered at the center of mass for ', &
690 trim(label), ' domain and iteration number: ',iter
691 write(out_bld,'(a)')''
692 write(out_bld,'(a)')'.color red'
693 write(out_bld,'(a,3(f12.6,2x),a)')'.sphere ',(units_from_atomic(units_out%length,center(ll)), ll= 1, 3),' 0.2'
694 do ll = 1, 3
695 dipolearrow(ll,1) = units_from_atomic(units_out%length, center(ll) - multipoles(ll)/m_two)
696 dipolearrow(ll,2) = units_from_atomic(units_out%length, center(ll) + multipoles(ll)/m_two)
697 end do
698 write(out_bld,'(a,6(f12.6,2x),a)')'.arrow ',(dipolearrow(ll,1), ll= 1, 3), &
699 (dipolearrow(ll,2), ll= 1, 3), ' 0.1 0.5 0.90'
700 call io_close(out_bld)
701
702 pop_sub(out_bld_multipoles)
703 end subroutine out_bld_multipoles
704
705 ! ---------------------------------------------------------
706 subroutine local_write_print_header_init(out)
707 type(c_ptr), intent(inout) :: out
708
710 call write_iter_clear(out)
711 call write_iter_string(out,'################################################################################')
712 call write_iter_nl(out)
713 call write_iter_string(out,'# HEADER')
714 call write_iter_nl(out)
715
717 end subroutine local_write_print_header_init
718
719
720 ! ---------------------------------------------------------
721 subroutine local_write_print_header_end(out)
722 type(c_ptr), intent(inout) :: out
723
725
726 call write_iter_string(out,'################################################################################')
727 call write_iter_nl(out)
728
730 end subroutine local_write_print_header_end
731
732end module local_write_oct_m
733
734!! Local Variables:
735!! mode: f90
736!! coding: utf-8
737!! End:
Sets the iteration number to the C object.
Definition: write_iter.F90:174
Writes to the corresponding file and adds one to the iteration. Must be called after write_iter_init(...
Definition: write_iter.F90:167
real(real64), parameter, public m_two
Definition: global.F90:189
real(real64), parameter, public p_proton_charge
Definition: global.F90:226
real(real64), parameter, public m_zero
Definition: global.F90:187
This module defines classes and functions for interaction partners.
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_close(iunit, grp)
Definition: io.F90:468
character(len=max_path_len) function, public io_workpath(path, namespace)
Definition: io.F90:313
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:354
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:395
subroutine, public kick_write(kick, iunit, out)
Definition: kick.F90:891
integer, parameter local_out_potential
subroutine local_write_print_header_init(out)
subroutine, public local_write_init(writ, namespace, lab, iter, dt)
subroutine, public local_write_end(writ)
integer, parameter local_out_energy
logical function, public local_write_check_hm(writ)
subroutine local_write_print_header_end(out)
integer, parameter local_out_density
integer, parameter local_out_max
subroutine local_write_density(out_dens, namespace, space, out_pot, lab, mesh_mask, mesh, ions, ext_partners, st, hm, ks, iter, how)
subroutine out_bld_multipoles(namespace, multipoles, center, label, iter)
subroutine local_write_multipole(out_multip, namespace, lab, ions_mask, mesh_mask, mesh, ions, st, lmax, kick, iter, l_start, start, how)
subroutine local_write_energy(out_energy, namespace, space, lab, mesh_mask, mesh, ions, ext_partners, st, hm, ks, iter, l_start, start)
subroutine, public local_write_iter(writ, namespace, space, lab, ions_mask, mesh_mask, mesh, st, hm, ks, ions, ext_partners, kick, iter, l_start, ldoverwrite)
This module defines various routines, operating on mesh functions.
subroutine, public dmf_multipoles(mesh, ff, lmax, multipole, mask)
This routine calculates the multipoles of a function ff.
real(real64) function, public dmf_integrate(mesh, ff, mask, reduce)
Integrate a function on the mesh.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1057
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:420
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:723
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
Definition: mpi.F90:430
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:266
subroutine, public dpoisson_solve(this, namespace, pot, rho, all_nodes, kernel)
Calculates the Poisson equation. Given the density returns the corresponding potential.
Definition: poisson.F90:892
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:623
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:552
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 v_ks_calc(ks, namespace, space, hm, st, ions, ext_partners, calc_eigenval, time, calc_energy, calc_current, force_semilocal)
Definition: v_ks.F90:732
Explicit interfaces to C functions, defined in write_iter_low.cc.
Definition: write_iter.F90:114
Extension of space that contains the knowledge of the spin dimension.
Describes mesh distribution to nodes.
Definition: mesh.F90:186
The states_elec_t class contains all electronic wave functions.
int true(void)