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
25 use math_oct_m
28 use mesh_oct_m
30 use mpi_oct_m
32 use parser_oct_m
34 use space_oct_m
36 use types_oct_m
37 use unit_oct_m
41 use xc_oct_m
42
43 implicit none
44
45 private
46
47 public :: &
51
52 integer, parameter, public :: &
53 EXTERNAL_CURRENT_PARSER = 0, &
55
56contains
57
58 !----------------------------------------------------------
59 subroutine get_rs_density_ext(st, space, mesh, time, rs_current_density_ext)
60 type(states_mxll_t), intent(inout) :: st
61 class(space_t), intent(in) :: space
62 class(mesh_t), intent(in) :: mesh
63 real(real64), intent(in) :: time
64 complex(real64), optional, intent(inout) :: rs_current_density_ext(:,:)
65
66 real(real64), allocatable :: current(:,:,:)
67
68 push_sub(get_rs_density_ext)
69
70 safe_allocate(current(1:mesh%np, 1:space%dim, 1))
71
72 call external_current_calculation(st, space, mesh, time, current(:, :, 1))
73 call build_rs_current_state(current(:, :, 1), mesh, rs_current_density_ext, st%ep, mesh%np)
74
75 safe_deallocate_a(current)
76
77 pop_sub(get_rs_density_ext)
78 end subroutine get_rs_density_ext
79
80
81 !----------------------------------------------------------
82 subroutine external_current_init(st, space, namespace, mesh)
83 type(states_mxll_t), intent(inout) :: st
84 class(space_t), intent(in) :: space
85 class(mesh_t), intent(in) :: mesh
86 type(namespace_t), intent(in) :: namespace
87
88 type(block_t) :: blk
89 integer :: ip, il, nlines, ncols, idir, ierr
90 real(real64) :: j_vector(space%dim), dummy(space%dim), xx(1:space%dim), rr, omega
91 character(len=1024) :: tdf_expression, phase_expression
92
93
94 push_sub(external_current_init)
95
96 call profiling_in('EXTERNAL_CURRENT_INIT')
97
98 !%Variable UserDefinedMaxwellExternalCurrent
99 !%Type block
100 !%Section Maxwell
101 !%Description
102 !%
103 !% Example:
104 !%
105 !% <tt>%UserDefinedMaxwellExternalCurrent
106 !% <br>&nbsp;&nbsp; current_parser | "expression_x_dir1" | "expression_y_dir1" | "expression_z_dir1"
107 !% <br>&nbsp;&nbsp; current_parser | "expression_x_dir2" | "expression_y_dir2" | "expression_z_dir2"
108 !% <br>&nbsp;&nbsp; current_td_function | "amplitude_j0_x" | "amplitude_j0_y" | "amplitude_j0_z" | omega |
109 !% envelope_td_function_name | phase
110 !% <br>%</tt>
111 !%
112 !% Description about UserDefinedMaxwellExternalCurrent follows
113 !%
114 !%Option current_parser 0
115 !% description follows
116 !%Option current_td_function 1
117 !% description follows
118 !%End
119
120 if (parse_block(namespace, 'UserDefinedMaxwellExternalCurrent', blk) == 0) then
121
122 ! find out how many lines (i.e. states) the block has
123 nlines = parse_block_n(blk)
124
125 st%external_current_number = nlines
126 safe_allocate(st%external_current_modus(1:nlines))
127 safe_allocate(st%external_current_string(1:space%dim, 1:nlines))
128 safe_allocate(st%external_current_amplitude(1:mesh%np, 1:space%dim, 1:nlines))
129 safe_allocate(st%external_current_td_function(1:nlines))
130 safe_allocate(st%external_current_omega(1:nlines))
131 safe_allocate(st%external_current_td_phase(1:nlines))
132
133 ! read all lines
134 do il = 1, nlines
135 ! Check that number of columns is four, five, six or seven.
136 ncols = parse_block_cols(blk, il - 1)
137 if ((ncols /= 4) .and. (ncols /= 5) .and. (ncols /= 6) .and. (ncols /= 7)) then
138 message(1) = 'Each line in the MaxwellExternalCurrent block must have'
139 message(2) = 'four, five, six or or seven columns.'
140 call messages_fatal(2, namespace=namespace)
141 end if
142
143 call parse_block_integer(blk, il - 1, 0, st%external_current_modus(il))
144
145 if (st%external_current_modus(il) == external_current_parser) then
146 ! parse formula string
147 do idir = 1, space%dim
148 call parse_block_string(blk, il - 1, idir, st%external_current_string(idir, il), convert_to_c=.true.)
149 end do
150 else if (st%external_current_modus(il) == external_current_td_function) then
151 do idir = 1, space%dim
152 call parse_block_string(blk, il - 1, idir, st%external_current_string(idir, il), convert_to_c=.true.)
153 do ip = 1, mesh%np
154 call mesh_r(mesh, ip, rr, coords = xx)
155 call parse_expression(j_vector(idir), dummy(idir), st%dim, xx, rr, m_zero, &
156 st%external_current_string(idir, il))
157 st%external_current_amplitude(ip, idir, il) = j_vector(idir)
158 end do
159 end do
160 call parse_block_float(blk, il-1, 4, omega, unit_one/units_inp%time)
161 st%external_current_omega(il) = omega
162 call parse_block_string(blk, il-1, 5, tdf_expression)
163 call tdf_read(st%external_current_td_function(il), namespace, trim(tdf_expression), ierr)
164 if (parse_block_cols(blk, il-1) > 6) then
165 call parse_block_string(blk, il-1, 6, phase_expression)
166 call tdf_read(st%external_current_td_phase(il), namespace, trim(phase_expression), ierr)
167 if (ierr /= 0) then
168 write(message(1),'(3A)') 'Error in the "', trim(tdf_expression), '" field defined in the TDExternalFields block:'
169 write(message(2),'(3A)') 'Time-dependent phase function "', trim(phase_expression), '" not found.'
170 call messages_warning(2, namespace=namespace)
171 end if
172 else
173 call tdf_init(st%external_current_td_phase(il))
174 end if
175 end if
176 end do
178 end if
179
180 call profiling_out('EXTERNAL_CURRENT_INIT')
181
182 pop_sub(external_current_init)
183 end subroutine external_current_init
184
185 !----------------------------------------------------------
186 subroutine external_current_calculation(st, space, mesh, time, current)
187 type(states_mxll_t), intent(in) :: st
188 class(space_t), intent(in) :: space
189 class(mesh_t), intent(in) :: mesh
190 real(real64), intent(in) :: time
191 real(real64), intent(inout) :: current(:,:)
192
193 integer :: ip, jn, idir
194 real(real64) :: xx(space%dim), rr, tt, j_vector(space%dim), dummy(space%dim), amp(space%dim)
195 complex(real64) :: exp_arg
196 real(real64) :: tmp_amp, phase
197
199
200 call profiling_in("EXTERNAL_CURRENT_CALC")
201
202 current(:,:) = m_zero
203 do jn = 1, st%external_current_number
204 if (st%external_current_modus(jn) == external_current_parser) then
205 do ip = 1, mesh%np
206 call mesh_r(mesh, ip, rr, coords = xx)
207 do idir = 1, space%dim
208 tt = time
209 call parse_expression(j_vector(idir), dummy(idir), space%dim, xx, rr, tt, &
210 trim(st%external_current_string(idir,jn)))
211 end do
212 current(ip, :) = current(ip, :) + j_vector
213 end do
214
215 else if (st%external_current_modus(jn) == external_current_td_function) then
216 exp_arg = st%external_current_omega(jn) * time + tdf(st%external_current_td_phase(jn),time)
217 phase = real(exp(-m_zi*exp_arg), real64)
218 tmp_amp = tdf(st%external_current_td_function(jn), time)
219 do ip = 1, mesh%np
220 amp = st%external_current_amplitude(ip, :, jn) * tmp_amp
221 current(ip, :) = current(ip, :) + amp(:) * phase
222 end do
223 end if
224 end do
225
226 call profiling_out("EXTERNAL_CURRENT_CALC")
227
229 end subroutine external_current_calculation
230
232
233!! Local Variables:
234!! mode: f90
235!! coding: utf-8
236!! 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:200
complex(real64), parameter, public m_zi
Definition: global.F90:214
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
Definition: mesh.F90:342
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public parse_block_string(blk, l, c, res, convert_to_c)
Definition: parser.F90:818
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:623
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:631
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:554
subroutine, public build_rs_current_state(current_state, mesh, rs_current_state, ep_field, np)
subroutine, public tdf_init(f)
Definition: tdfunction.F90:390
subroutine, public tdf_read(f, namespace, function_name, ierr)
This function initializes "f" from the TDFunctions block.
Definition: tdfunction.F90:220
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:134
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:120
Describes mesh distribution to nodes.
Definition: mesh.F90:187
int true(void)