Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
mapping_handler.f90
1
2! Copyright (c) 2023, The Neko Authors
3! All rights reserved.
4!
5! Redistribution and use in mapping and binary forms, with or without
6! modification, are permitted provided that the following conditions
7! are met:
8!
9! * Redistributions of mapping code must retain the above copyright
10! notice, this list of conditions and the following disclaimer.
11!
12! * Redistributions in binary form must reproduce the above
13! copyright notice, this list of conditions and the following
14! disclaimer in the documentation and/or other materials provided
15! with the distribution.
16!
17! * Neither the name of the authors nor the names of its
18! contributors may be used to endorse or promote products derived
19! from this software without specific prior written permission.
20!
21! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32! POSSIBILITY OF SUCH DAMAGE.
33!
36 use neko_config, only: neko_bcknd_device
37 use num_types, only: rp
40 use field, only: field_t
41 use field_list, only: field_list_t
42 use json_utils, only: json_get, json_extract_item, json_get_or_default
43 use json_module, only: json_file
44 use coefs, only: coef_t
45 use user_intf, only: user_t
46 use field_math, only: field_rzero, field_copy
47 use math, only: col2
48 use device_math, only: device_col2
49 use scratch_registry, only: neko_scratch_registry
50 use utils, only: neko_warning
51 use vector, only:vector_t
53 implicit none
54 private
55
62 type, public :: mapping_handler_t
66 class(mapping_wrapper_t), allocatable :: mapping_cascade(:)
68 type(coef_t), pointer :: coef
69
70 contains
72 procedure, pass(this) :: init_base => mapping_handler_init_base
74 procedure, pass(this) :: free => mapping_handler_free
76 generic :: apply_forward => mapping_handler_apply_forward_field, &
77 mapping_handler_apply_forward_vector
78 procedure, pass(this) :: mapping_handler_apply_forward_field
79 procedure, pass(this) :: mapping_handler_apply_forward_vector
82 generic :: apply_backward => mapping_handler_apply_backward_field, &
83 mapping_handler_apply_backward_vector
84 procedure, pass(this) :: mapping_handler_apply_backward_field
85 procedure, pass(this) :: mapping_handler_apply_backward_vector
87 generic :: add => add_mapping, add_json_mappings
89 procedure, pass(this) :: add_mapping => &
90 mapping_handler_add_mapping
92 procedure, pass(this) :: add_json_mappings => &
93 mapping_handler_add_json_mappings
94 end type mapping_handler_t
95
96contains
97
99 subroutine mapping_handler_init_base(this, coef)
100 class(mapping_handler_t), intent(inout) :: this
101 type(coef_t), target, intent(in) :: coef
102
103 call this%free()
104
105 this%coef => coef
106
107 end subroutine mapping_handler_init_base
108
109
111 subroutine mapping_handler_free(this)
112 class(mapping_handler_t), intent(inout) :: this
113 integer :: i
114
115 if (allocated(this%mapping_cascade)) then
116 do i = 1, size(this%mapping_cascade)
117 call this%mapping_cascade(i)%free()
118 end do
119 deallocate(this%mapping_cascade)
120 end if
121
122 end subroutine mapping_handler_free
123
128 subroutine mapping_handler_apply_forward_field(this, X_out, X_in)
129 class(mapping_handler_t), intent(inout) :: this
130 type(field_t), intent(in) :: X_in
131 type(field_t), intent(inout) :: X_out
132 integer :: i
133 type(field_t), pointer :: tmp_fld_in, tmp_fld_out
134 integer :: temp_indices(2)
135
136 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1))
137 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2))
138
139 ! Start by copying the first X_in into the tmp_fld_out to begin the
140 ! cascade.
141 call field_copy(tmp_fld_out, x_in)
142
143 ! We enter the cascade
144 if (allocated(this%mapping_cascade)) then
145 do i = 1, size(this%mapping_cascade)
146 ! the output from one mapping becomes the input for the next.
147 call field_copy(tmp_fld_in, tmp_fld_out)
148 ! apply the mapping on temp_fld
149 call this%mapping_cascade(i)%mapping%apply_forward(tmp_fld_out, &
150 tmp_fld_in)
151
152 end do
153
154 end if
155
156 ! our final mapping should now live in tmp_fld_out
157 call field_copy(x_out, tmp_fld_out)
158
159 ! free the scratch.
160 call neko_scratch_registry%relinquish_field(temp_indices)
161
162 end subroutine mapping_handler_apply_forward_field
163
168 subroutine mapping_handler_apply_forward_vector(this, X_out, X_in)
169 class(mapping_handler_t), intent(inout) :: this
170 type(vector_t), intent(in) :: X_in
171 type(vector_t), intent(inout) :: X_out
172 type(field_t), pointer :: tmp_fld_in, tmp_fld_out
173 integer :: temp_indices(2)
174
175 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1))
176 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2))
177
178 call vector_to_field(tmp_fld_in, x_in)
179 call mapping_handler_apply_forward_field(this, tmp_fld_out, tmp_fld_in)
180 call field_to_vector(x_out, tmp_fld_out)
181
182 ! free the scratch.
183 call neko_scratch_registry%relinquish_field(temp_indices)
184
185 end subroutine mapping_handler_apply_forward_vector
186
193 subroutine mapping_handler_apply_backward_field(this, sens_out, sens_in)
194 class(mapping_handler_t), intent(inout) :: this
195 type(field_t), intent(inout) :: sens_out
196 type(field_t), intent(in) :: sens_in
197 integer :: i
198 type(field_t), pointer :: tmp_fld_in, tmp_fld_out
199 integer :: temp_indices(2)
200
201 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1))
202 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2))
203
204 ! Start by copying the first sens_in into the tmp_fld_out to begin the
205 ! cascade.
206 call field_copy(tmp_fld_out, sens_in)
207
208 ! We enter the cascade
209 if (allocated(this%mapping_cascade)) then
210 do i = size(this%mapping_cascade), 1, -1
211 ! the output from one mapping becomes the input for the next.
212 call field_copy(tmp_fld_in, tmp_fld_out)
213 ! apply the mapping on temp_fld
214 ! NOTE
215 ! all the X_in that is required to map backward should be held
216 ! internally by each mapping
217 call this%mapping_cascade(i)%mapping%apply_backward(tmp_fld_out, &
218 tmp_fld_in)
219
220 end do
221
222 end if
223
224 ! post-multiply by mass matrix
225 if (neko_bcknd_device .eq. 1) then
226 call device_col2(tmp_fld_out%x_d, this%coef%B_d, tmp_fld_out%size())
227 else
228 call col2(tmp_fld_out%x, this%coef%B, tmp_fld_out%size())
229 end if
230
231 ! our final mapping should now live in tmp_fld_out
232 call field_copy(sens_out, tmp_fld_out)
233
234 ! free the scratch.
235 call neko_scratch_registry%relinquish_field(temp_indices)
236
237
238 end subroutine mapping_handler_apply_backward_field
239
246 subroutine mapping_handler_apply_backward_vector(this, X_out, X_in)
247 class(mapping_handler_t), intent(inout) :: this
248 type(vector_t), intent(in) :: X_in
249 type(vector_t), intent(inout) :: X_out
250 type(field_t), pointer :: tmp_fld_in, tmp_fld_out
251 integer :: temp_indices(2)
252
253 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1))
254 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2))
255
256 call vector_to_field(tmp_fld_in, x_in)
257 call mapping_handler_apply_backward_field(this, tmp_fld_out, tmp_fld_in)
258 call field_to_vector(x_out, tmp_fld_out)
259
260 ! free the scratch.
261 call neko_scratch_registry%relinquish_field(temp_indices)
262
263 end subroutine mapping_handler_apply_backward_vector
264
266 subroutine mapping_handler_add_json_mappings(this, json, name)
267 class(mapping_handler_t), intent(inout) :: this
268 type(json_file), intent(inout) :: json
269 character(len=*), intent(in) :: name
270
271 class(mapping_wrapper_t), dimension(:), allocatable :: temp
272
273 ! A single mapping as its own json_file.
274 type(json_file) :: mapping_subdict
275 integer :: n_mappings, i, i0
276
277 if (json%valid_path(name)) then
278 ! Get the number of mapping_cascade.
279 call json%info(name, n_children = n_mappings)
280
281 if (allocated(this%mapping_cascade)) then
282 i0 = size(this%mapping_cascade)
283 call move_alloc(this%mapping_cascade, temp)
284 allocate(this%mapping_cascade(i0 + n_mappings))
285 if (allocated(temp)) then
286 do i = 1, i0
287 call move_alloc(temp(i)%mapping, &
288 this%mapping_cascade(i)%mapping)
289 end do
290 end if
291 else
292 i0 = 0
293 allocate(this%mapping_cascade(n_mappings))
294 end if
295
296 do i = 1, n_mappings
297 ! Create a new json containing just the subdict for this mapping.
298 call json_extract_item(json, name, i, mapping_subdict)
299 call mapping_factory(this%mapping_cascade(i + i0)%mapping, &
300 mapping_subdict, this%coef)
301 end do
302 else
303 ! I was considering an error, but maybe a warning is more appropriate
304 call neko_warning("No mappings selected")
305 end if
306
307 end subroutine mapping_handler_add_json_mappings
308
312 subroutine mapping_handler_add_mapping(this, mapping)
313 class(mapping_handler_t), intent(inout) :: this
314 class(mapping_t), intent(in) :: mapping
315 class(mapping_wrapper_t), dimension(:), allocatable :: temp
316
317 integer :: n_mappings, i
318
319 if (allocated(this%mapping_cascade)) then
320 n_mappings = size(this%mapping_cascade)
321 else
322 n_mappings = 0
323 end if
324
325 call move_alloc(this%mapping_cascade, temp)
326 allocate(this%mapping_cascade(n_mappings + 1))
327
328 if (allocated(temp)) then
329 do i = 1, n_mappings
330 call move_alloc(temp(i)%mapping, this%mapping_cascade(i)%mapping)
331 end do
332 end if
333
334 this%mapping_cascade(n_mappings + 1)%mapping = mapping
335
336 end subroutine mapping_handler_add_mapping
337end module mapping_handler
mapping factory. Both constructs and initializes the object.
Definition mapping.f90:137
Implements the mapping_handler_t type.
Mappings to be applied to a scalar field.
Definition mapping.f90:35
Contains extensions to the neko library required to run the topology optimization code.
Definition neko_ext.f90:9
subroutine, public field_to_vector(vector, field)
Field to vector.
Definition neko_ext.f90:373
subroutine, public vector_to_field(field, vector)
Vector to field.
Definition neko_ext.f90:349
Base abstract class for mapping.
Definition mapping.f90:45
A helper type that is needed to have an array of polymorphic objects.
Definition mapping.f90:72
Abstract class for handling mapping_cascade.