38 use comm,
only: neko_comm
39 use utils,
only: neko_error
40 use num_types,
only: rp, dp
41 use,
intrinsic :: iso_fortran_env, only: error_unit
42 use rhs_maker,
only : rhs_maker_bdf_t, rhs_maker_ext_t, rhs_maker_oifs_t, &
43 rhs_maker_ext_fctry, rhs_maker_bdf_fctry, rhs_maker_oifs_fctry
45 use checkpoint_payload,
only : checkpoint_payload_t
46 use checkpoint,
only : chkp_t
47 use field,
only : field_t
48 use scalar_bc_projector,
only : scalar_bc_projector_t
49 use mesh,
only : mesh_t
50 use coefs,
only : coef_t
51 use device,
only : host_to_device, device_memcpy
52 use gather_scatter,
only : gs_t, gs_op_add
53 use scalar_residual,
only : scalar_residual_t, scalar_residual_factory
54 use ax_product,
only : ax_t, ax_helm_allocator
55 use field_series,
only: field_series_t
56 use facet_normal,
only : facet_normal_t
57 use krylov,
only : ksp_monitor_t
58 use device_math,
only : device_add2s2, device_col2
59 use time_scheme_controller,
only : time_scheme_controller_t
60 use projection,
only : projection_t
61 use math,
only : glsc2, col2, add2s2
62 use field_math,
only : field_col3, field_col2
63 use logger,
only : neko_log, log_size, neko_log_debug
65 use profiler,
only : profiler_start_region, profiler_end_region
66 use json_utils,
only : json_get, json_get_or_default, json_extract_item
67 use json_module,
only : json_file, json_core, json_value
68 use user_intf,
only : user_t
69 use neko_config,
only : neko_bcknd_device
70 use time_step_controller,
only : time_step_controller_t
71 use scratch_registry,
only : neko_scratch_registry
72 use time_state,
only : time_state_t
73 use bc,
only : bc_t, bc_dirichlet
74 use mpi_f08,
only: mpi_integer, mpi_sum, mpi_max
82 type(field_t) :: s_adj_res
85 type(field_t) :: ds_adj
88 class(ax_t),
allocatable :: ax
91 type(projection_t) :: proj_s
94 type(scalar_bc_projector_t) :: bc_projector
103 type(field_t) :: advs
106 class(scalar_residual_t),
allocatable :: res
109 class(rhs_maker_ext_t),
allocatable :: makeext
112 class(rhs_maker_bdf_t),
allocatable :: makebdf
115 class(rhs_maker_oifs_t),
allocatable :: makeoifs
119 procedure, pass(this) :: init => adjoint_scalar_pnpn_init
121 procedure, pass(this) :: register_checkpoint => &
122 adjoint_scalar_pnpn_register_checkpoint
124 procedure, pass(this) :: restart => adjoint_scalar_pnpn_restart
126 procedure, pass(this) :: free => adjoint_scalar_pnpn_free
128 procedure, pass(this) :: step => adjoint_scalar_pnpn_step
130 procedure, pass(this) :: setup_bcs_ => adjoint_scalar_pnpn_setup_bcs_
140 module subroutine adjoint_bc_factory(object, scheme, json, coef, user)
141 class(bc_t),
pointer,
intent(inout) :: object
142 type(adjoint_scalar_pnpn_t),
intent(in) :: scheme
143 type(json_file),
intent(inout) :: json
144 type(coef_t),
target,
intent(in) :: coef
145 type(user_t),
target,
intent(in) :: user
146 end subroutine adjoint_bc_factory
147 end interface adjoint_bc_factory
167 subroutine adjoint_scalar_pnpn_init(this, msh, coef, gs, params_adjoint, &
168 params_primal, numerics_params, user, chkp, ulag, vlag, wlag, &
170 class(adjoint_scalar_pnpn_t),
target,
intent(inout) :: this
171 type(mesh_t),
target,
intent(in) :: msh
172 type(coef_t),
target,
intent(in) :: coef
173 type(gs_t),
target,
intent(inout) :: gs
174 type(json_file),
target,
intent(inout) :: params_adjoint
175 type(json_file),
target,
intent(inout) :: params_primal
176 type(json_file),
target,
intent(inout) :: numerics_params
177 type(user_t),
target,
intent(in) :: user
178 type(chkp_t),
target,
intent(inout) :: chkp
179 type(field_series_t),
target,
intent(in) :: ulag, vlag, wlag
180 type(time_scheme_controller_t),
target,
intent(in) :: time_scheme
181 type(field_t),
target,
intent(in) :: rho
183 class(bc_t),
pointer :: bc_i
184 character(len=15),
parameter :: scheme =
'Modular (Pn/Pn)'
186 real(kind=dp),
pointer :: tlag(:), dtlag(:)
191 call this%scheme_init(msh, coef, gs, params_adjoint, params_primal, &
195 call ax_helm_allocator(this%ax, type_name =
"standard")
198 call scalar_residual_factory(this%res)
201 call rhs_maker_ext_fctry(this%makeext)
204 call rhs_maker_bdf_fctry(this%makebdf)
207 call rhs_maker_oifs_fctry(this%makeoifs)
210 associate(xh_lx => this%Xh%lx, xh_ly => this%Xh%ly, xh_lz => this%Xh%lz, &
211 dm_xh => this%dm_Xh, nelv => this%msh%nelv)
213 call this%s_adj_res%init(dm_xh,
"s_adj_res")
215 call this%abx1%init(dm_xh,
"abx1")
217 call this%abx2%init(dm_xh,
"abx2")
219 call this%advs%init(dm_xh,
"advs")
221 call this%ds_adj%init(dm_xh,
'ds_adj')
226 call this%setup_bcs_(user)
229 do i = 1, this%bcs%size()
230 if (this%bcs%bc_type(i) .eq. bc_dirichlet)
then
231 bc_i => this%bcs%get(i)
232 call this%bc_projector%mark(bc_i)
238 call this%proj_s%init(this%dm_Xh%size(), this%projection_dim, &
239 this%projection_activ_step)
242 call json_get_or_default(numerics_params,
'oifs', this%oifs, .false.)
248 call json_get_or_default(params_adjoint,
'advection', advection, .true.)
250 call chkp%get_time_history(tlag, dtlag)
251 call advection_adjoint_factory(this%adv, numerics_params, this%c_Xh, &
252 ulag, vlag, wlag, dtlag, &
253 tlag, time_scheme, .not. advection, &
255 end subroutine adjoint_scalar_pnpn_init
258 subroutine adjoint_scalar_pnpn_register_checkpoint(this, chkp)
259 class(adjoint_scalar_pnpn_t),
target,
intent(inout) :: this
260 type(chkp_t),
intent(inout) :: chkp
261 type(checkpoint_payload_t),
pointer :: payload
263 payload => chkp%add_payload(
"adjoint_scalars/" // trim(this%name))
264 call payload%add_field(this%s_adj)
265 call payload%add_series(this%s_adj_lag)
266 call payload%add_field(this%abx1)
267 call payload%add_field(this%abx2)
269 end subroutine adjoint_scalar_pnpn_register_checkpoint
272 subroutine adjoint_scalar_pnpn_restart(this, chkp)
273 class(adjoint_scalar_pnpn_t),
target,
intent(inout) :: this
274 type(chkp_t),
intent(inout) :: chkp
275 logical :: interpolated
278 n = this%s_adj%dof%size()
289 interpolated =
allocated(chkp%previous_mesh%elements) .or. &
290 chkp%previous_Xh%lx .ne. this%Xh%lx
292 if (interpolated)
then
293 call col2(this%s_adj%x, this%c_Xh%mult, n)
294 call col2(this%s_adj_lag%lf(1)%x, this%c_Xh%mult, n)
295 call col2(this%s_adj_lag%lf(2)%x, this%c_Xh%mult, n)
297 if (neko_bcknd_device .eq. 1)
then
298 call device_memcpy(this%s_adj%x, this%s_adj%x_d, &
299 n, host_to_device, sync = .false.)
300 call device_memcpy(this%s_adj_lag%lf(1)%x, this%s_adj_lag%lf(1)%x_d, &
301 n, host_to_device, sync = .false.)
302 call device_memcpy(this%s_adj_lag%lf(2)%x, this%s_adj_lag%lf(2)%x_d, &
303 n, host_to_device, sync = .false.)
304 call device_memcpy(this%abx1%x, this%abx1%x_d, &
305 n, host_to_device, sync = .false.)
306 call device_memcpy(this%abx2%x, this%abx2%x_d, &
307 n, host_to_device, sync = .false.)
308 call device_memcpy(this%advs%x, this%advs%x_d, &
309 n, host_to_device, sync = .false.)
312 if (interpolated)
then
313 call this%gs_Xh%op(this%s_adj, gs_op_add)
314 call this%gs_Xh%op(this%s_adj_lag%lf(1), gs_op_add)
315 call this%gs_Xh%op(this%s_adj_lag%lf(2), gs_op_add)
318 end subroutine adjoint_scalar_pnpn_restart
320 subroutine adjoint_scalar_pnpn_free(this)
321 class(adjoint_scalar_pnpn_t),
intent(inout) :: this
324 call this%scheme_free()
326 call this%bc_projector%free()
327 call this%proj_s%free()
329 call this%s_adj_res%free()
331 call this%ds_adj%free()
333 call this%abx1%free()
334 call this%abx2%free()
336 call this%advs%free()
338 if (
allocated(this%Ax))
then
342 if (
allocated(this%res))
then
346 if (
allocated(this%makeext))
then
347 deallocate(this%makeext)
350 if (
allocated(this%makebdf))
then
351 deallocate(this%makebdf)
354 if (
allocated(this%makeoifs))
then
355 deallocate(this%makeoifs)
358 end subroutine adjoint_scalar_pnpn_free
360 subroutine adjoint_scalar_pnpn_step(this, time, ext_bdf, dt_controller, &
362 class(adjoint_scalar_pnpn_t),
intent(inout) :: this
363 type(time_state_t),
intent(in) :: time
364 type(time_scheme_controller_t),
intent(in) :: ext_bdf
365 type(time_step_controller_t),
intent(in) :: dt_controller
366 type(ksp_monitor_t),
intent(inout) :: ksp_results
367 type(field_t),
pointer :: rho_cp
368 integer :: rho_cp_index
372 if (this%freeze)
return
374 n = this%dm_Xh%size()
375 call neko_scratch_registry%request_field(rho_cp, rho_cp_index, .false.)
377 call profiler_start_region(
'Adjoint Scalar')
378 associate(u => this%u, v => this%v, w => this%w, s_adj => this%s_adj, &
379 cp => this%cp, rho => this%rho, lambda => this%lambda, &
380 ds_adj => this%ds_adj, &
381 s_adj_res => this%s_adj_res, &
382 ax => this%Ax, f_xh => this%f_Xh, xh => this%Xh, &
383 c_xh => this%c_Xh, dm_xh => this%dm_Xh, gs_xh => this%gs_Xh, &
384 s_adj_lag => this%s_adj_lag, oifs => this%oifs, &
385 projection_dim => this%projection_dim, &
386 msh => this%msh, res => this%res, makeoifs => this%makeoifs, &
387 makeext => this%makeext, makebdf => this%makebdf, &
388 t => time%t, tstep => time%tstep, dt => time%dt)
391 call print_debug(this)
400 call this%update_material_properties(time)
401 call field_col3(rho_cp, rho, cp)
404 call this%source_term%compute(time, extrapolate = .true.)
418 call this%adv%compute_adjoint_scalar(u, v, w, s_adj, f_xh, &
419 xh, this%c_Xh, dm_xh%size())
426 call field_col2(f_xh, rho_cp)
429 call this%bcs%apply_scalar(this%f_Xh%x, dm_xh%size(), time, .false.)
436 call makeext%compute_scalar(this%abx1, this%abx2, f_xh%x, &
437 ext_bdf%advection_coeffs%x, n)
440 call makebdf%compute_scalar(s_adj_lag, f_xh%x, s_adj, c_xh%B, &
441 rho_cp, dt, ext_bdf%diffusion_coeffs%x, ext_bdf%ndiff, n)
447 call this%source_term%compute(time, extrapolate = .false., &
450 call s_adj_lag%update()
453 call this%bcs%apply_scalar(this%s_adj%x, this%dm_Xh%size(), time, &
457 call profiler_start_region(
'Adjoint_scalar_residual')
458 call res%compute(ax, s_adj, s_adj_res, f_xh, c_xh, msh, xh, &
459 lambda, rho_cp, ext_bdf%diffusion_coeffs%x(1), &
462 call gs_xh%op(s_adj_res, gs_op_add)
466 call this%bc_projector%apply(s_adj_res%x, dm_xh%size())
468 call profiler_end_region(
'Adjoint_scalar_residual')
470 call this%proj_s%pre_solving(s_adj_res%x, tstep, c_xh, n, dt_controller)
472 call this%pc%update()
473 call profiler_start_region(
'Adjoint_scalar_solve')
474 ksp_results = this%ksp%solve(ax, ds_adj, s_adj_res%x, n, &
475 c_xh, this%bc_projector, gs_xh)
476 call profiler_end_region(
'Adjoint_scalar_solve')
478 ksp_results%name =
'Adjoint Scalar'
480 call this%proj_s%post_solving(ds_adj%x, ax, c_xh, this%bc_projector, &
481 gs_xh, n, tstep, dt_controller)
484 if (neko_bcknd_device .eq. 1)
then
485 call device_add2s2(s_adj%x_d, ds_adj%x_d, 1.0_rp, n)
487 call add2s2(s_adj%x, ds_adj%x, 1.0_rp, n)
491 call neko_scratch_registry%relinquish_field(rho_cp_index)
492 call profiler_end_region(
'Adjoint Scalar')
493 end subroutine adjoint_scalar_pnpn_step
495 subroutine print_debug(this)
496 class(adjoint_scalar_pnpn_t),
intent(inout) :: this
500 n = this%dm_Xh%size()
511 end subroutine print_debug
516 subroutine adjoint_scalar_pnpn_setup_bcs_(this, user)
517 class(adjoint_scalar_pnpn_t),
target,
intent(inout) :: this
518 type(user_t),
target,
intent(in) :: user
519 integer :: i, j, n_bcs, zone_size, global_zone_size, ierr
520 type(json_core) :: core
521 type(json_value),
pointer :: bc_object
522 type(json_file) :: bc_subdict
523 class(bc_t),
pointer :: bc_i
526 logical,
allocatable :: marked_zones(:)
527 integer,
allocatable :: zone_indices(:)
529 if (this%params%valid_path(
'boundary_conditions'))
then
530 call this%params%info(
'boundary_conditions', &
532 call this%params%get_core(core)
533 call this%params%get(
'boundary_conditions', bc_object, found)
535 call this%bcs%init(n_bcs)
537 allocate(marked_zones(
size(this%msh%labeled_zones)))
538 marked_zones = .false.
542 call json_extract_item(core, bc_object, i, bc_subdict)
547 call json_get(bc_subdict,
"zone_indices", zone_indices)
549 do j = 1,
size(zone_indices)
550 zone_size = this%msh%labeled_zones(zone_indices(j))%size
551 call mpi_allreduce(zone_size, global_zone_size, 1, &
552 mpi_integer, mpi_max, neko_comm, ierr)
554 if (global_zone_size .eq. 0)
then
555 write(error_unit,
'(A, A, I0, A, A, I0, A)')
"*** ERROR ***: ",&
556 "Zone index ", zone_indices(j), &
557 " is invalid as this zone has 0 size, meaning it ", &
558 "does not exist in the mesh. Check adjoint scalar BC ", &
563 if (marked_zones(zone_indices(j)) .eqv. .true.)
then
564 write(error_unit,
'(A, A, I0, A, A, A, A)')
"*** ERROR ***: ", &
565 "Zone with index ", zone_indices(j), &
566 " has already been assigned a boundary condition. ", &
567 "Please check your boundary_conditions entry for the ", &
568 "adjoint scalar and make sure that each zone index ", &
569 "appears only in a single boundary condition."
572 marked_zones(zone_indices(j)) = .true.
578 call adjoint_bc_factory(bc_i, this, bc_subdict, this%c_Xh, user)
579 call this%bcs%append(bc_i)
583 do i = 1,
size(this%msh%labeled_zones)
584 if ((this%msh%labeled_zones(i)%size .gt. 0) .and. &
585 (marked_zones(i) .eqv. .false.))
then
586 write(error_unit,
'(A, A, I0)')
"*** ERROR ***: ", &
587 "No adjoint scalar boundary condition assigned to zone ", i
593 do i = 1,
size(this%msh%labeled_zones)
594 if (this%msh%labeled_zones(i)%size .gt. 0)
then
595 write(error_unit,
'(A, A, A)')
"*** ERROR ***: ", &
596 "No boundary_conditions entry in the case file for " // &
597 " adjoint scalar ", &
603 end subroutine adjoint_scalar_pnpn_setup_bcs_
Boundary condition factory. Both constructs and initializes the object.
Contains the adjoint_scalar_pnpn_t type.
Contains the adjoint_scalar_scheme_t type.
Subroutines to add advection terms to the RHS of a transport equation.
Base type for a scalar advection-diffusion solver.
Base abstract type for computing the advection operator.