37 use neko_config,
only: neko_bcknd_device
38 use num_types,
only: rp, sp, dp
41 use field,
only: field_t
42 use fld_file_output,
only: fld_file_output_t
43 use field_list,
only: field_list_t
44 use json_utils,
only: json_get, json_extract_item, json_get_or_default
45 use json_module,
only: json_file
46 use coefs,
only: coef_t
47 use user_intf,
only: user_t
48 use field_math,
only: field_rzero, field_copy
50 use device_math,
only: device_col2
51 use scratch_registry,
only: neko_scratch_registry
52 use utils,
only: neko_warning, neko_error
53 use vector,
only:vector_t
55 use gather_scatter,
only : gs_op_add
71 type(coef_t),
pointer :: coef
73 type(fld_file_output_t) :: design_output
75 type(fld_file_output_t) :: sensitivity_output
77 type(field_t),
pointer :: design_out => null()
78 type(field_t),
pointer :: sensitivity_out => null()
80 type(field_t),
allocatable :: sensitivity_stages(:)
82 logical :: output_fields_set = .false.
83 logical :: outputs_initialized = .false.
85 logical :: verbose_design = .false.
87 logical :: verbose_sensitivity = .false.
89 integer :: output_precision = sp
93 procedure, pass(this) :: init_base => mapping_handler_init_base
95 procedure, pass(this) :: free => mapping_handler_free
97 generic :: apply_forward => mapping_handler_apply_forward_field, &
98 mapping_handler_apply_forward_vector
99 procedure, pass(this) :: mapping_handler_apply_forward_field
100 procedure, pass(this) :: mapping_handler_apply_forward_vector
103 generic :: apply_backward => mapping_handler_apply_backward_field, &
104 mapping_handler_apply_backward_vector
105 procedure, pass(this) :: mapping_handler_apply_backward_field
106 procedure, pass(this) :: mapping_handler_apply_backward_vector
108 generic :: add => add_mapping, add_json_mappings
110 procedure, pass(this) :: add_mapping => &
111 mapping_handler_add_mapping
113 procedure, pass(this) :: add_json_mappings => &
114 mapping_handler_add_json_mappings
116 procedure, pass(this) :: make_cts => mapping_handler_make_cts
118 procedure, pass(this) :: init_output_fields => &
119 mapping_handler_init_output_fields
121 procedure, pass(this) :: write_design => mapping_handler_write_design
123 procedure, pass(this) :: write_sensitivity => &
124 mapping_handler_write_sensitivity
133 integer :: i, n_mappings, n_fields
135 if (.not. this%output_fields_set)
then
136 call neko_error(
'Mapping output fields have not been configured')
138 if (.not.
associated(this%coef))
then
139 call neko_error(
'Mapping handler coefficients are not initialized')
141 if (.not.
associated(this%design_out))
then
142 call neko_error(
'Mapped design output field is not associated')
144 if (.not.
associated(this%sensitivity_out))
then
145 call neko_error(
'Sensitivity output field is not associated')
148 call this%design_output%free()
149 call this%sensitivity_output%free()
151 if (
allocated(this%sensitivity_stages))
then
152 do i = 1,
size(this%sensitivity_stages)
153 call this%sensitivity_stages(i)%free()
155 deallocate(this%sensitivity_stages)
159 if (
allocated(this%mapping_cascade)) n_mappings =
size(this%mapping_cascade)
161 if (this%verbose_design)
then
163 n_fields = n_mappings + 1
164 if (n_fields .le. 0) n_fields = 1
167 if (n_mappings .gt. 0)
then
174 call this%design_output%init(this%output_precision,
'design', n_fields)
175 if (this%verbose_design .and. n_mappings .gt. 0)
then
177 call this%design_output%fields%assign_to_field(i, &
178 this%mapping_cascade(i)%mapping%X_in)
180 call this%design_output%fields%assign_to_field(n_fields, this%design_out)
181 else if (n_mappings .gt. 0)
then
182 call this%design_output%fields%assign_to_field(1, &
183 this%mapping_cascade(1)%mapping%X_in)
184 call this%design_output%fields%assign_to_field(2, this%design_out)
186 call this%design_output%fields%assign_to_field(1, this%design_out)
189 if (this%verbose_sensitivity)
then
191 n_fields = n_mappings + 2
192 allocate(this%sensitivity_stages(n_mappings + 1))
193 do i = 1, n_mappings + 1
194 call this%sensitivity_stages(i)%init(this%coef%dof)
197 call this%sensitivity_output%init(this%output_precision, &
198 'sensitivity', n_fields)
199 do i = 1, n_mappings + 1
200 call this%sensitivity_output%fields%assign_to_field(i, &
201 this%sensitivity_stages(i))
203 call this%sensitivity_output%fields%assign_to_field(n_fields, &
204 this%sensitivity_out)
206 call this%sensitivity_output%init(this%output_precision, &
208 call this%sensitivity_output%fields%assign_to_field(1, &
209 this%sensitivity_out)
212 this%outputs_initialized = .true.
217 subroutine mapping_handler_init_base(this, coef)
219 type(coef_t),
target,
intent(in) :: coef
225 end subroutine mapping_handler_init_base
229 subroutine mapping_handler_free(this)
233 if (
allocated(this%mapping_cascade))
then
234 do i = 1,
size(this%mapping_cascade)
235 call this%mapping_cascade(i)%free()
237 deallocate(this%mapping_cascade)
239 if (
allocated(this%sensitivity_stages))
then
240 do i = 1,
size(this%sensitivity_stages)
241 call this%sensitivity_stages(i)%free()
243 deallocate(this%sensitivity_stages)
245 if (this%outputs_initialized)
then
246 call this%design_output%free()
247 call this%sensitivity_output%free()
249 this%outputs_initialized = .false.
250 this%output_fields_set = .false.
251 this%output_precision = sp
252 if (
associated(this%design_out))
nullify(this%design_out)
253 if (
associated(this%sensitivity_out))
nullify(this%sensitivity_out)
254 if (
associated(this%coef))
nullify(this%coef)
256 end subroutine mapping_handler_free
262 subroutine mapping_handler_apply_forward_field(this, X_out, X_in)
264 type(field_t),
intent(in) :: X_in
265 type(field_t),
intent(inout) :: X_out
267 type(field_t),
pointer :: tmp_fld_in, tmp_fld_out
268 integer :: temp_indices(2)
270 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
272 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
277 call field_copy(tmp_fld_out, x_in)
280 call this%make_cts(tmp_fld_out)
283 if (
allocated(this%mapping_cascade))
then
284 do i = 1,
size(this%mapping_cascade)
286 call field_copy(tmp_fld_in, tmp_fld_out)
288 call this%mapping_cascade(i)%mapping%apply_forward(tmp_fld_out, &
296 call field_copy(x_out, tmp_fld_out)
299 call neko_scratch_registry%relinquish_field(temp_indices)
301 end subroutine mapping_handler_apply_forward_field
307 subroutine mapping_handler_apply_forward_vector(this, X_out, X_in)
309 type(vector_t),
intent(in) :: X_in
310 type(vector_t),
intent(inout) :: X_out
311 type(field_t),
pointer :: tmp_fld_in, tmp_fld_out
312 integer :: temp_indices(2)
314 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
316 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
320 call mapping_handler_apply_forward_field(this, tmp_fld_out, tmp_fld_in)
324 call neko_scratch_registry%relinquish_field(temp_indices)
326 end subroutine mapping_handler_apply_forward_vector
334 subroutine mapping_handler_apply_backward_field(this, sens_out, sens_in)
336 type(field_t),
intent(inout) :: sens_out
337 type(field_t),
intent(in) :: sens_in
339 type(field_t),
pointer :: tmp_fld_in, tmp_fld_out
340 integer :: temp_indices(2)
342 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
344 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
349 call field_copy(tmp_fld_out, sens_in)
350 if (
allocated(this%sensitivity_stages))
then
351 call field_copy(this%sensitivity_stages(1), sens_in)
355 call this%make_cts(tmp_fld_out)
358 if (
allocated(this%mapping_cascade))
then
359 do i =
size(this%mapping_cascade), 1, -1
361 call field_copy(tmp_fld_in, tmp_fld_out)
366 call this%mapping_cascade(i)%mapping%apply_backward(tmp_fld_out, &
368 if (
allocated(this%sensitivity_stages))
then
369 call field_copy(this%sensitivity_stages( &
370 size(this%mapping_cascade) - i + 2), tmp_fld_out)
378 if (neko_bcknd_device .eq. 1)
then
379 call device_col2(tmp_fld_out%x_d, this%coef%B_d, tmp_fld_out%size())
381 call col2(tmp_fld_out%x, this%coef%B, tmp_fld_out%size())
385 call field_copy(sens_out, tmp_fld_out)
388 call neko_scratch_registry%relinquish_field(temp_indices)
391 end subroutine mapping_handler_apply_backward_field
399 subroutine mapping_handler_apply_backward_vector(this, X_out, X_in)
401 type(vector_t),
intent(in) :: X_in
402 type(vector_t),
intent(inout) :: X_out
403 type(field_t),
pointer :: tmp_fld_in, tmp_fld_out
404 integer :: temp_indices(2)
406 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
408 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
412 call mapping_handler_apply_backward_field(this, tmp_fld_out, tmp_fld_in)
416 call neko_scratch_registry%relinquish_field(temp_indices)
418 end subroutine mapping_handler_apply_backward_vector
421 subroutine mapping_handler_add_json_mappings(this, json, name)
423 type(json_file),
intent(inout) :: json
424 character(len=*),
intent(in) :: name
429 type(json_file) :: mapping_subdict
430 integer :: n_mappings, i, i0
432 if (json%valid_path(name))
then
434 call json%info(name, n_children = n_mappings)
436 if (
allocated(this%mapping_cascade))
then
437 i0 =
size(this%mapping_cascade)
438 call move_alloc(this%mapping_cascade, temp)
439 allocate(this%mapping_cascade(i0 + n_mappings))
440 if (
allocated(temp))
then
442 call move_alloc(temp(i)%mapping, &
443 this%mapping_cascade(i)%mapping)
448 allocate(this%mapping_cascade(n_mappings))
453 call json_extract_item(json, name, i, mapping_subdict)
455 mapping_subdict, this%coef)
460 call neko_warning(
"No mappings selected")
463 end subroutine mapping_handler_add_json_mappings
468 subroutine mapping_handler_add_mapping(this, mapping)
473 integer :: n_mappings, i
475 if (
allocated(this%mapping_cascade))
then
476 n_mappings =
size(this%mapping_cascade)
481 call move_alloc(this%mapping_cascade, temp)
482 allocate(this%mapping_cascade(n_mappings + 1))
484 if (
allocated(temp))
then
486 call move_alloc(temp(i)%mapping, this%mapping_cascade(i)%mapping)
490 this%mapping_cascade(n_mappings + 1)%mapping =
mapping
493 end subroutine mapping_handler_add_mapping
502 subroutine mapping_handler_init_output_fields(this, design_out, &
503 sensitivity_out, verbose_design, verbose_sensitivity, output_precision)
505 type(field_t),
target,
intent(inout) :: design_out
506 type(field_t),
target,
intent(inout) :: sensitivity_out
507 logical,
intent(in),
optional :: verbose_design
508 logical,
intent(in),
optional :: verbose_sensitivity
509 integer,
intent(in),
optional :: output_precision
511 this%design_out => design_out
512 this%sensitivity_out => sensitivity_out
513 if (
present(verbose_design)) this%verbose_design = verbose_design
514 if (
present(verbose_sensitivity)) this%verbose_sensitivity = &
516 if (
present(output_precision))
then
517 if (output_precision .ne. sp .and. output_precision .ne. dp)
then
518 call neko_error(
'output_precision must be either sp or dp')
520 this%output_precision = output_precision
522 this%output_fields_set = .true.
526 end subroutine mapping_handler_init_output_fields
531 subroutine mapping_handler_write_design(this, idx)
533 integer,
intent(in) :: idx
535 if (.not. this%outputs_initialized)
then
536 call neko_error(
'Mapping design output is not initialized')
538 call this%design_output%sample(real(idx, kind=rp))
540 end subroutine mapping_handler_write_design
545 subroutine mapping_handler_write_sensitivity(this, idx)
547 integer,
intent(in) :: idx
549 if (.not. this%outputs_initialized)
then
550 call neko_error(
'Mapping sensitivity output is not initialized')
552 call this%sensitivity_output%sample(real(idx, kind=rp))
554 end subroutine mapping_handler_write_sensitivity
560 subroutine mapping_handler_make_cts(this, fld)
562 type(field_t),
intent(inout) :: fld
564 call this%coef%gs_h%op(fld, gs_op_add)
565 if (neko_bcknd_device .eq. 1)
then
566 call device_col2(fld%x_d, this%coef%mult_d, fld%size())
568 call col2(fld%x, this%coef%mult, fld%size())
571 end subroutine mapping_handler_make_cts
mapping factory. Both constructs and initializes the object.
Implements the mapping_handler_t type.
subroutine mapping_handler_setup_outputs(this)
Setup output objects after mappings are known.
Mappings to be applied to a scalar field.
Contains extensions to the neko library required to run the topology optimization code.
subroutine, public field_to_vector(vector, field)
Field to vector.
subroutine, public vector_to_field(field, vector)
Vector to field.
Base abstract class for mapping.
A helper type that is needed to have an array of polymorphic objects.
Abstract class for handling mapping_cascade.