Octopus
external_densities.F90
Go to the documentation of this file.
1!! Copyright (C) 2019 R. Jestaedt, H. Appel
2!! Copyright (C) 2020 N. Tancogne-Dejean
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 debug_oct_m
24 use global_oct_m
26 use math_oct_m
29 use mesh_oct_m
31 use mpi_oct_m
33 use parser_oct_m
35 use space_oct_m
36 use string_oct_m
38 use types_oct_m
39 use unit_oct_m
43 use xc_oct_m
44
45 implicit none
46
47 private
48
49 public :: &
53
54 integer, parameter, public :: &
55 EXTERNAL_CURRENT_PARSER = 0, &
57
58contains
59
60 !----------------------------------------------------------
61 subroutine get_rs_density_ext(st, space, mesh, time, rs_current_density_ext)
62 type(states_mxll_t), intent(inout) :: st
63 class(space_t), intent(in) :: space
64 class(mesh_t), intent(in) :: mesh
65 real(real64), intent(in) :: time
66 complex(real64), optional, intent(inout) :: rs_current_density_ext(:,:)
67
68 real(real64), allocatable :: current(:,:,:)
69
70 push_sub(get_rs_density_ext)
71
72 safe_allocate(current(1:mesh%np, 1:space%dim, 1))
73
74 call external_current_calculation(st, space, mesh, time, current(:, :, 1))
75 call build_rs_current_state(current(:, :, 1), mesh, rs_current_density_ext, st%ep, mesh%np)
76
77 safe_deallocate_a(current)
78
79 pop_sub(get_rs_density_ext)
80 end subroutine get_rs_density_ext
81
82
83 !----------------------------------------------------------
84 subroutine external_current_init(st, space, namespace, mesh)
85 type(states_mxll_t), intent(inout) :: st
86 class(space_t), intent(in) :: space
87 class(mesh_t), intent(in) :: mesh
88 type(namespace_t), intent(in) :: namespace
89
90 type(block_t) :: blk
91 integer :: ip, il, nlines, ncols, idir, ierr
92 real(real64) :: j_vector(space%dim), dummy(space%dim), xx(1:space%dim), rr, omega
93 character(len=1024) :: tdf_expression, phase_expression
94
95
96 push_sub(external_current_init)
97
98 call profiling_in('EXTERNAL_CURRENT_INIT')
99
100 !%Variable UserDefinedMaxwellExternalCurrent
101 !%Type block
102 !%Section Maxwell
103 !%Description
104 !%
105 !% Example:
106 !%
107 !% <tt>%UserDefinedMaxwellExternalCurrent
108 !% <br>&nbsp;&nbsp; current_parser | "expression_x_dir1" | "expression_y_dir1" | "expression_z_dir1"
109 !% <br>&nbsp;&nbsp; current_parser | "expression_x_dir2" | "expression_y_dir2" | "expression_z_dir2"
110 !% <br>&nbsp;&nbsp; current_td_function | "amplitude_j0_x" | "amplitude_j0_y" | "amplitude_j0_z" | omega | envelope_td_function_name | phase
111 !% <br>%</tt>
112 !%
113 !% Description about UserDefinedMaxwellExternalCurrent follows
114 !%
115 !%Option current_parser 0
116 !% description follows
117 !%Option current_td_function 1
118 !% description follows
119 !%End
120
121 if (parse_block(namespace, 'UserDefinedMaxwellExternalCurrent', blk) == 0) then
122
123 ! find out how many lines (i.e. states) the block has
124 nlines = parse_block_n(blk)
125
126 st%external_current_number = nlines
127 safe_allocate(st%external_current_modus(1:nlines))
128 safe_allocate(st%external_current_string(1:space%dim, 1:nlines))
129 safe_allocate(st%external_current_amplitude(1:mesh%np, 1:space%dim, 1:nlines))
130 safe_allocate(st%external_current_td_function(1:nlines))
131 safe_allocate(st%external_current_omega(1:nlines))
132 safe_allocate(st%external_current_td_phase(1:nlines))
133
134 ! read all lines
135 do il = 1, nlines
136 ! Check that number of columns is four, five, six or seven.
137 ncols = parse_block_cols(blk, il - 1)
138 if ((ncols /= 4) .and. (ncols /= 5) .and. (ncols /= 6) .and. (ncols /= 7)) then
139 message(1) = 'Each line in the MaxwellExternalCurrent block must have'
140 message(2) = 'four, five, six or or seven columns.'
141 call messages_fatal(2, namespace=namespace)
142 end if
143
144 call parse_block_integer(blk, il - 1, 0, st%external_current_modus(il))
145
146 if (st%external_current_modus(il) == external_current_parser) then
147 ! parse formula string
148 do idir = 1, space%dim
149 call parse_block_string(blk, il - 1, idir, st%external_current_string(idir, il))
150 call conv_to_c_string(st%external_current_string(idir, il))
151 end do
152 else if (st%external_current_modus(il) == external_current_td_function) then
153 do idir = 1, space%dim
154 call parse_block_string(blk, il - 1, idir, st%external_current_string(idir, il))
155 call conv_to_c_string(st%external_current_string(idir, il))
156 do ip = 1, mesh%np
157 call mesh_r(mesh, ip, rr, coords = xx)
158 call parse_expression(j_vector(idir), dummy(idir), st%dim, xx, rr, m_zero, &
159 st%external_current_string(idir, il))
160 j_vector(idir) = units_to_atomic(units_inp%energy/(units_inp%length**2), j_vector(idir))
161 st%external_current_amplitude(ip, idir, il) = j_vector(idir)
162 end do
163 end do
164 call parse_block_float(blk, il-1, 4, omega, unit_one/units_inp%time)
165 st%external_current_omega(il) = omega
166 call parse_block_string(blk, il-1, 5, tdf_expression)
167 call tdf_read(st%external_current_td_function(il), namespace, trim(tdf_expression), ierr)
168 if (parse_block_cols(blk, il-1) > 6) then
169 call parse_block_string(blk, il-1, 6, phase_expression)
170 call tdf_read(st%external_current_td_phase(il), namespace, trim(phase_expression), ierr)
171 if (ierr /= 0) then
172 write(message(1),'(3A)') 'Error in the "', trim(tdf_expression), '" field defined in the TDExternalFields block:'
173 write(message(2),'(3A)') 'Time-dependent phase function "', trim(phase_expression), '" not found.'
174 call messages_warning(2, namespace=namespace)
175 end if
176 else
177 call tdf_init(st%external_current_td_phase(il))
178 end if
179 end if
180 end do
181 call parse_block_end(blk)
182 end if
183
184 call profiling_out('EXTERNAL_CURRENT_INIT')
185
186 pop_sub(external_current_init)
187 end subroutine external_current_init
188
189 !----------------------------------------------------------
190 subroutine external_current_calculation(st, space, mesh, time, current)
191 type(states_mxll_t), intent(in) :: st
192 class(space_t), intent(in) :: space
193 class(mesh_t), intent(in) :: mesh
194 real(real64), intent(in) :: time
195 real(real64), intent(inout) :: current(:,:)
196
197 integer :: ip, jn, idir
198 real(real64) :: xx(space%dim), rr, tt, j_vector(space%dim), dummy(space%dim), amp(space%dim)
199 complex(real64) :: exp_arg
200 real(real64) :: tmp_amp, phase
201
203
204 call profiling_in("EXTERNAL_CURRENT_CALC")
205
206 current(:,:) = m_zero
207 do jn = 1, st%external_current_number
208 if (st%external_current_modus(jn) == external_current_parser) then
209 do ip = 1, mesh%np
210 call mesh_r(mesh, ip, rr, coords = xx)
211 do idir = 1, space%dim
212 tt = time
213 call parse_expression(j_vector(idir), dummy(idir), space%dim, xx, rr, tt, &
214 trim(st%external_current_string(idir,jn)))
215 j_vector(idir) = units_to_atomic(units_inp%energy/(units_inp%length**2), j_vector(idir))
216 end do
217 current(ip, :) = current(ip, :) + j_vector
218 end do
219
220 else if (st%external_current_modus(jn) == external_current_td_function) then
221 exp_arg = st%external_current_omega(jn) * time + tdf(st%external_current_td_phase(jn),time)
222 phase = real(exp(-m_zi*exp_arg), real64)
223 tmp_amp = tdf(st%external_current_td_function(jn), time)
224 do ip = 1, mesh%np
225 amp = st%external_current_amplitude(ip, :, jn) * tmp_amp
226 current(ip, :) = current(ip, :) + amp(:) * phase
227 end do
228 end if
229 end do
230
231 call profiling_out("EXTERNAL_CURRENT_CALC")
232
234 end subroutine external_current_calculation
235
237
238!! Local Variables:
239!! mode: f90
240!! coding: utf-8
241!! End:
double exp(double __x) __attribute__((__nothrow__
subroutine, public get_rs_density_ext(st, space, mesh, time, rs_current_density_ext)
integer, parameter, public external_current_td_function
subroutine, public external_current_calculation(st, space, mesh, time, current)
subroutine, public external_current_init(st, space, namespace, mesh)
real(real64), parameter, public m_zero
Definition: global.F90:187
complex(real64), parameter, public m_zi
Definition: global.F90:201
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:115
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:118
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
Definition: mesh.F90:336
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:543
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
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:618
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
subroutine, public build_rs_current_state(current_state, mesh, rs_current_state, ep_field, np)
subroutine, public conv_to_c_string(str)
converts to c string
Definition: string.F90:252
subroutine, public tdf_init(f)
Definition: tdfunction.F90:388
subroutine, public tdf_read(f, namespace, function_name, ierr)
This function initializes "f" from the TDFunctions block.
Definition: tdfunction.F90:218
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_inp
the units systems for reading and writing
type(unit_t), public unit_one
some special units required for particular quantities
Definition: xc.F90:114
Describes mesh distribution to nodes.
Definition: mesh.F90:186