37 use neko_config,
only: neko_bcknd_device
38 use num_types,
only: rp, sp, dp
41 use field,
only: field_t
42 use field_output,
only: field_output_t
43 use json_utils,
only: json_extract_item
44 use json_module,
only: json_file
45 use coefs,
only: coef_t
46 use field_math,
only: field_copy
48 use device_math,
only: device_col2
49 use scratch_registry,
only: neko_scratch_registry
50 use utils,
only: neko_warning, neko_error
51 use vector,
only:vector_t
53 use gather_scatter,
only : gs_op_add
69 type(coef_t),
pointer :: coef
71 type(field_output_t) :: design_output
73 type(field_output_t) :: sensitivity_output
75 type(field_t),
pointer :: design_in => null()
76 type(field_t),
pointer :: design_out => null()
77 type(field_t),
pointer :: sensitivity_out => null()
79 type(field_t),
allocatable :: sensitivity_stages(:)
81 logical :: output_fields_set = .false.
82 logical :: outputs_initialized = .false.
84 logical :: verbose_design = .false.
86 logical :: verbose_sensitivity = .false.
88 integer :: output_precision = sp
90 character(len=32) :: output_format =
'fld'
92 character(len=80) :: forward_file_name =
''
94 character(len=80) :: sensitivity_file_name =
''
98 procedure, pass(this) :: init_base => mapping_handler_init_base
100 procedure, pass(this) :: free => mapping_handler_free
102 generic :: apply_forward => mapping_handler_apply_forward_field, &
103 mapping_handler_apply_forward_vector
104 procedure, pass(this) :: mapping_handler_apply_forward_field
105 procedure, pass(this) :: mapping_handler_apply_forward_vector
108 generic :: apply_backward => mapping_handler_apply_backward_field, &
109 mapping_handler_apply_backward_vector
110 procedure, pass(this) :: mapping_handler_apply_backward_field
111 procedure, pass(this) :: mapping_handler_apply_backward_vector
113 generic :: add => add_mapping, add_json_mappings
115 procedure, pass(this) :: add_mapping => &
116 mapping_handler_add_mapping
118 procedure, pass(this) :: add_json_mappings => &
119 mapping_handler_add_json_mappings
121 procedure, pass(this) :: set_stage_names => &
122 mapping_handler_set_stage_names
124 procedure, pass(this) :: make_cts => mapping_handler_make_cts
126 procedure, pass(this) :: init_output_fields => &
127 mapping_handler_init_output_fields
129 procedure, pass(this) :: write_design => mapping_handler_write_design
131 procedure, pass(this) :: write_sensitivity => &
132 mapping_handler_write_sensitivity
134 procedure, pass(this) :: set_output_counter => &
135 mapping_handler_set_output_counter
144 integer :: i, n_mappings, n_fields
146 if (.not. this%output_fields_set)
then
147 call neko_error(
'Mapping output fields have not been configured')
149 if (.not.
associated(this%coef))
then
150 call neko_error(
'Mapping handler coefficients are not initialized')
152 if (.not.
associated(this%design_out))
then
153 call neko_error(
'Mapped design output field is not associated')
155 if (.not.
associated(this%design_in))
then
156 call neko_error(
'Unmapped design input field is not associated')
158 if (.not.
associated(this%sensitivity_out))
then
159 call neko_error(
'Sensitivity output field is not associated')
163 if (
allocated(this%mapping_cascade)) n_mappings =
size(this%mapping_cascade)
165 if (this%verbose_design)
then
167 n_fields = n_mappings + 1
168 if (n_fields .le. 0) n_fields = 1
171 if (n_mappings .gt. 0)
then
178 call this%set_stage_names()
180 call this%design_output%init(trim(this%forward_file_name), n_fields, &
181 precision = this%output_precision, &
182 format = trim(this%output_format))
184 if (this%verbose_design)
then
186 call this%design_output%fields%assign_to_field(i, &
187 this%mapping_cascade(i)%mapping%X_in)
189 call this%design_output%fields%assign_to_field(n_fields, this%design_out)
190 else if (n_mappings .eq. 0)
then
191 call this%design_output%fields%assign_to_field(1, this%design_out)
193 call this%design_output%fields%assign_to_field(1, &
194 this%mapping_cascade(1)%mapping%X_in)
195 call this%design_output%fields%assign_to_field(2, this%design_out)
198 if (this%verbose_sensitivity)
then
200 n_fields = n_mappings + 2
201 allocate(this%sensitivity_stages(n_mappings + 1))
202 do i = 1, n_mappings + 1
203 call this%sensitivity_stages(i)%init(this%coef%dof)
205 call this%sensitivity_output%init( &
206 trim(this%sensitivity_file_name), n_fields, &
207 precision = this%output_precision, &
208 format = trim(this%output_format))
209 do i = 1, n_mappings + 1
210 call this%sensitivity_output%fields%assign_to_field(i, &
211 this%sensitivity_stages(i))
213 call this%sensitivity_output%fields%assign_to_field(n_fields, &
214 this%sensitivity_out)
216 call this%sensitivity_output%init( &
217 trim(this%sensitivity_file_name), 1, &
218 precision = this%output_precision, &
219 format = trim(this%output_format))
220 call this%sensitivity_output%fields%assign_to_field(1, &
221 this%sensitivity_out)
224 this%outputs_initialized = .true.
229 subroutine mapping_handler_init_base(this, coef)
231 type(coef_t),
target,
intent(in) :: coef
237 end subroutine mapping_handler_init_base
241 subroutine mapping_handler_free(this)
245 if (
allocated(this%mapping_cascade))
then
246 do i = 1,
size(this%mapping_cascade)
247 call this%mapping_cascade(i)%free()
249 deallocate(this%mapping_cascade)
251 if (
allocated(this%sensitivity_stages))
then
252 do i = 1,
size(this%sensitivity_stages)
253 call this%sensitivity_stages(i)%free()
255 deallocate(this%sensitivity_stages)
258 call this%design_output%free()
259 call this%sensitivity_output%free()
261 this%outputs_initialized = .false.
262 this%output_fields_set = .false.
263 this%output_precision = sp
264 this%output_format =
'fld'
265 this%forward_file_name =
''
266 this%sensitivity_file_name =
''
267 if (
associated(this%design_in))
nullify(this%design_in)
268 if (
associated(this%design_out))
nullify(this%design_out)
269 if (
associated(this%sensitivity_out))
nullify(this%sensitivity_out)
270 if (
associated(this%coef))
nullify(this%coef)
272 end subroutine mapping_handler_free
278 subroutine mapping_handler_apply_forward_field(this, X_out, X_in)
280 type(field_t),
intent(in) :: X_in
281 type(field_t),
intent(inout) :: X_out
283 type(field_t),
pointer :: tmp_fld_in, tmp_fld_out
284 integer :: temp_indices(2)
286 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
288 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
293 call field_copy(tmp_fld_out, x_in)
296 call this%make_cts(tmp_fld_out)
299 if (
allocated(this%mapping_cascade))
then
300 do i = 1,
size(this%mapping_cascade)
302 call field_copy(tmp_fld_in, tmp_fld_out)
304 call this%mapping_cascade(i)%mapping%apply_forward(tmp_fld_out, &
312 call field_copy(x_out, tmp_fld_out)
315 call neko_scratch_registry%relinquish_field(temp_indices)
317 end subroutine mapping_handler_apply_forward_field
323 subroutine mapping_handler_apply_forward_vector(this, X_out, X_in)
325 type(vector_t),
intent(in) :: X_in
326 type(vector_t),
intent(inout) :: X_out
327 type(field_t),
pointer :: tmp_fld_in, tmp_fld_out
328 integer :: temp_indices(2)
330 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
332 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
336 call mapping_handler_apply_forward_field(this, tmp_fld_out, tmp_fld_in)
340 call neko_scratch_registry%relinquish_field(temp_indices)
342 end subroutine mapping_handler_apply_forward_vector
350 subroutine mapping_handler_apply_backward_field(this, sens_out, sens_in)
352 type(field_t),
intent(inout) :: sens_out
353 type(field_t),
intent(in) :: sens_in
355 type(field_t),
pointer :: tmp_fld_in, tmp_fld_out
356 integer :: temp_indices(2)
358 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
360 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
365 call field_copy(tmp_fld_out, sens_in)
366 if (
allocated(this%sensitivity_stages))
then
367 call field_copy(this%sensitivity_stages(1), sens_in)
371 call this%make_cts(tmp_fld_out)
374 if (
allocated(this%mapping_cascade))
then
375 do i =
size(this%mapping_cascade), 1, -1
377 call field_copy(tmp_fld_in, tmp_fld_out)
382 call this%mapping_cascade(i)%mapping%apply_backward(tmp_fld_out, &
384 if (
allocated(this%sensitivity_stages))
then
385 call field_copy(this%sensitivity_stages( &
386 size(this%mapping_cascade) - i + 2), tmp_fld_out)
394 call field_copy(sens_out, tmp_fld_out)
397 call neko_scratch_registry%relinquish_field(temp_indices)
400 end subroutine mapping_handler_apply_backward_field
408 subroutine mapping_handler_apply_backward_vector(this, X_out, X_in)
410 type(vector_t),
intent(in) :: X_in
411 type(vector_t),
intent(inout) :: X_out
412 type(field_t),
pointer :: tmp_fld_in, tmp_fld_out
413 integer :: temp_indices(2)
415 call neko_scratch_registry%request_field(tmp_fld_in, temp_indices(1), &
417 call neko_scratch_registry%request_field(tmp_fld_out, temp_indices(2), &
421 call mapping_handler_apply_backward_field(this, tmp_fld_out, tmp_fld_in)
425 call neko_scratch_registry%relinquish_field(temp_indices)
427 end subroutine mapping_handler_apply_backward_vector
430 subroutine mapping_handler_add_json_mappings(this, json, name)
432 type(json_file),
intent(inout) :: json
433 character(len=*),
intent(in) :: name
438 type(json_file) :: mapping_subdict
439 integer :: n_mappings, i, i0
441 if (json%valid_path(name))
then
443 call json%info(name, n_children = n_mappings)
445 if (
allocated(this%mapping_cascade))
then
446 i0 =
size(this%mapping_cascade)
447 call move_alloc(this%mapping_cascade, temp)
448 allocate(this%mapping_cascade(i0 + n_mappings))
449 if (
allocated(temp))
then
451 call move_alloc(temp(i)%mapping, &
452 this%mapping_cascade(i)%mapping)
457 allocate(this%mapping_cascade(n_mappings))
462 call json_extract_item(json, name, i, mapping_subdict)
464 mapping_subdict, this%coef)
469 call neko_warning(
"No mappings selected")
472 end subroutine mapping_handler_add_json_mappings
477 subroutine mapping_handler_add_mapping(this, mapping)
482 integer :: n_mappings, i
484 if (
allocated(this%mapping_cascade))
then
485 n_mappings =
size(this%mapping_cascade)
490 call move_alloc(this%mapping_cascade, temp)
491 allocate(this%mapping_cascade(n_mappings + 1))
493 if (
allocated(temp))
then
495 call move_alloc(temp(i)%mapping, this%mapping_cascade(i)%mapping)
499 this%mapping_cascade(n_mappings + 1)%mapping =
mapping
502 end subroutine mapping_handler_add_mapping
505 pure function mapping_handler_derivative_name(field_name)
result(name)
506 character(len=*),
intent(in) :: field_name
507 character(len=80) :: name
509 name =
'dFd_' // trim(field_name)
511 end function mapping_handler_derivative_name
515 subroutine mapping_handler_set_stage_names(this)
518 character(len=80) :: previous_name, current_name
523 previous_name = trim(this%design_in%name)
524 if (
allocated(this%mapping_cascade))
then
525 do i = 1,
size(this%mapping_cascade)
526 current_name = trim(this%mapping_cascade(i)%mapping%fld_name)
527 this%mapping_cascade(i)%mapping%X_in%name = trim(previous_name)
528 previous_name = trim(current_name)
533 this%sensitivity_out%name = mapping_handler_derivative_name( &
535 if (
allocated(this%sensitivity_stages))
then
536 this%sensitivity_stages(1)%name = mapping_handler_derivative_name( &
537 this%design_out%name)
538 if (
allocated(this%mapping_cascade))
then
539 do i =
size(this%mapping_cascade), 1, -1
540 j =
size(this%mapping_cascade) - i + 2
541 this%sensitivity_stages(j)%name = &
542 mapping_handler_derivative_name( &
543 this%mapping_cascade(i)%mapping%X_in%name)
548 end subroutine mapping_handler_set_stage_names
561 subroutine mapping_handler_init_output_fields(this, design_in, design_out, &
562 sensitivity_out, verbose_design, verbose_sensitivity, &
563 output_precision, output_format, forward_file_name, &
564 sensitivity_file_name)
566 type(field_t),
target,
intent(inout) :: design_in
567 type(field_t),
target,
intent(inout) :: design_out
568 type(field_t),
target,
intent(inout) :: sensitivity_out
569 logical,
intent(in) :: verbose_design
570 logical,
intent(in) :: verbose_sensitivity
571 integer,
intent(in) :: output_precision
572 character(len=*),
intent(in) :: output_format
573 character(len=*),
intent(in) :: forward_file_name
574 character(len=*),
intent(in) :: sensitivity_file_name
576 this%design_in => design_in
577 this%design_out => design_out
578 this%sensitivity_out => sensitivity_out
579 this%verbose_design = verbose_design
580 this%verbose_sensitivity = verbose_sensitivity
581 if (output_precision .ne. sp .and. output_precision .ne. dp)
then
582 call neko_error(
'output_precision must be either sp or dp')
584 this%output_precision = output_precision
585 this%output_format = trim(output_format)
586 this%forward_file_name = trim(forward_file_name)
587 this%sensitivity_file_name = trim(sensitivity_file_name)
588 this%output_fields_set = .true.
592 end subroutine mapping_handler_init_output_fields
597 subroutine mapping_handler_write_design(this, idx)
599 integer,
intent(in) :: idx
601 if (.not. this%outputs_initialized)
then
602 call neko_error(
'Mapping design output is not initialized')
604 call this%design_output%sample(real(idx, kind=rp))
606 end subroutine mapping_handler_write_design
611 subroutine mapping_handler_write_sensitivity(this, idx)
613 integer,
intent(in) :: idx
615 if (.not. this%outputs_initialized)
then
616 call neko_error(
'Mapping sensitivity output is not initialized')
618 call this%sensitivity_output%sample(real(idx, kind=rp))
620 end subroutine mapping_handler_write_sensitivity
625 subroutine mapping_handler_set_output_counter(this, idx)
627 integer,
intent(in) :: idx
629 if (.not. this%outputs_initialized)
return
631 call this%design_output%set_counter(idx)
632 call this%sensitivity_output%set_counter(idx)
634 end subroutine mapping_handler_set_output_counter
640 subroutine mapping_handler_make_cts(this, fld)
642 type(field_t),
intent(inout) :: fld
644 call this%coef%gs_h%op(fld, gs_op_add)
645 if (neko_bcknd_device .eq. 1)
then
646 call device_col2(fld%x_d, this%coef%mult_d, fld%size())
648 call col2(fld%x, this%coef%mult, fld%size())
651 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.