36 use gather_scatter,
only: gs_t, gs_op_min, gs_op_max
37 use mean_sqr_flow,
only: mean_sqr_flow_t
38 use neko_config,
only: neko_bcknd_device
39 use checkpoint,
only: chkp_t
40 use mean_flow,
only: mean_flow_t
41 use num_types,
only: rp, i8
42 use comm,
only: neko_comm
44 use field,
only: field_t
45 use space,
only: space_t, gll
46 use dofmap,
only: dofmap_t
47 use zero_dirichlet,
only: zero_dirichlet_t
48 use krylov,
only: ksp_t, krylov_solver_factory, ksp_max_iter
49 use coefs,
only: coef_t
50 use usr_inflow,
only: usr_inflow_t, usr_inflow_eval
51 use dirichlet,
only: dirichlet_t
52 use field_dirichlet,
only: field_dirichlet_t
53 use field_dirichlet_vector,
only: field_dirichlet_vector_t
54 use jacobi,
only: jacobi_t
55 use sx_jacobi,
only: sx_jacobi_t
56 use device_jacobi,
only: device_jacobi_t
57 use hsmg,
only: hsmg_t
58 use phmg,
only: phmg_t
59 use precon,
only: pc_t, precon_factory, precon_destroy
60 use fluid_stats,
only: fluid_stats_t
62 use bc_list,
only: bc_list_t
63 use mesh,
only: mesh_t, neko_msh_max_zlbls, neko_msh_max_zlbl_len
64 use math,
only: cfill, add2s2, glsum
65 use device_math,
only: device_cfill, device_add2s2
66 use time_scheme_controller,
only: time_scheme_controller_t
67 use operators,
only: cfl
68 use logger,
only: neko_log, log_size, neko_log_verbose
69 use field_registry,
only: neko_field_registry
70 use json_utils,
only: json_get, json_get_or_default, json_extract_object, &
72 use json_module,
only: json_file, json_core, json_value
73 use scratch_registry,
only: scratch_registry_t
74 use user_intf,
only: user_t, dummy_user_material_properties, &
75 user_material_properties
76 use utils,
only: neko_error, neko_warning
77 use field_series,
only: field_series_t
78 use time_step_controller,
only: time_step_controller_t
79 use field_math,
only: field_cfill, field_add2s2
80 use wall_model_bc,
only: wall_model_bc_t
81 use shear_stress,
only: shear_stress_t
82 use field_list,
only : field_list_t
83 use gradient_jump_penalty,
only: gradient_jump_penalty_t
84 use field_math,
only: field_addcol3
86 use mpi_f08,
only: mpi_integer, mpi_sum, mpi_allreduce
88 use device,
only : device_event_sync, glb_cmd_event, device_to_host, &
98 class(ksp_t),
allocatable :: ksp_vel
99 class(ksp_t),
allocatable :: ksp_prs
100 class(pc_t),
allocatable :: pc_vel
101 class(pc_t),
allocatable :: pc_prs
102 integer :: vel_projection_dim
103 integer :: pr_projection_dim
104 integer :: vel_projection_activ_step
105 integer :: pr_projection_activ_step
106 logical :: strict_convergence
109 type(field_t),
pointer :: u_adj_e => null()
110 type(field_t),
pointer :: v_adj_e => null()
111 type(field_t),
pointer :: w_adj_e => null()
113 type(mean_flow_t) :: mean
114 type(fluid_stats_t) :: stats
115 type(mean_sqr_flow_t) :: mean_sqr
116 logical :: forced_flow_rate = .false.
119 character(len=:),
allocatable :: nut_field_name
122 integer(kind=i8) :: glb_n_points
124 integer(kind=i8) :: glb_unique_points
125 type(scratch_registry_t) :: scratch
128 procedure, pass(this) :: init_base => adjoint_fluid_scheme_init_base
129 procedure, pass(this) :: scheme_free => adjoint_fluid_scheme_free
131 procedure, pass(this) :: validate => adjoint_fluid_scheme_validate
133 procedure, pass(this) :: bc_apply_vel => adjoint_fluid_scheme_bc_apply_vel
135 procedure, pass(this) :: bc_apply_prs => adjoint_fluid_scheme_bc_apply_prs
137 procedure, pass(this) :: compute_cfl => adjoint_compute_cfl
139 procedure, pass(this) :: set_material_properties => &
140 adjoint_fluid_scheme_set_material_properties
143 procedure, pass(this) :: update_material_properties => &
144 adjoint_fluid_scheme_update_material_properties
146 procedure,
nopass :: solver_factory => adjoint_fluid_scheme_solver_factory
148 procedure, pass(this) :: precon_factory_ => &
149 adjoint_fluid_scheme_precon_factory
154 module subroutine adjoint_fluid_scheme_factory(object, type_name)
156 character(len=*) :: type_name
157 end subroutine adjoint_fluid_scheme_factory
160 public :: adjoint_fluid_scheme_incompressible_t, adjoint_fluid_scheme_factory
165 subroutine adjoint_fluid_scheme_init_base(this, msh, lx, params, scheme, &
167 class(adjoint_fluid_scheme_incompressible_t),
target,
intent(inout) :: this
168 type(mesh_t),
target,
intent(inout) :: msh
169 integer,
intent(in) :: lx
170 character(len=*),
intent(in) :: scheme
171 type(json_file),
target,
intent(inout) :: params
172 type(user_t),
target,
intent(in) :: user
173 logical,
intent(in) :: kspv_init
174 character(len=LOG_SIZE) :: log_buf
175 real(kind=rp) :: real_val
176 logical :: logical_val
177 integer :: integer_val
178 character(len=:),
allocatable :: string_val1, string_val2
179 character(len=:),
allocatable :: json_key
180 type(json_file) :: json_subdict
188 if (msh%gdim .eq. 2)
then
189 call this%Xh%init(gll, lx, lx)
191 call this%Xh%init(gll, lx, lx, lx)
194 call this%dm_Xh%init(msh, this%Xh)
196 call this%gs_Xh%init(this%dm_Xh)
198 call this%c_Xh%init(this%gs_Xh)
201 call this%scratch%init(this%dm_Xh, 10, 2)
204 call json_get_or_default(params,
'case.fluid.name', this%name,
"fluid")
210 call neko_log%section(
'Adjoint fluid')
211 write(log_buf,
'(A, A)')
'Type : ', trim(scheme)
212 call neko_log%message(log_buf)
213 write(log_buf,
'(A, A)')
'Name : ', trim(this%name)
214 call neko_log%message(log_buf)
217 call neko_field_registry%add_field(this%dm_Xh,
'u_adj')
218 call neko_field_registry%add_field(this%dm_Xh,
'v_adj')
219 call neko_field_registry%add_field(this%dm_Xh,
'w_adj')
220 this%u_adj => neko_field_registry%get_field(
'u_adj')
221 this%v_adj => neko_field_registry%get_field(
'v_adj')
222 this%w_adj => neko_field_registry%get_field(
'w_adj')
227 call this%set_material_properties(params, user)
231 'case.adjoint_fluid.velocity_solver.projection_space_size', &
232 'case.fluid.velocity_solver.projection_space_size')
233 call json_get_or_default(params, json_key, this%vel_projection_dim, 0)
235 'case.adjoint_fluid.pressure_solver.projection_space_size', &
236 'case.fluid.pressure_solver.projection_space_size')
237 call json_get_or_default(params, json_key, this%pr_projection_dim, 0)
240 'case.adjoint_fluid.velocity_solver.projection_hold_steps', &
241 'case.fluid.velocity_solver.projection_hold_steps')
242 call json_get_or_default(params, json_key, &
243 this%vel_projection_activ_step, 5)
245 'case.adjoint_fluid.pressure_solver.projection_hold_steps', &
246 'case.fluid.pressure_solver.projection_hold_steps')
247 call json_get_or_default(params, json_key, &
248 this%pr_projection_activ_step, 5)
252 call json_get_or_default(params, json_key, this%freeze, .false.)
261 if (params%valid_path(
"case.fluid.flow_rate_force"))
then
262 call neko_error(
'Flow rate forcing not yet implemented')
263 this%forced_flow_rate = .true.
268 write(log_buf,
'(A, I1)')
'Poly order : ', lx-1
269 else if (lx .ge. 10)
then
270 write(log_buf,
'(A, I2)')
'Poly order : ', lx-1
272 write(log_buf,
'(A, I3)')
'Poly order : ', lx-1
274 call neko_log%message(log_buf)
275 this%glb_n_points = int(this%msh%glb_nelv, i8)*int(this%Xh%lxyz, i8)
276 this%glb_unique_points = int(glsum(this%c_Xh%mult, this%dm_Xh%size()), i8)
278 write(log_buf,
'(A, I0)')
'GLL points : ', this%glb_n_points
279 call neko_log%message(log_buf)
280 write(log_buf,
'(A, I0)')
'Unique pts.: ', this%glb_unique_points
281 call neko_log%message(log_buf)
283 call json_get(params,
'case.numerics.dealias', logical_val)
284 write(log_buf,
'(A, L1)')
'Dealias : ', logical_val
285 call neko_log%message(log_buf)
287 call json_get_or_default(params,
'case.output_boundary', logical_val, &
289 write(log_buf,
'(A, L1)')
'Save bdry : ', logical_val
290 call neko_log%message(log_buf)
292 call json_get_or_default(params,
"case.fluid.full_stress_formulation", &
293 logical_val, .false.)
294 write(log_buf,
'(A, L1)')
'Full stress: ', logical_val
295 call neko_log%message(log_buf)
300 allocate(this%f_adj_x)
301 allocate(this%f_adj_y)
302 allocate(this%f_adj_z)
303 call this%f_adj_x%init(this%dm_Xh, fld_name =
"adjoint_rhs_x")
304 call this%f_adj_y%init(this%dm_Xh, fld_name =
"adjoint_rhs_y")
305 call this%f_adj_z%init(this%dm_Xh, fld_name =
"adjoint_rhs_z")
325 call neko_log%section(
"Adjoint Velocity solver")
328 'case.adjoint_fluid.velocity_solver.max_iterations', &
329 'case.fluid.velocity_solver.max_iterations')
330 call json_get_or_default(params, json_key, integer_val, ksp_max_iter)
333 'case.adjoint_fluid.velocity_solver.type', &
334 'case.fluid.velocity_solver.type')
335 call json_get(params, json_key, string_val1)
338 'case.adjoint_fluid.velocity_solver.preconditioner.type', &
339 'case.fluid.velocity_solver.preconditioner.type')
340 call json_get(params, json_key, string_val2)
343 'case.adjoint_fluid.velocity_solver.preconditioner', &
344 'case.fluid.velocity_solver.preconditioner')
345 call json_extract_object(params, json_key, json_subdict)
348 'case.adjoint_fluid.velocity_solver.absolute_tolerance', &
349 'case.fluid.velocity_solver.absolute_tolerance')
350 call json_get(params, json_key, real_val)
353 'case.adjoint_fluid.velocity_solver.monitor', &
354 'case.fluid.velocity_solver.monitor')
355 call json_get_or_default(params, json_key, logical_val, .false.)
357 call neko_log%message(
'Type : (' // trim(string_val1) // &
358 ', ' // trim(string_val2) //
')')
360 write(log_buf,
'(A,ES13.6)')
'Abs tol :', real_val
361 call neko_log%message(log_buf)
362 call this%solver_factory(this%ksp_vel, this%dm_Xh%size(), &
363 string_val1, integer_val, real_val, logical_val)
364 call this%precon_factory_(this%pc_vel, this%ksp_vel, &
365 this%c_Xh, this%dm_Xh, this%gs_Xh, this%bcs_vel, &
366 string_val2, json_subdict)
367 call neko_log%end_section()
371 call json_get_or_default(params,
'case.fluid.strict_convergence', &
372 this%strict_convergence, .false.)
375 call this%ulag%init(this%u_adj, 2)
376 call this%vlag%init(this%v_adj, 2)
377 call this%wlag%init(this%w_adj, 2)
379 call neko_field_registry%add_field(this%dm_Xh,
'u_adj_e')
380 call neko_field_registry%add_field(this%dm_Xh,
'v_adj_e')
381 call neko_field_registry%add_field(this%dm_Xh,
'w_adj_e')
382 this%u_adj_e => neko_field_registry%get_field(
'u_adj_e')
383 this%v_adj_e => neko_field_registry%get_field(
'v_adj_e')
384 this%w_adj_e => neko_field_registry%get_field(
'w_adj_e')
387 call this%source_term%init(this%f_adj_x, this%f_adj_y, this%f_adj_z, &
389 call this%source_term%add(params,
'case.adjoint_fluid.source_term')
391 call neko_log%end_section()
393 end subroutine adjoint_fluid_scheme_init_base
396 subroutine adjoint_fluid_scheme_free(this)
397 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
401 if (
allocated(this%ksp_vel))
then
402 call this%ksp_vel%free()
403 deallocate(this%ksp_vel)
406 if (
allocated(this%ksp_prs))
then
407 call this%ksp_prs%free()
408 deallocate(this%ksp_prs)
411 if (
allocated(this%pc_vel))
then
412 call precon_destroy(this%pc_vel)
413 deallocate(this%pc_vel)
416 if (
allocated(this%pc_prs))
then
417 call precon_destroy(this%pc_prs)
418 deallocate(this%pc_prs)
421 call this%source_term%free()
423 call this%gs_Xh%free()
425 call this%c_Xh%free()
427 call this%scratch%free()
434 nullify(this%u_adj_e)
435 nullify(this%v_adj_e)
436 nullify(this%w_adj_e)
438 call this%ulag%free()
439 call this%vlag%free()
440 call this%wlag%free()
443 if (
associated(this%f_adj_x))
then
444 call this%f_adj_x%free()
447 if (
associated(this%f_adj_y))
then
448 call this%f_adj_y%free()
451 if (
associated(this%f_adj_z))
then
452 call this%f_adj_z%free()
455 nullify(this%f_adj_x)
456 nullify(this%f_adj_y)
457 nullify(this%f_adj_z)
462 end subroutine adjoint_fluid_scheme_free
466 subroutine adjoint_fluid_scheme_validate(this)
467 class(adjoint_fluid_scheme_incompressible_t),
target,
intent(inout) :: this
470 if ((.not.
associated(this%u_adj)) .or. &
471 (.not.
associated(this%v_adj)) .or. &
472 (.not.
associated(this%w_adj)) .or. &
473 (.not.
associated(this%p_adj)))
then
474 call neko_error(
'Fields are not registered')
477 if ((.not.
allocated(this%u_adj%x)) .or. &
478 (.not.
allocated(this%v_adj%x)) .or. &
479 (.not.
allocated(this%w_adj%x)) .or. &
480 (.not.
allocated(this%p_adj%x)))
then
481 call neko_error(
'Fields are not allocated')
484 if (.not.
allocated(this%ksp_vel))
then
485 call neko_error(
'No Krylov solver for velocity defined')
488 if (.not.
allocated(this%ksp_prs))
then
489 call neko_error(
'No Krylov solver for pressure defined')
495 call this%chkp%init(this%u_adj, this%v_adj, this%w_adj, this%p_adj)
497 end subroutine adjoint_fluid_scheme_validate
503 subroutine adjoint_fluid_scheme_bc_apply_vel(this, t, tstep, strong)
504 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
505 real(kind=rp),
intent(in) :: t
506 integer,
intent(in) :: tstep
507 logical,
intent(in) :: strong
510 class(bc_t),
pointer :: b => null()
512 call this%bcs_vel%apply_vector(&
513 this%u_adj%x, this%v_adj%x, this%w_adj%x, this%dm_Xh%size(), &
515 call this%gs_Xh%op(this%u_adj, gs_op_min, glb_cmd_event)
516 call this%gs_Xh%op(this%v_adj, gs_op_min, glb_cmd_event)
517 call this%gs_Xh%op(this%w_adj, gs_op_min, glb_cmd_event)
518 call device_event_sync(glb_cmd_event)
520 call this%bcs_vel%apply_vector(&
521 this%u_adj%x, this%v_adj%x, this%w_adj%x, this%dm_Xh%size(), &
523 call this%gs_Xh%op(this%u_adj, gs_op_max, glb_cmd_event)
524 call this%gs_Xh%op(this%v_adj, gs_op_max, glb_cmd_event)
525 call this%gs_Xh%op(this%w_adj, gs_op_max, glb_cmd_event)
526 call device_event_sync(glb_cmd_event)
528 do i = 1, this%bcs_vel%size()
529 b => this%bcs_vel%get(i)
535 end subroutine adjoint_fluid_scheme_bc_apply_vel
539 subroutine adjoint_fluid_scheme_bc_apply_prs(this, t, tstep)
540 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
541 real(kind=rp),
intent(in) :: t
542 integer,
intent(in) :: tstep
545 class(bc_t),
pointer :: b => null()
547 call this%bcs_prs%apply(this%p_adj, t, tstep)
548 call this%gs_Xh%op(this%p_adj, gs_op_min, glb_cmd_event)
549 call device_event_sync(glb_cmd_event)
551 call this%bcs_prs%apply(this%p_adj, t, tstep)
552 call this%gs_Xh%op(this%p_adj, gs_op_max, glb_cmd_event)
553 call device_event_sync(glb_cmd_event)
555 do i = 1, this%bcs_prs%size()
556 b => this%bcs_prs%get(i)
561 end subroutine adjoint_fluid_scheme_bc_apply_prs
565 subroutine adjoint_fluid_scheme_solver_factory(ksp, n, solver, &
566 max_iter, abstol, monitor)
567 class(ksp_t),
allocatable,
target,
intent(inout) :: ksp
568 integer,
intent(in),
value :: n
569 character(len=*),
intent(in) :: solver
570 integer,
intent(in) :: max_iter
571 real(kind=rp),
intent(in) :: abstol
572 logical,
intent(in) :: monitor
574 call krylov_solver_factory(ksp, n, solver, max_iter, abstol, &
577 end subroutine adjoint_fluid_scheme_solver_factory
580 subroutine adjoint_fluid_scheme_precon_factory(this, pc, ksp, coef, dof, gs, &
581 bclst, pctype, pcparams)
582 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
583 class(pc_t),
allocatable,
target,
intent(inout) :: pc
584 class(ksp_t),
target,
intent(inout) :: ksp
585 type(coef_t),
target,
intent(in) :: coef
586 type(dofmap_t),
target,
intent(in) :: dof
587 type(gs_t),
target,
intent(inout) :: gs
588 type(bc_list_t),
target,
intent(inout) :: bclst
589 character(len=*) :: pctype
590 type(json_file),
intent(inout) :: pcparams
592 call precon_factory(pc, pctype)
594 select type (pcp => pc)
596 call pcp%init(coef, dof, gs)
597 type is (sx_jacobi_t)
598 call pcp%init(coef, dof, gs)
599 type is (device_jacobi_t)
600 call pcp%init(coef, dof, gs)
602 call pcp%init(coef, bclst, pcparams)
604 call pcp%init(coef, bclst, pcparams)
609 end subroutine adjoint_fluid_scheme_precon_factory
628 function adjoint_compute_cfl(this, dt)
result(c)
629 class(adjoint_fluid_scheme_incompressible_t),
intent(in) :: this
630 real(kind=rp),
intent(in) :: dt
633 c = cfl(dt, this%u_adj%x, this%v_adj%x, this%w_adj%x, &
634 this%Xh, this%c_Xh, this%msh%nelv, this%msh%gdim)
636 end function adjoint_compute_cfl
643 subroutine adjoint_fluid_scheme_update_material_properties(this, t, tstep)
644 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
645 real(kind=rp),
intent(in) :: t
646 integer,
intent(in) :: tstep
647 type(field_t),
pointer :: nut
649 call this%user_material_properties(t, tstep, this%name, &
650 this%material_properties)
652 if (len(trim(this%nut_field_name)) > 0)
then
653 nut => neko_field_registry%get_field(this%nut_field_name)
654 call field_addcol3(this%mu, nut, this%rho)
661 if (neko_bcknd_device .eq. 1)
then
662 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
663 device_to_host, sync=.false.)
664 call device_memcpy(this%mu%x, this%mu%x_d, this%mu%size(), &
665 device_to_host, sync=.false.)
667 end subroutine adjoint_fluid_scheme_update_material_properties
673 subroutine adjoint_fluid_scheme_set_material_properties(this, params, user)
674 class(adjoint_fluid_scheme_incompressible_t),
intent(inout) :: this
675 type(json_file),
intent(inout) :: params
676 type(user_t),
target,
intent(in) :: user
677 character(len=LOG_SIZE) :: log_buf
679 procedure(user_material_properties),
pointer :: dummy_mp_ptr
680 real(kind=rp) :: const_mu, const_rho
683 dummy_mp_ptr => dummy_user_material_properties
685 call this%mu%init(this%dm_Xh,
"mu")
686 call this%rho%init(this%dm_Xh,
"rho")
687 call this%material_properties%init(2)
688 call this%material_properties%assign_to_field(1, this%rho)
689 call this%material_properties%assign_to_field(2, this%mu)
691 if (.not.
associated(user%material_properties, dummy_mp_ptr))
then
693 write(log_buf,
'(A)')
"Material properties must be set in the user&
695 call neko_log%message(log_buf)
696 this%user_material_properties => user%material_properties
698 call user%material_properties(0.0_rp, 0, this%name, &
699 this%material_properties)
702 this%user_material_properties => dummy_user_material_properties
704 if (params%valid_path(
'case.fluid.Re') .and. &
705 (params%valid_path(
'case.fluid.mu') .or. &
706 params%valid_path(
'case.fluid.rho')))
then
707 call neko_error(
"To set the material properties for the fluid, " // &
708 "either provide Re OR mu and rho in the case file.")
710 else if (params%valid_path(
'case.fluid.Re'))
then
712 write(log_buf,
'(A)')
'Non-dimensional fluid material properties &
714 call neko_log%message(log_buf, lvl = neko_log_verbose)
715 write(log_buf,
'(A)')
'Density will be set to 1, dynamic viscosity to&
717 call neko_log%message(log_buf, lvl = neko_log_verbose)
720 call json_get(params,
'case.fluid.Re', const_mu)
721 write(log_buf,
'(A)')
'Read non-dimensional material properties'
722 call neko_log%message(log_buf)
723 write(log_buf,
'(A,ES13.6)')
'Re :', const_mu
724 call neko_log%message(log_buf)
729 const_mu = 1.0_rp/const_mu
732 call json_get(params,
'case.fluid.mu', const_mu)
733 call json_get(params,
'case.fluid.rho', const_rho)
739 if (
associated(user%material_properties, dummy_mp_ptr))
then
741 call field_cfill(this%mu, const_mu)
742 call field_cfill(this%rho, const_rho)
745 write(log_buf,
'(A,ES13.6)')
'rho :', const_rho
746 call neko_log%message(log_buf)
747 write(log_buf,
'(A,ES13.6)')
'mu :', const_mu
748 call neko_log%message(log_buf)
755 if (neko_bcknd_device .eq. 1)
then
756 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
757 device_to_host, sync=.false.)
758 call device_memcpy(this%mu%x, this%mu%x_d, this%mu%size(), &
759 device_to_host, sync=.false.)
761 end subroutine adjoint_fluid_scheme_set_material_properties
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.