Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
mapping_handler.f90
Go to the documentation of this file.
1
34!
37 use neko_config, only: neko_bcknd_device
38 use num_types, only: rp
41 use field, only: field_t
42 use field_list, only: field_list_t
43 use json_utils, only: json_get, json_extract_item, json_get_or_default
44 use json_module, only: json_file
45 use coefs, only: coef_t
46 use user_intf, only: user_t
47 use field_math, only: field_rzero, field_copy
48 use math, only: col2
49 use device_math, only: device_col2
50 use scratch_registry, only: neko_scratch_registry
51 use utils, only: neko_warning
52 use vector, only:vector_t
54 use gather_scatter, only : gs_op_add
55 implicit none
56 private
57
64 type, public :: mapping_handler_t
68 class(mapping_wrapper_t), allocatable :: mapping_cascade(:)
70 type(coef_t), pointer :: coef
71
72 contains
74 procedure, pass(this) :: init_base => mapping_handler_init_base
76 procedure, pass(this) :: free => mapping_handler_free
78 generic :: apply_forward => mapping_handler_apply_forward_field, &
79 mapping_handler_apply_forward_vector
80 procedure, pass(this) :: mapping_handler_apply_forward_field
81 procedure, pass(this) :: mapping_handler_apply_forward_vector
84 generic :: apply_backward => mapping_handler_apply_backward_field, &
85 mapping_handler_apply_backward_vector
86 procedure, pass(this) :: mapping_handler_apply_backward_field
87 procedure, pass(this) :: mapping_handler_apply_backward_vector
89 generic :: add => add_mapping, add_json_mappings
91 procedure, pass(this) :: add_mapping => &
92 mapping_handler_add_mapping
94 procedure, pass(this) :: add_json_mappings => &
95 mapping_handler_add_json_mappings
97 procedure, pass(this) :: make_cts => mapping_handler_make_cts
98 end type mapping_handler_t
99
100contains
101
103 subroutine mapping_handler_init_base(this, coef)
104 class(mapping_handler_t), intent(inout) :: this
105 type(coef_t), target, intent(in) :: coef
106
107 call this%free()
108
109 this%coef => coef
110
111 end subroutine mapping_handler_init_base
112
113
115 subroutine mapping_handler_free(this)
116 class(mapping_handler_t), intent(inout) :: this
117 integer :: i
118
119 if (allocated(this%mapping_cascade)) then
120 do i = 1, size(this%mapping_cascade)
121 call this%mapping_cascade(i)%free()
122 end do
123 deallocate(this%mapping_cascade)
124 end if
125
126 end subroutine mapping_handler_free
127
132 subroutine mapping_handler_apply_forward_field(this, X_out, X_in)
133 class(mapping_handler_t), intent(inout) :: this
134 type(field_t), intent(in) :: X_in
135 type(field_t), intent(inout) :: X_out
136 integer :: i
137 type(field_t), pointer :: tmp_fld_in, tmp_fld_out
138 integer :: temp_indices(2)
139
140 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
141 .false.)
142 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
143 .false.)
144
145 ! Start by copying the first X_in into the tmp_fld_out to begin the
146 ! cascade.
147 call field_copy(tmp_fld_out, x_in)
148
149 ! enforce continuity in the field
150 call this%make_cts(tmp_fld_out)
151
152 ! We enter the cascade
153 if (allocated(this%mapping_cascade)) then
154 do i = 1, size(this%mapping_cascade)
155 ! the output from one mapping becomes the input for the next.
156 call field_copy(tmp_fld_in, tmp_fld_out)
157 ! apply the mapping on temp_fld
158 call this%mapping_cascade(i)%mapping%apply_forward(tmp_fld_out, &
159 tmp_fld_in)
160
161 end do
162
163 end if
164
165 ! our final mapping should now live in tmp_fld_out
166 call field_copy(x_out, tmp_fld_out)
167
168 ! free the scratch.
169 call neko_scratch_registry%relinquish_field(temp_indices)
170
171 end subroutine mapping_handler_apply_forward_field
172
177 subroutine mapping_handler_apply_forward_vector(this, X_out, X_in)
178 class(mapping_handler_t), intent(inout) :: this
179 type(vector_t), intent(in) :: X_in
180 type(vector_t), intent(inout) :: X_out
181 type(field_t), pointer :: tmp_fld_in, tmp_fld_out
182 integer :: temp_indices(2)
183
184 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
185 .false.)
186 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
187 .false.)
188
189 call vector_to_field(tmp_fld_in, x_in)
190 call mapping_handler_apply_forward_field(this, tmp_fld_out, tmp_fld_in)
191 call field_to_vector(x_out, tmp_fld_out)
192
193 ! free the scratch.
194 call neko_scratch_registry%relinquish_field(temp_indices)
195
196 end subroutine mapping_handler_apply_forward_vector
197
204 subroutine mapping_handler_apply_backward_field(this, sens_out, sens_in)
205 class(mapping_handler_t), intent(inout) :: this
206 type(field_t), intent(inout) :: sens_out
207 type(field_t), intent(in) :: sens_in
208 integer :: i
209 type(field_t), pointer :: tmp_fld_in, tmp_fld_out
210 integer :: temp_indices(2)
211
212 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
213 .false.)
214 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
215 .false.)
216
217 ! Start by copying the first sens_in into the tmp_fld_out to begin the
218 ! cascade.
219 call field_copy(tmp_fld_out, sens_in)
220
221 ! enforce continuity in the field
222 call this%make_cts(tmp_fld_out)
223
224 ! We enter the cascade
225 if (allocated(this%mapping_cascade)) then
226 do i = size(this%mapping_cascade), 1, -1
227 ! the output from one mapping becomes the input for the next.
228 call field_copy(tmp_fld_in, tmp_fld_out)
229 ! apply the mapping on temp_fld
230 ! NOTE
231 ! all the X_in that is required to map backward should be held
232 ! internally by each mapping
233 call this%mapping_cascade(i)%mapping%apply_backward(tmp_fld_out, &
234 tmp_fld_in)
235
236 end do
237
238 end if
239
240 ! post-multiply by mass matrix
241 if (neko_bcknd_device .eq. 1) then
242 call device_col2(tmp_fld_out%x_d, this%coef%B_d, tmp_fld_out%size())
243 else
244 call col2(tmp_fld_out%x, this%coef%B, tmp_fld_out%size())
245 end if
246
247 ! our final mapping should now live in tmp_fld_out
248 call field_copy(sens_out, tmp_fld_out)
249
250 ! free the scratch.
251 call neko_scratch_registry%relinquish_field(temp_indices)
252
253
254 end subroutine mapping_handler_apply_backward_field
255
262 subroutine mapping_handler_apply_backward_vector(this, X_out, X_in)
263 class(mapping_handler_t), intent(inout) :: this
264 type(vector_t), intent(in) :: X_in
265 type(vector_t), intent(inout) :: X_out
266 type(field_t), pointer :: tmp_fld_in, tmp_fld_out
267 integer :: temp_indices(2)
268
269 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
270 .false.)
271 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
272 .false.)
273
274 call vector_to_field(tmp_fld_in, x_in)
275 call mapping_handler_apply_backward_field(this, tmp_fld_out, tmp_fld_in)
276 call field_to_vector(x_out, tmp_fld_out)
277
278 ! free the scratch.
279 call neko_scratch_registry%relinquish_field(temp_indices)
280
281 end subroutine mapping_handler_apply_backward_vector
282
284 subroutine mapping_handler_add_json_mappings(this, json, name)
285 class(mapping_handler_t), intent(inout) :: this
286 type(json_file), intent(inout) :: json
287 character(len=*), intent(in) :: name
288
289 class(mapping_wrapper_t), dimension(:), allocatable :: temp
290
291 ! A single mapping as its own json_file.
292 type(json_file) :: mapping_subdict
293 integer :: n_mappings, i, i0
294
295 if (json%valid_path(name)) then
296 ! Get the number of mapping_cascade.
297 call json%info(name, n_children = n_mappings)
298
299 if (allocated(this%mapping_cascade)) then
300 i0 = size(this%mapping_cascade)
301 call move_alloc(this%mapping_cascade, temp)
302 allocate(this%mapping_cascade(i0 + n_mappings))
303 if (allocated(temp)) then
304 do i = 1, i0
305 call move_alloc(temp(i)%mapping, &
306 this%mapping_cascade(i)%mapping)
307 end do
308 end if
309 else
310 i0 = 0
311 allocate(this%mapping_cascade(n_mappings))
312 end if
313
314 do i = 1, n_mappings
315 ! Create a new json containing just the subdict for this mapping.
316 call json_extract_item(json, name, i, mapping_subdict)
317 call mapping_factory(this%mapping_cascade(i + i0)%mapping, &
318 mapping_subdict, this%coef)
319 end do
320 else
321 ! I was considering an error, but maybe a warning is more appropriate
322 call neko_warning("No mappings selected")
323 end if
324
325 end subroutine mapping_handler_add_json_mappings
326
330 subroutine mapping_handler_add_mapping(this, mapping)
331 class(mapping_handler_t), intent(inout) :: this
332 class(mapping_t), intent(in) :: mapping
333 class(mapping_wrapper_t), dimension(:), allocatable :: temp
334
335 integer :: n_mappings, i
336
337 if (allocated(this%mapping_cascade)) then
338 n_mappings = size(this%mapping_cascade)
339 else
340 n_mappings = 0
341 end if
342
343 call move_alloc(this%mapping_cascade, temp)
344 allocate(this%mapping_cascade(n_mappings + 1))
345
346 if (allocated(temp)) then
347 do i = 1, n_mappings
348 call move_alloc(temp(i)%mapping, this%mapping_cascade(i)%mapping)
349 end do
350 end if
351
352 this%mapping_cascade(n_mappings + 1)%mapping = mapping
353
354 end subroutine mapping_handler_add_mapping
355
360 subroutine mapping_handler_make_cts(this, fld)
361 class(mapping_handler_t), intent(inout) :: this
362 type(field_t), intent(inout) :: fld
363
364 call this%coef%gs_h%op(fld, gs_op_add)
365 if (neko_bcknd_device .eq. 1) then
366 call device_col2(fld%x_d, this%coef%mult_d, fld%size())
367 else
368 call col2(fld%x, this%coef%mult, fld%size())
369 end if
370
371 end subroutine mapping_handler_make_cts
372end module mapping_handler
mapping factory. Both constructs and initializes the object.
Definition mapping.f90:138
Implements the mapping_handler_t type.
subroutine mapping_handler_init_base(this, coef)
Constructor.
Mappings to be applied to a scalar field.
Definition mapping.f90:36
Contains extensions to the neko library required to run the topology optimization code.
Definition neko_ext.f90:42
subroutine, public field_to_vector(vector, field)
Field to vector.
Definition neko_ext.f90:406
subroutine, public vector_to_field(field, vector)
Vector to field.
Definition neko_ext.f90:382
Base abstract class for mapping.
Definition mapping.f90:46
A helper type that is needed to have an array of polymorphic objects.
Definition mapping.f90:73
Abstract class for handling mapping_cascade.