Octopus
filter.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
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#include "global.h"
20
21module filter_oct_m
22 use debug_oct_m
23 use global_oct_m
24 use io_oct_m
27 use parser_oct_m
30
31 implicit none
32
33 private
34
35 public :: &
36 filter_t, &
42
43 type filter_t
44 private
45 integer :: no_filters
46 type(tdf_t), allocatable :: f(:)
47 character(len=1024), allocatable :: expression(:)
48 integer, allocatable :: domain(:)
49 end type filter_t
50
51 integer, parameter, public :: &
52 filter_freq = 1, &
53 filter_time = 2
54
55contains
56
57
58 ! ---------------------------------------------------------
59 subroutine filter_init(steps, namespace, dt, filter)
60 integer, intent(in) :: steps
61 type(namespace_t), intent(in) :: namespace
62 real(real64), intent(in) :: dt
63 type(filter_t), intent(inout) :: filter
64
65 type(block_t) :: blk
66 integer :: i, no_f
67
68 push_sub(filter_init)
69
70 filter%no_filters = 0
71
72 !%Variable OCTFilter
73 !%Type block
74 !%Section Calculation Modes::Optimal Control
75 !%Description
76 !% The block <tt>OCTFilter</tt> describes the type and shape of the filter function
77 !% that are applied to the optimized laser field in each iteration.
78 !% The filter forces the laser field to obtain the given form in frequency space.
79 !% Each line of the block describes a filter; this way you can actually have more
80 !% than one filter function (<i>e.g.</i> a filter in time and two in frequency space).
81 !% The filters are applied in the given order, <i>i.e.</i>, first the filter specified
82 !% by the first line is applied, then second line.
83 !% The syntax of each line is, then:
84 !%
85 !% <tt>%OCTFilter
86 !% <br>&nbsp;&nbsp;domain | function
87 !% <br>%</tt>
88 !%
89 !%
90 !% Possible arguments for domain are:
91 !%
92 !% (i) <tt>frequency_filter</tt>: Specifies a spectral filter.
93 !%
94 !% (ii) <tt>time_filter</tt>: DISABLED IN THIS VERSION.
95 !%
96 !% Example:
97 !%
98 !% <tt>%OCTFilter
99 !% <br>&nbsp;&nbsp;time | "exp(-80*( w + 0.1567 )^2 ) + exp(-80*( w - 0.1567 )^2 )"
100 !% <br>%</tt>
101 !%
102 !% Be careful that also the negative-frequency component is filtered since the resulting
103 !% field has to be real-valued.
104 !%
105 !%Option frequency_filter 1
106 !% The filter is applied in the frequency domain.
107 !%End
108 if (parse_block(namespace, 'OCTFilter', blk) == 0) then
109 no_f = parse_block_n(blk)
110
111 if (no_f <= 0) then
112 pop_sub(filter_init)
113 return
114 end if
115
116 filter%no_filters = no_f
117 safe_allocate(filter%f(1:no_f))
118 safe_allocate(filter%expression(1:no_f))
119 safe_allocate(filter%domain(1:no_f))
120
121 do i = 1, no_f
122 call parse_block_integer(blk, i-1, 0, filter%domain(i))
123 call parse_block_string(blk, i-1, 1, filter%expression(i), convert_to_c=.true.)
124 call tdf_init_numerical(filter%f(i), steps, dt, -m_one)
125 call tdf_numerical_to_fourier(filter%f(i))
126 end do
127 call build_filter(filter)
128
129 call parse_block_end(blk)
130 end if
131
132 pop_sub(filter_init)
133 end subroutine filter_init
134 ! ---------------------------------------------------------
135
136
137 ! ---------------------------------------------------------
138 subroutine filter_apply(f, filter)
139 type(tdf_t), intent(inout) :: f
140 type(filter_t), intent(in) :: filter
142 integer :: no_f, i, j, nfreqs
144 push_sub(filter_apply)
145
146 no_f = filter%no_filters
147 if (no_f <= 0) then
148 pop_sub(filter_apply)
149 return
150 end if
151
152 do i = 1, no_f
153 write(message(1),'(a,i2)') "Info: Applying filter "
155
156 nfreqs = tdf_nfreqs(f)
157
158 select case (filter%domain(i))
159 case (filter_freq)
161 call tdf_set_numerical(f, 1, tdf(f, 1)*tdf(filter%f(i), 1))
162 do j = 2, nfreqs !+ 1
163 call tdf_set_numerical(f, j, tdf(f, j)*tdf(filter%f(i), j) / sqrt(m_two))
164 end do
165 do j = nfreqs + 1, 2*nfreqs - 1
166 call tdf_set_numerical(f, j, tdf(f, j)*tdf(filter%f(i), j-nfreqs+1) / sqrt(m_two))
167 end do
169
170 case default
171 message(1) = "...I don't know this filter type..."
172 call messages_fatal(1)
173 end select
174
175 end do
176
177 pop_sub(filter_apply)
178 end subroutine filter_apply
179 ! ---------------------------------------------------------
180
181
182 !------------------------------------------------
183 subroutine build_filter(filter)
184 type(filter_t), intent(inout) :: filter
185
186 integer :: i, ip, j, nfreqs
187 real(real64) :: f_re, f_im
188 complex(real64), allocatable :: ff(:)
189 real(real64), allocatable :: grid(:)
190
191 push_sub(build_filter)
192
193 do i = 1, filter%no_filters
194
195 nfreqs = tdf_nfreqs(filter%f(i))
196
197 safe_allocate(ff(1:tdf_nfreqs(filter%f(i))))
198 safe_allocate(grid(1:tdf_nfreqs(filter%f(i))))
199 ff = m_z0
200 grid = m_zero
201
202 select case (filter%domain(i))
203 case (filter_freq)
204 call tdf_fourier_grid(filter%f(i), grid)
205 ff = m_z1
206 do ip = 1, tdf_nfreqs(filter%f(i))
207 call parse_expression(f_re, f_im, "w", real(grid(ip), real64), filter%expression(i))
208 ff(ip) = cmplx(f_re, f_im, real64)
209 end do
210
211 case default
212 write(message(1),'(a)') "Unknown choice of domain for filter."
213 write(message(2),'(a)') "Choose: time or freq ."
214 call messages_fatal(2)
215 end select
216
217 call tdf_set_numerical(filter%f(i), 1, real(ff(1), real64))
218 do j = 2, nfreqs !+ 1
219 call tdf_set_numerical(filter%f(i), j, sqrt(m_two)*real(ff(j), real64))
220 end do
221 ! WARNING: all the sine coefficients (imaginary part of ff) should be null.
222 do j = nfreqs + 1, 2*nfreqs - 1
223 call tdf_set_numerical(filter%f(i), j, -sqrt(m_two)*aimag(ff(j-nfreqs+1)))
224 end do
225
226 safe_deallocate_a(ff)
227 safe_deallocate_a(grid)
228
229 end do
230
231 pop_sub(build_filter)
232 end subroutine build_filter
233 ! ---------------------------------------------------------
234
235
236 ! ---------------------------------------------------------
237 subroutine filter_write(filter, namespace)
238 type(filter_t), intent(in) :: filter
239 type(namespace_t), intent(in) :: namespace
240
241 integer :: kk, iunit, i, max_iter
242 character(len=80) :: filename
243 real(real64), allocatable :: wgrid(:)
244
245 push_sub(filter_write)
246
247 if (filter%no_filters <= 0) then
248 pop_sub(filter_write)
249 return
250 end if
251
252 do kk = 1, filter%no_filters
253 write(filename,'(a,i2.2)') oct_dir//'filter', kk
254 max_iter = tdf_niter(filter%f(kk))
255 iunit = io_open(filename, namespace, action='write')
256 safe_allocate(wgrid(1:max_iter/2+1))
257 call tdf_fourier_grid(filter%f(kk), wgrid)
258 do i = 1, max_iter/2+1
259 write(iunit, '(3es30.16e4)') wgrid(i), tdf(filter%f(kk), i)
260 end do
261 safe_deallocate_a(wgrid)
262 call io_close(iunit)
263 end do
264
265 pop_sub(filter_write)
266 end subroutine filter_write
267 ! ---------------------------------------------------------
268
269
270 ! ----------------------------------------------------------------
271 subroutine filter_end(filter)
272 type(filter_t), intent(inout) :: filter
273 integer :: i
274
275 push_sub(filter_end)
276
277 if (filter%no_filters <= 0) then
278 pop_sub(filter_end)
279 return
280 end if
281
282 do i = 1, filter%no_filters
283 call tdf_end(filter%f(i))
284 end do
285 safe_deallocate_a(filter%f)
286 filter%no_filters = 0
287 safe_deallocate_a(filter%expression)
288 safe_deallocate_a(filter%domain)
289
290 pop_sub(filter_end)
291 end subroutine filter_end
292 ! ---------------------------------------------------------
293
294
295 ! ---------------------------------------------------------
296 integer function filter_number(filter)
297 type(filter_t), intent(in) :: filter
298
299 push_sub(filter_number)
300 filter_number = filter%no_filters
301
302 pop_sub(filter_number)
303 end function filter_number
304 ! ---------------------------------------------------------
305
306
307end module filter_oct_m
308
309!! Local Variables:
310!! mode: f90
311!! coding: utf-8
312!! End:
double sqrt(double __x) __attribute__((__nothrow__
integer, parameter, public filter_time
Definition: filter.F90:146
integer function, public filter_number(filter)
Definition: filter.F90:392
subroutine, public filter_init(steps, namespace, dt, filter)
Definition: filter.F90:155
subroutine, public filter_apply(f, filter)
Definition: filter.F90:234
subroutine, public filter_write(filter, namespace)
Definition: filter.F90:333
subroutine, public filter_end(filter)
Definition: filter.F90:367
subroutine build_filter(filter)
Definition: filter.F90:279
real(real64), parameter, public m_two
Definition: global.F90:193
real(real64), parameter, public m_zero
Definition: global.F90:191
complex(real64), parameter, public m_z0
Definition: global.F90:201
complex(real64), parameter, public m_z1
Definition: global.F90:202
real(real64), parameter, public m_one
Definition: global.F90:192
character(len= *), parameter, public oct_dir
Definition: global.F90:273
Definition: io.F90:116
subroutine, public io_close(iunit, grp)
Definition: io.F90:466
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:401
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 messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
subroutine, public parse_block_string(blk, l, c, res, convert_to_c)
Definition: parser.F90:810
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:615
subroutine, public tdf_numerical_to_fourier(f)
Definition: tdfunction.F90:642
integer pure function, public tdf_nfreqs(f)
Definition: tdfunction.F90:374
integer pure function, public tdf_niter(f)
Definition: tdfunction.F90:366
subroutine, public tdf_end(f)
Definition: tdfunction.F90:982
subroutine, public tdf_fourier_grid(f, wgrid)
Definition: tdfunction.F90:615
subroutine, public tdf_init_numerical(f, niter, dt, omegamax, initval, rep)
Definition: tdfunction.F90:560
subroutine, public tdf_fourier_to_numerical(f)
Definition: tdfunction.F90:677
int true(void)