Octopus
output_mxll.F90
Go to the documentation of this file.
1!! Copyright (C) 2019 F. Bonafe, R. Jestaedt, H. Appel
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
19
20#include "global.h"
21
23 use debug_oct_m
28 use global_oct_m
29 use grid_oct_m
31 use io_oct_m
33 use mesh_oct_m
36 use output_oct_m
38 use parser_oct_m
40 use space_oct_m
43 use string_oct_m
44 use unit_oct_m
46
47
48 implicit none
49
50 private
51 public :: &
54
55contains
56
57 ! ---------------------------------------------------------
58 subroutine output_mxll_init(outp, namespace, space)
59 type(output_t), intent(out) :: outp
60 type(namespace_t), intent(in) :: namespace
61 class(space_t), intent(in) :: space
62 integer :: what_i
63 push_sub(output_mxll_init)
64
65 !%Variable MaxwellOutput
66 !%Type block
67 !%Default none
68 !%Section Output
69 !%Description
70 !% Specifies what to print. The output files are written at the end of the run into the output directory for the
71 !% Maxwell run.
72 !% Time-dependent simulations print only per iteration, including always the last. The frequency of output per iteration
73 !% is set by <tt>OutputInterval</tt> and the directory is set by <tt>OutputIterDir</tt>.
74 !% Each option must be in a separate row. Optionally individual output formats and output intervals can be defined
75 !% for each row or they can be read separately from <tt>OutputFormat</tt> and <tt>MaxwellOutputInterval</tt> variables
76 !% in the input file.
77 !%
78 !% Example:
79 !% <br><br><tt>%MaxwellOutput
80 !% <br>&nbsp;&nbsp;electric_field
81 !% <br>&nbsp;&nbsp;magnetic_field
82 !% <br>%<br></tt>
83 !% This block supports all the formats of the <tt>Output</tt> block.
84 !% See <tt>Output</tt>.
85 !%Option electric_field 1
86 !% Output of the electric field
87 !%Option magnetic_field 2
88 !% Output of the magnetic field
89 !%Option trans_electric_field 3
90 !% Output of the transversal electric field
91 !%Option trans_magnetic_field 4
92 !% Output of the transversal magnetic field
93 !%Option long_electric_field 5
94 !% Output of the longitudinal electric field
95 !%Option long_magnetic_field 6
96 !% Output of the longitudinal magnetic field
97 !%Option div_electric_field 7
98 !% Output of the divergence of the electric field
99 !%Option div_magnetic_field 8
100 !% Output of the divergence of the magnetic field
101 !%Option poynting_vector 9
102 !% Output of the Maxwell Poynting vector
103 !%Option maxwell_energy_density 10
104 !% Output of the electromagnetic density
105 !%Option external_current 11
106 !% Output of the external Maxwell current
107 !%Option charge_density 12
108 !% Output of the charge density calculated by the divergence of the electric field.
109 !%Option orbital_angular_momentum 13
110 !% Output of the orbital angular momentum
111 !%Option vector_potential_mag 14
112 !% Output of the vector potential from magnetic field
113 !%Option magnetic_field_diff 15
114 !% Output of the magnetic field difference
115 !%Option total_current_mxll 16
116 !% Output of the total current density
117 !%End
118
119 !%Variable MaxwellOutputInterval
120 !%Type integer
121 !%Default 50
122 !%Section Output
123 !%Description
124 !% The output requested by variable <tt>MaxwellOutput</tt> is written
125 !% to the directory <tt>MaxwellOutputIterDir</tt>
126 !% when the iteration number is a multiple of the <tt>MaxwellOutputInterval</tt> variable.
127 !% Subdirectories are named Y.X, where Y is <tt>td</tt>, <tt>scf</tt>, or <tt>unocc</tt>, and
128 !% X is the iteration number. To use the working directory, specify <tt>"."</tt>
129 !% (Output of restart files is instead controlled by <tt>MaxwellRestartWriteInterval</tt>.)
130 !% Must be >= 0. If it is 0, then no output is written.
131 !% This variable can also be defined inside the <tt>MaxwellOutput</tt> block.
132 !% See <tt>MaxwellOutput</tt>.
133 !%End
134
135 outp%what = .false.
136 call io_function_read_what_how_when(namespace, space, outp%what, outp%how, outp%output_interval, &
137 'MaxwellOutput', 'OutputFormat', 'MaxwellOutputInterval')
138
139 do what_i = lbound(outp%what, 1), ubound(outp%what, 1)
140 ! xyz format is not available for Maxwell
141 if (bitand(outp%how(what_i), option__outputformat__xyz) /= 0) then
142 message(1) = "OutputFormat = xyz is not compatible with Maxwell systems"
143 call messages_warning(1)
144 end if
145 end do
146
147
148
149 !%Variable MaxwellOutputIterDir
150 !%Default "output_iter"
151 !%Type string
152 !%Section Output
153 !%Description
154 !% The name of the directory where <tt>Octopus</tt> stores information
155 !% such as the density, forces, etc. requested by variable <tt>MaxwellOutput</tt>
156 !% in the format specified by <tt>OutputHow</tt>.
157 !% This information is written while iterating <tt>CalculationMode = maxwell</tt>
158 !% according to <tt>OutputInterval</tt>, and has nothing to do with the restart information.
159 !%End
160 call parse_variable(namespace, 'MaxwellOutputIterDir', "output_iter", outp%iter_dir)
161 if (any(outp%what) .and. maxval(outp%output_interval) > 0) then
162 call io_mkdir(outp%iter_dir, namespace)
163 end if
164 call add_last_slash(outp%iter_dir)
165
166 !%Variable MaxwellRestartWriteInterval
167 !%Type integer
168 !%Default 50
169 !%Section Execution::IO
170 !%Description
171 !% Restart data is written when the iteration number is a multiple of the
172 !% <tt>MaxwellRestartWriteInterval</tt> variable. (Other output is controlled by <tt>MaxwellOutputInterval</tt>.)
173 !%End
174 call parse_variable(namespace, 'MaxwellRestartWriteInterval', 50, outp%restart_write_interval)
175 if (outp%restart_write_interval <= 0) then
176 message(1) = "MaxwellRestartWriteInterval must be > 0."
177 call messages_fatal(1, namespace=namespace)
178 end if
179
180 if (outp%what(option__maxwelloutput__electric_field)) then
181 outp%wfs_list = trim("1-3")
182 end if
183
184 if (outp%what(option__maxwelloutput__magnetic_field)) then
185 outp%wfs_list = trim("1-3")
186 end if
187
188 if (outp%what(option__maxwelloutput__trans_electric_field)) then
189 outp%wfs_list = trim("1-3")
190 end if
191
192 if (outp%what(option__maxwelloutput__trans_magnetic_field)) then
193 outp%wfs_list = trim("1-3")
194 end if
195
196
197 pop_sub(output_mxll_init)
198 end subroutine output_mxll_init
199
200
201 ! ---------------------------------------------------------
202 subroutine output_mxll(outp, namespace, space, gr_mxll, st_mxll, hm_mxll, helmholtz, time, dir, gr_elec, st_elec, hm_elec)
203 type(output_t), intent(in) :: outp
204 type(namespace_t), intent(in) :: namespace
205 class(space_t), intent(in) :: space
206 type(states_mxll_t), intent(inout) :: st_mxll
207 type(hamiltonian_mxll_t), intent(in) :: hm_mxll
208 type(grid_t), intent(in) :: gr_mxll
209 type(helmholtz_decomposition_t), intent(inout) :: helmholtz
210 real(real64), intent(in) :: time
211 character(len=*), intent(in) :: dir
212 type(grid_t), optional, intent(inout) :: gr_elec
213 type(states_elec_t), optional, intent(inout) :: st_elec
214 type(hamiltonian_elec_t), optional, intent(in) :: hm_elec
215
216 push_sub(output_mxll)
217
218 if (any(outp%what)) then
219 message(1) = "Info: Writing output to " // trim(dir)
220 call messages_info(1, namespace=namespace)
221 call io_mkdir(dir, namespace)
222 end if
223
224 call output_states_mxll(outp, namespace, space, dir, st_mxll, gr_mxll)
225 call output_energy_density_mxll(outp, namespace, space, dir, st_mxll, gr_mxll)
226 call output_poynting_vector_orbital_angular_momentum(outp, namespace, space, dir, st_mxll, gr_mxll)
227 call output_transverse_rs_state(helmholtz, outp, namespace, space, dir, st_mxll, gr_mxll)
228 call output_longitudinal_rs_state(helmholtz, outp, namespace, space, dir, st_mxll, gr_mxll)
229 call output_vector_potential_mag(outp, helmholtz, namespace, gr_mxll, space, dir, st_mxll)
230 call output_divergence_rs_state(outp, namespace, space, dir, st_mxll, gr_mxll)
231 call output_external_current_density(outp, namespace, space, dir, st_mxll, gr_mxll, hm_mxll, time)
232 call output_total_current_mxll(outp, namespace, space, dir, st_mxll, gr_mxll, hm_mxll, time, st_mxll%ep, gr_mxll%np)
233 call output_charge_density_mxll(outp, namespace, space, dir, st_mxll, gr_mxll, hm_mxll)
234
235 if (present(hm_elec) .and. present(gr_elec) .and. present(st_elec)) then
236 call output_coupling_potentials(outp, namespace, dir, hm_elec, gr_elec)
237 call output_current_density(outp, namespace, dir, st_mxll, gr_mxll, hm_mxll, st_elec, gr_elec, hm_elec, time)
238 end if
239
240 pop_sub(output_mxll)
241 end subroutine output_mxll
242
243
244 ! ---------------------------------------------------------
245 subroutine output_states_mxll(outp, namespace, space, dir, st, mesh)
246 type(output_t), intent(in) :: outp
247 type(namespace_t), intent(in) :: namespace
248 class(space_t), intent(in) :: space
249 character(len=*), intent(in) :: dir
250 type(states_mxll_t), intent(in) :: st
251 class(mesh_t), intent(in) :: mesh
252
253 integer :: ierr
254 character(len=MAX_PATH_LEN) :: fname
255 type(unit_t) :: fn_unit
256 real(real64), allocatable :: dtmp(:,:)
257
258 push_sub(output_states_mxll)
259
260 ! Electric field
261 if (outp%what(option__maxwelloutput__electric_field)) then
262 fn_unit = units_out%energy/units_out%length
263 safe_allocate(dtmp(1:mesh%np, 1:space%dim))
264 call get_electric_field_state(st%rs_state, mesh, dtmp, st%ep, mesh%np)
265 fname = 'e_field'
266 call io_function_output_vector(outp%how(option__maxwelloutput__electric_field), dir, fname, namespace, space, &
267 mesh, dtmp, fn_unit, ierr)
268 safe_deallocate_a(dtmp)
269 end if
270
271 ! Magnetic field
272 if (outp%what(option__maxwelloutput__magnetic_field)) then
273 fn_unit = unit_one/units_out%length**2
274 safe_allocate(dtmp(1:mesh%np, 1:space%dim))
275 call get_magnetic_field_state(st%rs_state, mesh, st%rs_sign, dtmp, st%mu(1:mesh%np), mesh%np)
276 fname = 'b_field'
277 call io_function_output_vector(outp%how(option__maxwelloutput__magnetic_field), dir, fname, namespace, space, &
278 mesh, dtmp, fn_unit, ierr)
279 safe_deallocate_a(dtmp)
280 end if
281
282 pop_sub(output_states_mxll)
283 end subroutine output_states_mxll
284
285
286 !----------------------------------------------------------
287 subroutine output_energy_density_mxll(outp, namespace, space, dir, st, mesh) !< have to set unit output correctly
288 type(output_t), intent(in) :: outp
289 type(namespace_t), intent(in) :: namespace
290 class(space_t), intent(in) :: space
291 character(len=*), intent(in) :: dir
292 type(states_mxll_t), intent(in) :: st
293 class(mesh_t), intent(in) :: mesh
294
295 integer :: ierr
296 real(real64), allocatable :: energy_density(:), e_energy_density(:), b_energy_density(:)
297
299
300 ! Maxwell energy density
301 if (outp%what(option__maxwelloutput__maxwell_energy_density)) then
302 safe_allocate(energy_density(1:mesh%np))
303 safe_allocate(e_energy_density(1:mesh%np))
304 safe_allocate(b_energy_density(1:mesh%np))
305 ! calculate the energy density
306 call energy_density_calc(mesh, st, st%rs_state, energy_density, e_energy_density, b_energy_density)
307
308 call dio_function_output(outp%how(option__maxwelloutput__maxwell_energy_density), dir, "maxwell_energy_density", &
309 namespace, space, mesh, energy_density, units_out%energy/units_out%length**3, ierr)
310
311 safe_deallocate_a(energy_density)
312 safe_deallocate_a(e_energy_density)
313 safe_deallocate_a(b_energy_density)
314 end if
315
317 end subroutine output_energy_density_mxll
318
319
320 !----------------------------------------------------------
321 subroutine output_poynting_vector_orbital_angular_momentum(outp, namespace, space, dir, st, mesh)
322 type(output_t), intent(in) :: outp
323 type(namespace_t), intent(in) :: namespace
324 class(space_t), intent(in) :: space
325 character(len=*), intent(in) :: dir
326 type(states_mxll_t), intent(in) :: st
327 class(mesh_t), intent(in) :: mesh
328
329 integer :: ierr
330 character(len=MAX_PATH_LEN) :: fname
331 type(unit_t) :: fn_unit
332 real(real64), allocatable :: poynting_vector(:,:), oam(:,:)
333
335
336 if (outp%what(option__maxwelloutput__poynting_vector).or.outp%what(option__maxwelloutput__orbital_angular_momentum)) then
337
338 ! the Poynting vector is needed in both cases, so we compute it here first
339 fn_unit = units_out%energy/(units_out%time*units_out%length**2)
340 safe_allocate(poynting_vector(1:mesh%np, 1:space%dim))
341 call get_poynting_vector(mesh, st, st%rs_state, st%rs_sign, poynting_vector, st%ep, st%mu)
342
343 if(outp%what(option__maxwelloutput__poynting_vector)) then
344 fname = 'poynting_vector'
345 call io_function_output_vector(outp%how(option__maxwelloutput__poynting_vector), dir, fname, namespace, space, &
346 mesh, poynting_vector, fn_unit, ierr)
347 end if
348
349 if(outp%what(option__maxwelloutput__orbital_angular_momentum)) then
350 safe_allocate(oam(1:mesh%np, 1:space%dim))
351 call get_orbital_angular_momentum(mesh, st, poynting_vector, oam)
352 fname = 'orbital_angular_momentum'
353 call io_function_output_vector(outp%how(option__maxwelloutput__orbital_angular_momentum), dir, fname, namespace, space, &
354 mesh, oam, fn_unit, ierr)
355 safe_deallocate_a(oam)
356 end if
357
358 safe_deallocate_a(poynting_vector)
359 end if
360
363
364
365 ! add documentation to magnetic field subtraction order
366 subroutine output_vector_potential_mag(outp, helmholtz, namespace, gr, space, dir, st) !< have to set unit output correctly
367 type(output_t), intent(in) :: outp
368 type(helmholtz_decomposition_t), intent(inout) :: helmholtz
369 type(namespace_t), intent(in) :: namespace
370 type(grid_t), intent(in) :: gr
371 class(space_t), intent(in) :: space
372 character(len=*), intent(in) :: dir
373 type(states_mxll_t), intent(in) :: st
374
375 character(len=MAX_PATH_LEN) :: fname
376 integer :: ierr
377 type(unit_t) :: fn_unit
378 real(real64), allocatable :: dtmp(:,:),vtmp(:,:), mag_fromvec(:,:) , delta(:,:)
379
381
382 ! vector potential from magnetic field
383 if (outp%what(option__maxwelloutput__vector_potential_mag) .or. &
384 outp%what(option__maxwelloutput__magnetic_field_diff)) then
385
386 fn_unit = unit_one/units_out%length
387 safe_allocate(dtmp(1:gr%np_part, 1:space%dim))
388 safe_allocate(vtmp(1:gr%np_part, 1:space%dim))
389 call get_magnetic_field_state(st%rs_state, gr, st%rs_sign, dtmp, st%mu(1:gr%np), gr%np)
390 ! Get vector potential for magnetic field
391 call helmholtz%get_vector_potential(namespace, vtmp, trans_field=dtmp)
392
393 if (outp%what(option__maxwelloutput__vector_potential_mag)) then
394 message(1) = 'Vector potential is currently missing surface contributions'
395 message(2) = 'If in doubt, use magnetic_field_diff output which shows deviation of B field'
396 message(3) = 'Large B field deviations mean the calculated vector potential is unreliable'
397 call messages_warning(3)
398
399 fname = 'vector_potential_mag'
400 call io_function_output_vector(outp%how(option__maxwelloutput__vector_potential_mag), dir, fname, namespace, &
401 space, gr, vtmp, fn_unit, ierr)
402 end if
403
404 if (outp%what(option__maxwelloutput__magnetic_field_diff)) then
405 fn_unit = unit_one/units_out%length**2
406 safe_allocate(mag_fromvec(1:gr%np_part, 1:space%dim))
407 safe_allocate(delta(1:gr%np, 1:space%dim))
408 ! Get transverse field from vector potential
409 call helmholtz%get_trans_field(namespace, mag_fromvec, vector_potential=vtmp)
410 ! mag_fromvec is of size np_part, but should be used up to np
411 ! Due to how the Helmholtz decomposition works (see its documentation), we have to remove a stencil from dtmp
412 call helmholtz%apply_inner_stencil_mask(dtmp)
413 delta = dtmp(1:gr%np, 1:space%dim) - mag_fromvec(1:gr%np, 1:space%dim)
414 fname = 'magnetic_field_diff'
415 call io_function_output_vector(outp%how(option__maxwelloutput__magnetic_field_diff), dir, fname, namespace, &
416 space, gr, delta, fn_unit, ierr)
417 safe_deallocate_a(mag_fromvec)
418 safe_deallocate_a(delta)
419 end if
420
421 safe_deallocate_a(dtmp)
422 safe_deallocate_a(vtmp)
423 end if
424
426 end subroutine output_vector_potential_mag
427
428
429 !----------------------------------------------------------
430 subroutine output_transverse_rs_state(helmholtz, outp, namespace, space, dir, st, gr) !< have to set unit output correctly
431 type(helmholtz_decomposition_t), intent(inout) :: helmholtz
432 type(output_t), intent(in) :: outp
433 type(namespace_t), intent(in) :: namespace
434 class(space_t), intent(in) :: space
435 character(len=*), intent(in) :: dir
436 type(states_mxll_t), intent(inout) :: st ! needs to be inout as st%rs_state is passed to get_trans_field
437 type(grid_t), intent(in) :: gr
438
439 character(len=MAX_PATH_LEN) :: fname
440 integer :: ierr
441 type(unit_t) :: fn_unit
442 real(real64), allocatable :: dtmp(:,:)
443
445
446 if (outp%what(option__maxwelloutput__trans_electric_field) .or. outp%what(option__maxwelloutput__trans_magnetic_field)) then
447 call helmholtz%get_trans_field(namespace, st%rs_state_trans, total_field=st%rs_state)
448 end if
449
450 ! transverse component of the electric field
451 if (outp%what(option__maxwelloutput__trans_electric_field)) then
452 fn_unit = units_out%energy/units_out%length
453 safe_allocate(dtmp(1:gr%np, 1:space%dim))
454 call get_electric_field_state(st%rs_state_trans, gr, dtmp, st%ep(1:gr%np), gr%np)
455 fname = 'e_field_trans'
456 call io_function_output_vector(outp%how(option__maxwelloutput__trans_electric_field), dir, fname, namespace, space, &
457 gr, dtmp, fn_unit, ierr)
458 safe_deallocate_a(dtmp)
459 end if
460
461 ! transverse component of the magnetic field
462 if (outp%what(option__maxwelloutput__trans_magnetic_field)) then
463 fn_unit = unit_one/units_out%length**2
464 safe_allocate(dtmp(1:gr%np, 1:space%dim))
465 call get_magnetic_field_state(st%rs_state_trans, gr, st%rs_sign, dtmp, st%mu(1:gr%np), gr%np)
466 fname = 'b_field_trans'
467 call io_function_output_vector(outp%how(option__maxwelloutput__trans_magnetic_field), dir, fname, namespace, space, &
468 gr, dtmp, fn_unit, ierr)
469 safe_deallocate_a(dtmp)
470 end if
471
473 end subroutine output_transverse_rs_state
474
475
476 !----------------------------------------------------------
477 !This subroutine is left here, will be corrected and called in near future
478 subroutine output_longitudinal_rs_state(helmholtz, outp, namespace, space, dir, st, gr) !< have to set unit output correctly
479 type(helmholtz_decomposition_t), intent(inout) :: helmholtz
480 type(output_t), intent(in) :: outp
481 type(namespace_t), intent(in) :: namespace
482 class(space_t), intent(in) :: space
483 character(len=*), intent(in) :: dir
484 type(states_mxll_t), intent(inout) :: st ! needs to be inout as st%rs_state is passed to get_long_field
485 type(grid_t), intent(in) :: gr
486
487 character(len=MAX_PATH_LEN) :: fname
488 integer :: ierr
489 type(unit_t) :: fn_unit
490 real(real64), allocatable :: dtmp(:,:)
491
493
494 if (outp%what(option__maxwelloutput__long_electric_field) .or. outp%what(option__maxwelloutput__long_magnetic_field)) then
495 call helmholtz%get_long_field(namespace, st%rs_state_long, total_field=st%rs_state)
496 end if
497
498 ! longitudinal component of the electric field
499 if (outp%what(option__maxwelloutput__long_electric_field)) then
500 fn_unit = units_out%energy/units_out%length
501 safe_allocate(dtmp(1:gr%np, 1:space%dim))
502 call get_electric_field_state(st%rs_state_long, gr, dtmp, st%ep(1:gr%np), gr%np)
503 fname = 'e_field_long'
504 call io_function_output_vector(outp%how(option__maxwelloutput__long_electric_field), dir, fname, namespace, space, &
505 gr, dtmp, fn_unit, ierr)
506 safe_deallocate_a(dtmp)
507 end if
508
509 ! longitudinal component of the magnetic field
510 if (outp%what(option__maxwelloutput__long_magnetic_field)) then
511 fn_unit = unit_one/units_out%length**2
512 safe_allocate(dtmp(1:gr%np, 1:space%dim))
513 call get_magnetic_field_state(st%rs_state_long, gr, st%rs_sign, dtmp, st%mu(1:gr%np), gr%np)
514 fname = 'b_field_long'
515 call io_function_output_vector(outp%how(option__maxwelloutput__long_magnetic_field), dir, fname, namespace, space, &
516 gr, dtmp, fn_unit, ierr)
517 safe_deallocate_a(dtmp)
518 end if
519
521 end subroutine output_longitudinal_rs_state
522
524 !----------------------------------------------------------
525 subroutine output_divergence_rs_state(outp, namespace, space, dir, st, gr) !< have to set unit output correctly
526 type(output_t), intent(in) :: outp
527 type(namespace_t), intent(in) :: namespace
528 class(space_t), intent(in) :: space
529 character(len=*), intent(in) :: dir
530 type(states_mxll_t), intent(in) :: st
531 type(grid_t), intent(in) :: gr
532
533 integer :: ierr
534 type(unit_t) :: fn_unit
535 real(real64), allocatable :: dtmp_1(:,:), dtmp_2(:)
536
538
539 ! divergence of the electric field
540 if (outp%what(option__maxwelloutput__div_electric_field)) then
541 fn_unit = units_out%length**(-space%dim)
542 safe_allocate(dtmp_1(1:gr%np_part, 1:space%dim))
543 safe_allocate(dtmp_2(1:gr%np))
544 dtmp_1 = m_zero
545 call get_electric_field_state(st%rs_state, gr, dtmp_1(1:gr%np,:), st%ep(1:gr%np), gr%np)
546 call get_divergence_field(gr, dtmp_1, dtmp_2, .false.)
547 call dio_function_output(outp%how(option__maxwelloutput__div_electric_field), dir, "e_field_div", namespace, space, &
548 gr, dtmp_2, fn_unit, ierr)
549 safe_deallocate_a(dtmp_1)
550 safe_deallocate_a(dtmp_2)
551 end if
552
553 ! divergence of the magnetic field
554 if (outp%what(option__maxwelloutput__div_magnetic_field)) then
555 ! unit does not matter, should be zero
556 fn_unit = unit_one
557 safe_allocate(dtmp_1(1:gr%np_part, 1:space%dim))
558 safe_allocate(dtmp_2(1:gr%np))
559 dtmp_1 = m_zero
560 call get_magnetic_field_state(st%rs_state, gr, st%rs_sign, dtmp_1(1:gr%np,:), st%mu(1:gr%np), gr%np)
561 call get_divergence_field(gr, dtmp_1, dtmp_2, .false.)
562 call dio_function_output(outp%how(option__maxwelloutput__div_magnetic_field), dir, "b_field_div", namespace, space, &
563 gr, dtmp_2, fn_unit, ierr)
564 safe_deallocate_a(dtmp_1)
565 safe_deallocate_a(dtmp_2)
566 end if
567
569 end subroutine output_divergence_rs_state
570
572 !------------------------------------------------------------
573 subroutine output_coupling_potentials(outp, namespace, dir, hm, gr) !< have to set unit output correctly
574 type(output_t), intent(in) :: outp
575 type(namespace_t), intent(in) :: namespace
576 character(len=*), intent(in) :: dir
577 type(hamiltonian_elec_t), intent(in) :: hm
578 type(grid_t), intent(in) :: gr
579
580 message(1) = "Maxwell-matter coupling potentials not implemented yet."
581 call messages_fatal(1, namespace=namespace)
582
583 end subroutine output_coupling_potentials
584
585
586 !----------------------------------------------------------
587 subroutine output_current_density(outp, namespace, dir, st_mxll, gr_mxll, hm_mxll, st_elec, gr_elec, hm_elec, time)
588 type(output_t), intent(in) :: outp
589 type(namespace_t), intent(in) :: namespace
590 character(len=*), intent(in) :: dir
591 type(states_mxll_t), intent(in) :: st_mxll
592 type(grid_t), intent(in) :: gr_mxll
593 type(hamiltonian_mxll_t), intent(in) :: hm_mxll
594 type(states_elec_t), intent(in) :: st_elec
595 type(grid_t), intent(in) :: gr_elec
596 type(hamiltonian_elec_t), intent(in) :: hm_elec
597 real(real64), intent(in) :: time
598
599 message(1) = "Current density can not yet be calculated in a Maxwell propagation."
600 call messages_fatal(1, namespace=namespace)
601
602 end subroutine output_current_density
603
604
605 !----------------------------------------------------------
606 subroutine output_external_current_density(outp, namespace, space, dir, st, mesh, hm, time)
607 type(output_t), intent(in) :: outp
608 type(namespace_t), intent(in) :: namespace
609 class(space_t), intent(in) :: space
610 character(len=*), intent(in) :: dir
611 type(states_mxll_t), intent(in) :: st
612 class(mesh_t), intent(in) :: mesh
613 type(hamiltonian_mxll_t), intent(in) :: hm
614 real(real64), intent(in) :: time
615
616 character(len=MAX_PATH_LEN) :: fname
617 integer :: ierr
618 real(real64), allocatable :: dtmp(:,:)
619 type(unit_t) :: fn_unit
620
622
623 ! Maxwell current density
624 if (outp%what(option__maxwelloutput__external_current)) then
625 if (hm%current_density_ext_flag) then
626 fn_unit = (unit_one/units_out%time)/(units_out%length**2)
627 safe_allocate(dtmp(1:mesh%np, 1:space%dim))
628 call external_current_calculation(st, space, mesh, time, dtmp)
629 fname = 'external_current'
630 call io_function_output_vector(outp%how(option__maxwelloutput__external_current), dir, fname, namespace, space, &
631 mesh, dtmp, fn_unit, ierr)
632 safe_deallocate_a(dtmp)
633 end if
634 end if
635
638
639 subroutine output_total_current_mxll(outp, namespace, space, dir, st, mesh, hm, time, ep_field, np)
640 type(output_t), intent(in) :: outp
641 type(namespace_t), intent(in) :: namespace
642 class(space_t), intent(in) :: space
643 character(len=*), intent(in) :: dir
644 type(states_mxll_t), intent(in) :: st
645 class(mesh_t), intent(in) :: mesh
646 type(hamiltonian_mxll_t), intent(in) :: hm
647 real(real64), intent(in) :: time
648 real(real64), optional, intent(in) :: ep_field(:)
649 integer, optional, intent(in) :: np
650
651 real(real64), allocatable :: ctmp(:,:)
652 character(len=MAX_PATH_LEN) :: fname
653 integer :: ierr, ip, idim, np_, ff_dim
654 type(unit_t) :: fn_unit
655
657 safe_allocate(ctmp(1:mesh%np, 1:space%dim))
658 if (outp%what(option__maxwelloutput__total_current_mxll)) then
659 np_ = optional_default(np, mesh%np)
660 ff_dim = space%dim
661 if (present(ep_field)) then
662 do idim = 1, ff_dim
663 do ip = 1, np_
664 ctmp(ip, idim) = sqrt(m_two*ep_field(ip)) * real(st%rs_current_density_t1(ip, idim))
665 end do
666 end do
667 else
668 do idim = 1, ff_dim
669 do ip = 1, np_
670 ctmp(ip, idim) = sqrt(m_two*p_ep) * real(st%rs_current_density_t1(ip, idim))
671 end do
672 end do
673 end if
674
675 fn_unit = (unit_one/units_out%time)/(units_out%length**2)
676 fname = 'total_current_mxll'
677 call io_function_output_vector(outp%how(option__maxwelloutput__total_current_mxll), dir, fname, namespace, space, &
678 mesh, ctmp, fn_unit, ierr)
679 end if
680 safe_deallocate_a(ctmp)
682 end subroutine output_total_current_mxll
683
684
685 !----------------------------------------------------------
686 subroutine output_charge_density_mxll(outp, namespace, space, dir, st, gr, hm) !< have to set unit output correctly
687 type(output_t), intent(in) :: outp
688 type(namespace_t), intent(in) :: namespace
689 class(space_t), intent(in) :: space
690 character(len=*), intent(in) :: dir
691 type(states_mxll_t), intent(in) :: st
692 type(grid_t), intent(in) :: gr
693 type(hamiltonian_mxll_t), intent(in) :: hm
694
695 integer :: ierr
696 type(unit_t) :: fn_unit
697 real(real64), allocatable :: dtmp_1(:,:), dtmp_2(:)
698
700
701 ! charge density calculated by the divergence of the electric field
702 if (outp%what(option__maxwelloutput__charge_density)) then
703 fn_unit = units_out%length**(-space%dim)
704 safe_allocate(dtmp_1(1:gr%np_part,1:space%dim))
705 safe_allocate(dtmp_2(1:gr%np))
706 call get_electric_field_state(st%rs_state, gr, dtmp_1, st%ep, gr%np)
707 call get_divergence_field(gr, dtmp_1, dtmp_2, .true.)
708 call dio_function_output(outp%how(option__maxwelloutput__charge_density), dir, "charge_density", namespace, space, &
709 gr, dtmp_2(:), fn_unit, ierr)
710 safe_deallocate_a(dtmp_1)
711 safe_deallocate_a(dtmp_2)
712 end if
713
715 end subroutine output_charge_density_mxll
716
717end module output_mxll_oct_m
718
719!! Local Variables:
720!! mode: f90
721!! coding: utf-8
722!! End:
subroutine, public energy_density_calc(mesh, st, rs_field, energy_dens, e_energy_dens, b_energy_dens, plane_waves_check, rs_field_plane_waves, energy_dens_plane_waves)
subroutine, public external_current_calculation(st, space, mesh, time, current)
real(real64), parameter, public m_two
Definition: global.F90:189
real(real64), parameter, public m_zero
Definition: global.F90:187
real(real64), parameter, public p_ep
Definition: global.F90:227
This module implements the underlying real-space grid.
Definition: grid.F90:117
The Helmholtz decomposition is intended to contain "only mathematical" functions and procedures to co...
subroutine, public io_function_read_what_how_when(namespace, space, what, how, output_interval, what_tag_in, how_tag_in, output_interval_tag_in, ignore_error)
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_mkdir(fname, namespace, parents)
Definition: io.F90:354
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:543
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
Definition: messages.F90:624
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
this module contains the output system
Definition: output_low.F90:115
subroutine output_total_current_mxll(outp, namespace, space, dir, st, mesh, hm, time, ep_field, np)
subroutine output_states_mxll(outp, namespace, space, dir, st, mesh)
subroutine output_current_density(outp, namespace, dir, st_mxll, gr_mxll, hm_mxll, st_elec, gr_elec, hm_elec, time)
subroutine output_poynting_vector_orbital_angular_momentum(outp, namespace, space, dir, st, mesh)
subroutine output_external_current_density(outp, namespace, space, dir, st, mesh, hm, time)
subroutine, public output_mxll_init(outp, namespace, space)
subroutine output_coupling_potentials(outp, namespace, dir, hm, gr)
subroutine output_transverse_rs_state(helmholtz, outp, namespace, space, dir, st, gr)
subroutine output_energy_density_mxll(outp, namespace, space, dir, st, mesh)
subroutine output_longitudinal_rs_state(helmholtz, outp, namespace, space, dir, st, gr)
subroutine, public output_mxll(outp, namespace, space, gr_mxll, st_mxll, hm_mxll, helmholtz, time, dir, gr_elec, st_elec, hm_elec)
subroutine output_vector_potential_mag(outp, helmholtz, namespace, gr, space, dir, st)
subroutine output_divergence_rs_state(outp, namespace, space, dir, st, gr)
subroutine output_charge_density_mxll(outp, namespace, space, dir, st, gr, hm)
this module contains the output system
Definition: output.F90:115
subroutine, public get_electric_field_state(rs_state, mesh, electric_field, ep_field, np)
subroutine, public get_poynting_vector(mesh, st, rs_state, rs_sign, poynting_vector, ep_field, mu_field)
subroutine, public get_divergence_field(gr, field, field_div, charge_density)
subroutine, public get_magnetic_field_state(rs_state, mesh, rs_sign, magnetic_field, mu_field, np)
subroutine, public get_orbital_angular_momentum(mesh, st, poynting_vector, orbital_angular_momentum)
subroutine, public add_last_slash(str)
Adds a '/' in the end of the string, only if it missing. Useful for directories.
Definition: string.F90:161
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
type(unit_t), public unit_one
some special units required for particular quantities
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:168
Describes mesh distribution to nodes.
Definition: mesh.F90:186
output handler class
Definition: output_low.F90:163
The states_elec_t class contains all electronic wave functions.
int true(void)