38 use gather_scatter,
only: gs_t, gs_op_min, gs_op_max
39 use neko_config,
only: neko_bcknd_device
40 use num_types,
only: rp, dp, i8
42 use field,
only: field_t
43 use space,
only: space_t, gll, gl,
operator(.ne.)
44 use dofmap,
only: dofmap_t
45 use krylov,
only: ksp_t, krylov_solver_factory, ksp_max_iter
46 use coefs,
only: coef_t
47 use precon,
only: pc_t, precon_factory
48 use fluid_stats,
only: fluid_stats_t
50 use bc_list,
only: bc_list_t
51 use mesh,
only: mesh_t, neko_msh_max_zlbls, neko_msh_max_zlbl_len
52 use operators,
only: cfl
53 use logger,
only: neko_log, log_size, neko_log_verbose
54 use registry,
only: neko_registry
55 use json_utils,
only: json_get, json_get_or_default
56 use json_module,
only: json_file
57 use user_intf,
only: user_t, dummy_user_material_properties, &
58 user_material_properties_intf
59 use utils,
only: neko_error
60 use time_state,
only: time_state_t
63 use device_math,
only: device_cfill, device_add2s2
64 use field_math,
only: field_cfill, field_add2s2, field_addcol3
67 use device,
only : device_event_sync, glb_cmd_event, device_to_host, &
77 class(ksp_t),
allocatable :: ksp_vel
78 class(ksp_t),
allocatable :: ksp_prs
79 class(pc_t),
allocatable :: pc_vel
80 class(pc_t),
allocatable :: pc_prs
81 integer :: vel_projection_dim
82 integer :: pr_projection_dim
83 integer :: vel_projection_activ_step
84 integer :: pr_projection_activ_step
85 logical :: strict_convergence
88 type(field_t),
pointer :: u_adj_e => null()
89 type(field_t),
pointer :: v_adj_e => null()
90 type(field_t),
pointer :: w_adj_e => null()
92 type(fluid_stats_t) :: stats
93 logical :: forced_flow_rate = .false.
96 character(len=:),
allocatable :: nut_field_name
99 integer(kind=i8) :: glb_n_points
101 integer(kind=i8) :: glb_unique_points
105 procedure, pass(this) :: scheme_free => adjoint_fluid_scheme_free
107 procedure, pass(this) :: validate => adjoint_fluid_scheme_validate
109 procedure, pass(this) :: bc_apply_vel => adjoint_fluid_scheme_bc_apply_vel
111 procedure, pass(this) :: bc_apply_prs => adjoint_fluid_scheme_bc_apply_prs
113 procedure, pass(this) :: compute_cfl => adjoint_compute_cfl
115 procedure, pass(this) :: set_material_properties => &
116 adjoint_fluid_scheme_set_material_properties
119 procedure, pass(this) :: update_material_properties => &
120 adjoint_fluid_scheme_update_material_properties
122 procedure,
nopass :: solver_factory => adjoint_fluid_scheme_solver_factory
124 procedure, pass(this) :: precon_factory_ => &
125 adjoint_fluid_scheme_precon_factory
130 module subroutine adjoint_fluid_scheme_factory(object, type_name)
132 character(len=*) :: type_name
133 end subroutine adjoint_fluid_scheme_factory
136 public :: adjoint_fluid_scheme_incompressible_t, adjoint_fluid_scheme_factory
141 subroutine adjoint_fluid_scheme_init_base(this, msh, lx, params, scheme, &
143 class(adjoint_fluid_scheme_incompressible_t),
target,
intent(inout) :: this
144 type(mesh_t),
target,
intent(inout) :: msh
145 integer,
intent(in) :: lx
146 character(len=*),
intent(in) :: scheme
147 type(json_file),
target,
intent(inout) :: params
148 type(user_t),
target,
intent(in) :: user
149 logical,
intent(in) :: kspv_init
150 character(len=LOG_SIZE) :: log_buf
151 real(kind=rp) :: real_val
152 logical :: logical_val
153 integer :: integer_val
154 character(len=:),
allocatable :: string_val1, string_val2
155 character(len=:),
allocatable :: json_key
156 type(json_file) :: json_subdict
166 lxd = (3 * (lx + 1)) / 2
167 if (msh%gdim .eq. 2)
then
168 call this%Xh%init(gll, lx, lx)
170 call this%Xh%init(gll, lx, lx, lx)
172 call this%Xh_GL%init(gl, lxd, lxd, lxd)
177 call this%dm_Xh%init(msh, this%Xh)
178 call this%dm_Xh_GL%init(msh, this%Xh_GL)
180 call this%gs_Xh%init(this%dm_Xh)
181 call this%gs_Xh_GL%init(this%dm_Xh_GL)
183 call this%c_Xh%init(this%gs_Xh)
184 call this%c_Xh_GL%init(this%gs_Xh_GL)
186 call this%GLL_to_GL%init(this%Xh_GL, this%Xh)
189 call this%scratch_GL%init(5, 2, this%dm_Xh_GL)
192 call json_get_or_default(params,
'case.fluid.name', this%name,
"fluid")
198 call neko_log%section(
'Adjoint fluid')
199 write(log_buf,
'(A, A)')
'Type : ', trim(scheme)
200 call neko_log%message(log_buf)
201 write(log_buf,
'(A, A)')
'Name : ', trim(this%name)
202 call neko_log%message(log_buf)
205 call neko_registry%add_field(this%dm_Xh,
'u_adj')
206 call neko_registry%add_field(this%dm_Xh,
'v_adj')
207 call neko_registry%add_field(this%dm_Xh,
'w_adj')
208 this%u_adj => neko_registry%get_field(
'u_adj')
209 this%v_adj => neko_registry%get_field(
'v_adj')
210 this%w_adj => neko_registry%get_field(
'w_adj')
215 call this%set_material_properties(params, user)
219 'case.adjoint_fluid.velocity_solver.projection_space_size', &
220 'case.fluid.velocity_solver.projection_space_size')
221 call json_get_or_default(params, json_key, this%vel_projection_dim, 0)
223 'case.adjoint_fluid.pressure_solver.projection_space_size', &
224 'case.fluid.pressure_solver.projection_space_size')
225 call json_get_or_default(params, json_key, this%pr_projection_dim, 0)
228 'case.adjoint_fluid.velocity_solver.projection_hold_steps', &
229 'case.fluid.velocity_solver.projection_hold_steps')
230 call json_get_or_default(params, json_key, &
231 this%vel_projection_activ_step, 5)
233 'case.adjoint_fluid.pressure_solver.projection_hold_steps', &
234 'case.fluid.pressure_solver.projection_hold_steps')
235 call json_get_or_default(params, json_key, &
236 this%pr_projection_activ_step, 5)
240 call json_get_or_default(params, json_key, this%freeze, .false.)
249 if (params%valid_path(
"case.fluid.flow_rate_force"))
then
250 call neko_error(
'Flow rate forcing not yet implemented')
251 this%forced_flow_rate = .true.
256 write(log_buf,
'(A, I1)')
'Poly order : ', lx-1
257 else if (lx .ge. 10)
then
258 write(log_buf,
'(A, I2)')
'Poly order : ', lx-1
260 write(log_buf,
'(A, I3)')
'Poly order : ', lx-1
262 call neko_log%message(log_buf)
263 this%glb_n_points = int(this%msh%glb_nelv, i8)*int(this%Xh%lxyz, i8)
264 this%glb_unique_points = int(glsum(this%c_Xh%mult, this%dm_Xh%size()), i8)
266 write(log_buf,
'(A, I0)')
'GLL points : ', this%glb_n_points
267 call neko_log%message(log_buf)
268 write(log_buf,
'(A, I0)')
'Unique pts.: ', this%glb_unique_points
269 call neko_log%message(log_buf)
271 call json_get(params,
'case.numerics.dealias', logical_val)
272 write(log_buf,
'(A, L1)')
'Dealias : ', logical_val
273 call neko_log%message(log_buf)
275 call json_get_or_default(params,
'case.output_boundary', logical_val, &
277 write(log_buf,
'(A, L1)')
'Save bdry : ', logical_val
278 call neko_log%message(log_buf)
280 call json_get_or_default(params,
"case.fluid.full_stress_formulation", &
281 logical_val, .false.)
282 write(log_buf,
'(A, L1)')
'Full stress: ', logical_val
283 call neko_log%message(log_buf)
288 allocate(this%f_adj_x)
289 allocate(this%f_adj_y)
290 allocate(this%f_adj_z)
291 call this%f_adj_x%init(this%dm_Xh, fld_name =
"adjoint_rhs_x")
292 call this%f_adj_y%init(this%dm_Xh, fld_name =
"adjoint_rhs_y")
293 call this%f_adj_z%init(this%dm_Xh, fld_name =
"adjoint_rhs_z")
313 call neko_log%section(
"Adjoint Velocity solver")
316 'case.adjoint_fluid.velocity_solver.max_iterations', &
317 'case.fluid.velocity_solver.max_iterations')
318 call json_get_or_default(params, json_key, integer_val, ksp_max_iter)
321 'case.adjoint_fluid.velocity_solver.type', &
322 'case.fluid.velocity_solver.type')
323 call json_get(params, json_key, string_val1)
326 'case.adjoint_fluid.velocity_solver.preconditioner.type', &
327 'case.fluid.velocity_solver.preconditioner.type')
328 call json_get(params, json_key, string_val2)
331 'case.adjoint_fluid.velocity_solver.preconditioner', &
332 'case.fluid.velocity_solver.preconditioner')
333 call json_get(params, json_key, json_subdict)
336 'case.adjoint_fluid.velocity_solver.absolute_tolerance', &
337 'case.fluid.velocity_solver.absolute_tolerance')
338 call json_get(params, json_key, real_val)
341 'case.adjoint_fluid.velocity_solver.monitor', &
342 'case.fluid.velocity_solver.monitor')
343 call json_get_or_default(params, json_key, logical_val, .false.)
345 call neko_log%message(
'Type : (' // trim(string_val1) // &
346 ', ' // trim(string_val2) //
')')
348 write(log_buf,
'(A,ES13.6)')
'Abs tol :', real_val
349 call neko_log%message(log_buf)
350 call this%solver_factory(this%ksp_vel, this%dm_Xh%size(), &
351 string_val1, integer_val, real_val, logical_val)
352 call this%precon_factory_(this%pc_vel, this%ksp_vel, &
353 this%c_Xh, this%bcs_vel, &
354 string_val2, json_subdict)
355 call neko_log%end_section()
359 call json_get_or_default(params,
'case.fluid.strict_convergence', &
360 this%strict_convergence, .false.)
363 call this%ulag%init(this%u_adj, 2)
364 call this%vlag%init(this%v_adj, 2)
365 call this%wlag%init(this%w_adj, 2)
367 call neko_registry%add_field(this%dm_Xh,
'u_adj_e')
368 call neko_registry%add_field(this%dm_Xh,
'v_adj_e')
369 call neko_registry%add_field(this%dm_Xh,
'w_adj_e')
370 this%u_adj_e => neko_registry%get_field(
'u_adj_e')
371 this%v_adj_e => neko_registry%get_field(
'v_adj_e')
372 this%w_adj_e => neko_registry%get_field(
'w_adj_e')
375 call this%source_term%init(this%f_adj_x, this%f_adj_y, this%f_adj_z, &
376 this%c_Xh, user, this%name)
377 call this%source_term%add(params,
'case.adjoint_fluid.source_term')
379 call neko_log%end_section()
381 end subroutine adjoint_fluid_scheme_init_base
384 subroutine adjoint_fluid_scheme_free(this)
385 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
386 class(bc_t),
pointer :: bc
391 if (
allocated(this%ksp_vel))
then
392 call this%ksp_vel%free()
393 deallocate(this%ksp_vel)
396 if (
allocated(this%ksp_prs))
then
397 call this%ksp_prs%free()
398 deallocate(this%ksp_prs)
401 if (
allocated(this%pc_vel))
then
402 call this%pc_vel%free()
403 deallocate(this%pc_vel)
406 if (
allocated(this%pc_prs))
then
407 call this%pc_prs%free()
408 deallocate(this%pc_prs)
411 do i = 1, this%bcs_vel%size()
412 bc => this%bcs_vel%get(i)
413 if (
associated(bc))
then
418 call this%bcs_vel%free()
420 do i = 1, this%bcs_prs%size()
421 bc => this%bcs_prs%get(i)
422 if (
associated(bc))
then
427 call this%bcs_prs%free()
429 call this%source_term%free()
431 call this%GLL_to_GL%free()
433 call this%gs_Xh%free()
435 call this%gs_Xh_GL%free()
437 call this%c_Xh%free()
439 call this%c_Xh_GL%free()
441 call this%scratch_GL%free()
448 nullify(this%u_adj_e)
449 nullify(this%v_adj_e)
450 nullify(this%w_adj_e)
452 call this%ulag%free()
453 call this%vlag%free()
454 call this%wlag%free()
457 if (
associated(this%f_adj_x))
then
458 call this%f_adj_x%free()
459 deallocate(this%f_adj_x)
462 if (
associated(this%f_adj_y))
then
463 call this%f_adj_y%free()
464 deallocate(this%f_adj_y)
467 if (
associated(this%f_adj_z))
then
468 call this%f_adj_z%free()
469 deallocate(this%f_adj_z)
472 nullify(this%f_adj_x)
473 nullify(this%f_adj_y)
474 nullify(this%f_adj_z)
478 call this%dm_Xh%free()
479 call this%dm_Xh_GL%free()
481 call this%Xh_GL%free()
486 end subroutine adjoint_fluid_scheme_free
490 subroutine adjoint_fluid_scheme_validate(this)
491 class(adjoint_fluid_scheme_incompressible_t),
target,
intent(inout) :: this
494 if ((.not.
associated(this%u_adj)) .or. &
495 (.not.
associated(this%v_adj)) .or. &
496 (.not.
associated(this%w_adj)) .or. &
497 (.not.
associated(this%p_adj)))
then
498 call neko_error(
'Fields are not registered')
501 if ((.not.
allocated(this%u_adj%x)) .or. &
502 (.not.
allocated(this%v_adj%x)) .or. &
503 (.not.
allocated(this%w_adj%x)) .or. &
504 (.not.
allocated(this%p_adj%x)))
then
505 call neko_error(
'Fields are not allocated')
508 if (this%u_adj%Xh .ne. this%v_adj%Xh .or. &
509 this%u_adj%Xh .ne. this%w_adj%Xh)
then
510 call neko_error(
'Different function spaces for velocity components')
513 if (this%u_adj%msh%nelv .ne. this%p_adj%msh%nelv)
then
514 call neko_error(
'Velocity and pressure defined on different meshes')
517 if (.not.
allocated(this%ksp_vel))
then
518 call neko_error(
'No Krylov solver for velocity defined')
521 if (.not.
allocated(this%ksp_prs))
then
522 call neko_error(
'No Krylov solver for pressure defined')
525 end subroutine adjoint_fluid_scheme_validate
531 subroutine adjoint_fluid_scheme_bc_apply_vel(this, time, strong)
532 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
533 type(time_state_t),
intent(in) :: time
534 logical,
intent(in) :: strong
537 class(bc_t),
pointer :: b => null()
539 call this%bcs_vel%apply_vector(&
540 this%u_adj%x, this%v_adj%x, this%w_adj%x, this%dm_Xh%size(), &
542 call this%gs_Xh%op(this%u_adj, gs_op_min, glb_cmd_event)
543 call this%gs_Xh%op(this%v_adj, gs_op_min, glb_cmd_event)
544 call this%gs_Xh%op(this%w_adj, gs_op_min, glb_cmd_event)
545 call device_event_sync(glb_cmd_event)
547 call this%bcs_vel%apply_vector(&
548 this%u_adj%x, this%v_adj%x, this%w_adj%x, this%dm_Xh%size(), &
550 call this%gs_Xh%op(this%u_adj, gs_op_max, glb_cmd_event)
551 call this%gs_Xh%op(this%v_adj, gs_op_max, glb_cmd_event)
552 call this%gs_Xh%op(this%w_adj, gs_op_max, glb_cmd_event)
553 call device_event_sync(glb_cmd_event)
555 do i = 1, this%bcs_vel%size()
556 b => this%bcs_vel%get(i)
562 end subroutine adjoint_fluid_scheme_bc_apply_vel
566 subroutine adjoint_fluid_scheme_bc_apply_prs(this, time)
567 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
568 type(time_state_t),
intent(in) :: time
571 class(bc_t),
pointer :: b => null()
573 call this%bcs_prs%apply(this%p_adj, time)
574 call this%gs_Xh%op(this%p_adj, gs_op_min, glb_cmd_event)
575 call device_event_sync(glb_cmd_event)
577 call this%bcs_prs%apply(this%p_adj, time)
578 call this%gs_Xh%op(this%p_adj, gs_op_max, glb_cmd_event)
579 call device_event_sync(glb_cmd_event)
581 do i = 1, this%bcs_prs%size()
582 b => this%bcs_prs%get(i)
587 end subroutine adjoint_fluid_scheme_bc_apply_prs
591 subroutine adjoint_fluid_scheme_solver_factory(ksp, n, solver, &
592 max_iter, abstol, monitor)
593 class(ksp_t),
allocatable,
target,
intent(inout) :: ksp
594 integer,
intent(in),
value :: n
595 character(len=*),
intent(in) :: solver
596 integer,
intent(in) :: max_iter
597 real(kind=rp),
intent(in) :: abstol
598 logical,
intent(in) :: monitor
600 call krylov_solver_factory(ksp, n, solver, max_iter, abstol, &
603 end subroutine adjoint_fluid_scheme_solver_factory
606 subroutine adjoint_fluid_scheme_precon_factory(this, pc, ksp, coef, &
608 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
609 class(pc_t),
allocatable,
target,
intent(inout) :: pc
610 class(ksp_t),
target,
intent(inout) :: ksp
611 type(coef_t),
target,
intent(in) :: coef
612 type(bc_list_t),
target,
intent(inout) :: bclst
613 character(len=*) :: pctype
614 type(json_file),
intent(inout) :: json
616 call precon_factory(pc, pctype, coef, bclst, json)
619 end subroutine adjoint_fluid_scheme_precon_factory
638 function adjoint_compute_cfl(this, dt)
result(c)
639 class(adjoint_fluid_scheme_incompressible_t),
intent(in) :: this
640 real(kind=dp),
intent(in) :: dt
643 c = cfl(dt, this%u_adj%x, this%v_adj%x, this%w_adj%x, &
644 this%Xh, this%c_Xh, this%msh%nelv, this%msh%gdim)
646 end function adjoint_compute_cfl
652 subroutine adjoint_fluid_scheme_update_material_properties(this, time)
653 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
654 type(time_state_t),
intent(in) :: time
655 type(field_t),
pointer :: nut
657 call this%user_material_properties(this%name, &
658 this%material_properties, time)
660 if (len(trim(this%nut_field_name)) > 0)
then
661 nut => neko_registry%get_field(this%nut_field_name)
662 call field_addcol3(this%mu, nut, this%rho)
669 if (neko_bcknd_device .eq. 1)
then
670 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
671 device_to_host, sync=.false.)
672 call device_memcpy(this%mu%x, this%mu%x_d, this%mu%size(), &
673 device_to_host, sync=.false.)
675 end subroutine adjoint_fluid_scheme_update_material_properties
681 subroutine adjoint_fluid_scheme_set_material_properties(this, params, user)
682 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
683 type(json_file),
intent(inout) :: params
684 type(user_t),
target,
intent(in) :: user
685 character(len=LOG_SIZE) :: log_buf
687 procedure(user_material_properties_intf),
pointer :: dummy_mp_ptr
688 real(kind=rp) :: const_mu, const_rho
689 type(time_state_t) :: time
692 dummy_mp_ptr => dummy_user_material_properties
694 call this%mu%init(this%dm_Xh,
"mu")
695 call this%rho%init(this%dm_Xh,
"rho")
696 call this%material_properties%init(2)
697 call this%material_properties%assign_to_field(1, this%rho)
698 call this%material_properties%assign_to_field(2, this%mu)
700 if (.not.
associated(user%material_properties, dummy_mp_ptr))
then
702 write(log_buf,
'(A)')
"Material properties must be set in the user&
704 call neko_log%message(log_buf)
705 this%user_material_properties => user%material_properties
707 call user%material_properties(this%name, &
708 this%material_properties, time)
711 this%user_material_properties => dummy_user_material_properties
713 if (params%valid_path(
'case.fluid.Re') .and. &
714 (params%valid_path(
'case.fluid.mu') .or. &
715 params%valid_path(
'case.fluid.rho')))
then
716 call neko_error(
"To set the material properties for the fluid, " // &
717 "either provide Re OR mu and rho in the case file.")
719 else if (params%valid_path(
'case.fluid.Re'))
then
721 write(log_buf,
'(A)')
'Non-dimensional fluid material properties &
723 call neko_log%message(log_buf, lvl = neko_log_verbose)
724 write(log_buf,
'(A)')
'Density will be set to 1, dynamic viscosity to&
726 call neko_log%message(log_buf, lvl = neko_log_verbose)
729 call json_get(params,
'case.fluid.Re', const_mu)
730 write(log_buf,
'(A)')
'Read non-dimensional material properties'
731 call neko_log%message(log_buf)
732 write(log_buf,
'(A,ES13.6)')
'Re :', const_mu
733 call neko_log%message(log_buf)
738 const_mu = 1.0_rp/const_mu
741 call json_get(params,
'case.fluid.mu', const_mu)
742 call json_get(params,
'case.fluid.rho', const_rho)
748 if (
associated(user%material_properties, dummy_mp_ptr))
then
750 call field_cfill(this%mu, const_mu)
751 call field_cfill(this%rho, const_rho)
754 write(log_buf,
'(A,ES13.6)')
'rho :', const_rho
755 call neko_log%message(log_buf)
756 write(log_buf,
'(A,ES13.6)')
'mu :', const_mu
757 call neko_log%message(log_buf)
764 if (neko_bcknd_device .eq. 1)
then
765 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
766 device_to_host, sync=.false.)
767 call device_memcpy(this%mu%x, this%mu%x_d, this%mu%size(), &
768 device_to_host, sync=.false.)
770 end subroutine adjoint_fluid_scheme_set_material_properties
subroutine adjoint_fluid_scheme_init_base(this, msh, lx, params, scheme, user, kspv_init)
Initialise an adjoint scheme.
Implements the adjoint_source_term_t type.
Base type of all fluid formulations.
Base type of all fluid formulations.
Wrapper contaning and executing the adjoint source terms.