38 use case,
only: case_t
39 use user_access_singleton,
only: neko_user_access
41 use fluid_scheme_incompressible,
only: fluid_scheme_incompressible_t
45 use scalars,
only: scalars_t
46 use fluid_pnpn,
only: fluid_pnpn_t
47 use time_step_controller,
only: time_step_controller_t
48 use field_output,
only: field_output_t
49 use simcomp_executor,
only: neko_simcomps
51 use json_file_module,
only: json_file
52 use json_utils,
only: json_get, json_get_or_default
53 use num_types,
only: rp, sp, dp
54 use mpi_f08,
only: mpi_wtime
55 use profiler,
only: profiler_start, profiler_stop, &
56 profiler_start_region, profiler_end_region
59 use simulation,
only: simulation_init, simulation_step, simulation_finalize, &
62 use runtime_stats,
only: neko_rt_stats
69 type(case_t),
public :: neko_case
73 class(fluid_scheme_incompressible_t),
public,
pointer :: fluid => null()
75 type(scalars_t),
public,
pointer :: scalars => null()
82 type(field_output_t),
public :: output_forward
85 type(field_output_t),
public :: output_adjoint
89 character(len=:),
allocatable :: forward_field_base_fname
93 character(len=:),
allocatable :: adjoint_field_base_fname
97 integer :: current_design_iteration = 0
99 logical :: unsteady = .false.
101 logical :: have_scalar = .false.
102 integer :: n_timesteps = 0
114 procedure, pass(this) :: free => simulation_free
116 procedure, pass(this) :: run_forward => simulation_run_forward
118 procedure, pass(this) :: run_backward => simulation_run_backward
120 procedure, pass(this) ::
reset => simulation_reset
122 procedure, pass(this) :: set_output_counter => &
123 simulation_set_output_counter
125 procedure, pass(this) :: set_design_iteration => &
126 simulation_set_design_iteration
128 procedure, pass(this) :: write => simulation_write
130 procedure, pass(this) :: write_forward => simulation_write_forward
132 procedure, pass(this) :: write_adjoint => simulation_write_adjoint
141 type(json_file),
intent(inout) :: parameters
142 type(json_file) :: state_recovery_params
143 integer :: i, n_scalars
144 character(len=:),
allocatable :: output_directory, precision_s, file_format
146 logical :: unsteady, subdivide
149 call this%neko_case%init(parameters)
150 call neko_user_access%init(this%neko_case)
152 call neko_rt_stats%init(parameters)
153 call neko_simcomps%init(this%neko_case)
156 call this%adjoint_case%init(this%neko_case)
160 this%forward_field_base_fname = &
161 trim(this%neko_case%f_out%file_%get_base_fname())
162 this%adjoint_field_base_fname = &
163 trim(this%adjoint_case%f_out%file_%get_base_fname())
168 select type (fluid => this%neko_case%fluid)
169 type is (fluid_pnpn_t)
173 select type (adjoint_fluid => this%adjoint_case%fluid_adj)
175 this%adjoint_fluid => adjoint_fluid
178 if (
allocated(this%neko_case%scalars))
then
179 this%scalars => this%neko_case%scalars
182 if (
allocated(this%adjoint_case%adjoint_scalars))
then
183 this%adjoint_scalars => this%adjoint_case%adjoint_scalars
190 call json_get_or_default(parameters,
'case.output_directory', &
191 output_directory,
'')
192 call json_get_or_default(parameters,
'case.output_precision', precision_s, &
194 call json_get_or_default(parameters,
'case.fluid.output_format', &
196 call json_get_or_default(parameters,
'case.fluid.output_subdivide', &
199 if (trim(precision_s) .eq.
'double')
then
207 if (
allocated(this%neko_case%scalars))
then
208 n_scalars =
size(this%neko_case%scalars%scalar_fields)
210 call this%output_forward%init(
'forward_fields', 4 + n_scalars, &
211 precision = precision, &
212 path = trim(output_directory), &
213 format = trim(file_format))
214 call this%output_forward%file_%set_subdivide(subdivide)
216 call this%output_forward%fields%assign(1, this%fluid%p)
217 call this%output_forward%fields%assign(2, this%fluid%u)
218 call this%output_forward%fields%assign(3, this%fluid%v)
219 call this%output_forward%fields%assign(4, this%fluid%w)
222 if (
allocated(this%neko_case%scalars))
then
224 call this%output_forward%fields%assign(4 + i, &
225 this%scalars%scalar_fields(i)%scalar%s)
230 call json_get_or_default(parameters, &
231 'case.adjoint_fluid.output_format', file_format,
'fld')
232 call json_get_or_default(parameters, &
233 'case.adjoint_fluid.output_subdivide', subdivide, .false.)
236 if (
allocated(this%adjoint_case%adjoint_scalars))
then
237 n_scalars =
size(this%adjoint_case%adjoint_scalars%adjoint_scalar_fields)
239 call this%output_adjoint%init(
'adjoint_fields', 4 + n_scalars, &
240 precision = precision, &
241 path = trim(output_directory), &
242 format = trim(file_format))
243 call this%output_adjoint%file_%set_subdivide(subdivide)
245 call this%output_adjoint%fields%assign(1, this%adjoint_fluid%p_adj)
246 call this%output_adjoint%fields%assign(2, this%adjoint_fluid%u_adj)
247 call this%output_adjoint%fields%assign(3, this%adjoint_fluid%v_adj)
248 call this%output_adjoint%fields%assign(4, this%adjoint_fluid%w_adj)
251 if (
allocated(this%adjoint_case%adjoint_scalars))
then
253 call this%output_adjoint%fields%assign(4 + i, &
254 this%adjoint_scalars%adjoint_scalar_fields(i)%s_adj)
259 call json_get_or_default(parameters,
"unsteady", unsteady, .false.)
260 this%unsteady = unsteady
263 if (this%unsteady)
then
264 call json_get(parameters,
'state_recovery', state_recovery_params)
265 call state_recover_factory(this%state_recover, this%neko_case, &
266 state_recovery_params)
273 subroutine simulation_free(this)
279 if (
allocated(this%state_recover))
then
280 call this%state_recover%free()
281 deallocate(this%state_recover)
285 call this%neko_case%free()
286 call this%adjoint_case%free()
287 call this%output_forward%free()
288 call this%output_adjoint%free()
292 nullify(this%scalars)
293 nullify(this%adjoint_fluid)
294 nullify(this%adjoint_scalars)
297 this%unsteady = .false.
298 this%have_scalar = .false.
300 this%current_design_iteration = 0
301 if (
allocated(this%forward_field_base_fname))
then
302 deallocate(this%forward_field_base_fname)
304 if (
allocated(this%adjoint_field_base_fname))
then
305 deallocate(this%adjoint_field_base_fname)
309 call neko_simcomps%free()
311 end subroutine simulation_free
314 subroutine simulation_run_forward(this)
316 type(time_step_controller_t) :: dt_controller
317 real(kind=dp) :: loop_start
319 call dt_controller%init(this%neko_case%params)
321 call this%neko_case%time%reset()
322 call simulation_init(this%neko_case, dt_controller)
324 call profiler_start_region(
"Forward simulation")
325 loop_start = mpi_wtime()
327 do while (.not. this%neko_case%time%is_done())
328 this%n_timesteps = this%n_timesteps + 1
330 call simulation_step(this%neko_case, dt_controller, loop_start)
332 if (this%unsteady)
then
333 call this%state_recover%save()
336 call profiler_end_region(
"Forward simulation")
338 call simulation_finalize(this%neko_case)
340 end subroutine simulation_run_forward
343 subroutine simulation_run_backward(this)
345 type(time_step_controller_t) :: dt_controller
346 real(kind=dp) :: loop_start
350 call dt_controller%init(this%neko_case%params)
354 call profiler_start_region(
"Adjoint simulation")
355 cfl = this%adjoint_case%fluid_adj%compute_cfl(this%adjoint_case%time%dt)
356 loop_start = mpi_wtime()
357 do i = this%n_timesteps, 1, -1
358 if (this%unsteady)
then
359 call this%state_recover%restore(i)
365 call profiler_end_region(
"Adjoint simulation")
369 end subroutine simulation_run_backward
372 subroutine simulation_reset(this)
375 call reset(this%neko_case, this%current_design_iteration, &
376 this%forward_field_base_fname)
378 this%current_design_iteration, this%adjoint_field_base_fname)
379 if (this%unsteady)
then
380 call this%state_recover%reset()
383 end subroutine simulation_reset
390 subroutine simulation_set_design_iteration(this, iteration)
392 integer,
intent(in) :: iteration
394 this%current_design_iteration = iteration
396 end subroutine simulation_set_design_iteration
398 subroutine simulation_set_output_counter(this, idx)
400 integer,
intent(in) :: idx
402 call this%output_forward%set_counter(idx)
403 call this%output_adjoint%set_counter(idx)
405 end subroutine simulation_set_output_counter
408 subroutine simulation_write(this, idx)
410 integer,
intent(in) :: idx
412 call this%output_forward%sample(real(idx, kind=rp))
413 call this%output_adjoint%sample(real(idx, kind=rp))
415 end subroutine simulation_write
418 subroutine simulation_write_forward(this, idx)
420 integer,
intent(in) :: idx
422 call this%output_forward%sample(real(idx, kind=rp))
424 end subroutine simulation_write_forward
427 subroutine simulation_write_adjoint(this, idx)
429 integer,
intent(in) :: idx
431 call this%output_adjoint%sample(real(idx, kind=rp))
433 end subroutine simulation_write_adjoint
Adjoint Pn/Pn formulation.
Contains the adjoint_scalars_t type that manages multiple scalar fields.
Contains extensions to the neko library required to run the topology optimization code.
subroutine, public reset(neko_case, design_iteration, output_base_fname)
Reset the case data structure.
subroutine, public reset_adjoint(adjoint_case, neko_case, design_iteration, output_base_fname)
Reset the adjoint case data structure.
Adjoint simulation driver.
subroutine, public simulation_adjoint_init(c, dt_controller)
Initialise a simulation_adjoint of a case.
subroutine, public simulation_adjoint_step(c, dt_controller, cfl, tstep_loop_start_time, final_time)
Compute a single time-step of an adjoint case.
subroutine, public simulation_adjoint_finalize(c)
Finalize a simulation of a case.
Implements the steady_problem_t type.
subroutine simulation_initialize(this, parameters)
Initialize the simulation.
Abstract interface for state recovery strategies.
Adjoint case type. Todo: This should Ideally be a subclass of case_t, however, that is not yet suppor...
Base type of all fluid formulations.
Type to manage multiple adjoint scalar transport equations.
Abstract base type for state recovery implementations.