Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
simulation.f90
Go to the documentation of this file.
1
34!
36! Here, we simply march forward to steady state solutions
38 use case, only: case_t
39 use neko, only: neko_solve
40 use user_access_singleton, only: neko_user_access
41 use adjoint_case, only: adjoint_case_t
42 use fluid_scheme_incompressible, only: fluid_scheme_incompressible_t
43 use adjoint_fluid_scheme, only: adjoint_fluid_scheme_t
45 use scalar_pnpn, only: scalar_pnpn_t
48 use scalars, only: scalars_t
49 use scalar_scheme, only: scalar_scheme_t
50 use fluid_pnpn, only: fluid_pnpn_t
51 use time_step_controller, only: time_step_controller_t
52 use time_state, only: time_state_t
53 use field_output, only: field_output_t
54 use chkp_output, only: chkp_output_t
55 use simcomp_executor, only: neko_simcomps
56 use neko_ext, only: reset, reset_adjoint
57 use field, only: field_t
58 use registry, only: neko_registry
59 use field_math, only: field_rzero, field_copy
60 use checkpoint, only: chkp_t
61 use file, only: file_t
62 use utils, only: neko_warning, neko_error
63 use comm, only: pe_rank
64 use json_file_module, only: json_file
65 use json_utils, only: json_get, json_get_or_default
66 use num_types, only: rp, sp, dp
67 use logger, only: log_size, neko_log
68 use mpi_f08, only: mpi_wtime
69 use jobctrl, only: jobctrl_time_limit
70 use profiler, only: profiler_start, profiler_stop, &
71 profiler_start_region, profiler_end_region
74 use simulation, only: simulation_init, simulation_step, simulation_finalize, &
75 simulation_restart
76 use simulation_checkpoint, only: simulation_checkpoint_t
77 use runtime_stats, only: neko_rt_stats
78 use scratch_registry, only: neko_scratch_registry
79 use registry, only: neko_registry
80 implicit none
81 private
82
84
86 type(case_t), public :: neko_case
88 type(adjoint_case_t), public :: adjoint_case
90 class(fluid_scheme_incompressible_t), public, pointer :: fluid => null()
92 type(scalars_t), public, pointer :: scalars => null()
94 class(adjoint_fluid_scheme_t), public, pointer :: adjoint_fluid => null()
96 type(adjoint_scalars_t), public, pointer :: adjoint_scalars => null()
99 type(field_output_t), public :: output_forward
102 type(field_output_t), public :: output_adjoint
106 character(len=:), allocatable :: forward_field_base_fname
110 character(len=:), allocatable :: adjoint_field_base_fname
114 integer :: current_design_iteration = 0
116 logical :: unsteady = .false.
117
118 logical :: have_scalar = .false.
119 integer :: n_timesteps = 0
120
121 ! ----------------------------------------------------------------------- !
122 ! Checkpoint system
123
125 type(simulation_checkpoint_t) :: checkpoint
126
127 contains
129 procedure, pass(this) :: init => simulation_initialize
131 procedure, pass(this) :: free => simulation_free
133 procedure, pass(this) :: run_forward => simulation_run_forward
135 procedure, pass(this) :: run_backward => simulation_run_backward
137 procedure, pass(this) :: reset => simulation_reset
139 procedure, pass(this) :: set_output_counter => &
140 simulation_set_output_counter
142 procedure, pass(this) :: set_design_iteration => &
143 simulation_set_design_iteration
145 procedure, pass(this) :: write => simulation_write
147 procedure, pass(this) :: write_forward => simulation_write_forward
149 procedure, pass(this) :: write_adjoint => simulation_write_adjoint
150
151 end type simulation_t
152 public :: simulation_t
153contains
154
156 subroutine simulation_initialize(this, parameters)
157 class(simulation_t), intent(inout), target :: this
158 type(json_file), intent(inout) :: parameters
159 type(json_file) :: checkpoint_params
160 integer :: i, n_scalars, unsteady_support
161 character(len=:), allocatable :: output_directory, precision_s, file_format
162 integer :: precision
163 logical :: unsteady, subdivide
164
165 ! initialize the primal Neko objects
166 call this%neko_case%init(parameters)
167 call neko_user_access%init(this%neko_case)
168
169 call neko_rt_stats%init(parameters)
170 call neko_simcomps%init(this%neko_case)
171
172 ! initialize the adjoint
173 call this%adjoint_case%init(this%neko_case)
174
175 ! Capture Neko's own field output filenames before any design-iteration
176 ! tag ever gets spliced into them (see `reset`/`neko_ext::reset`).
177 this%forward_field_base_fname = &
178 trim(this%neko_case%f_out%file_%get_base_fname())
179 this%adjoint_field_base_fname = &
180 trim(this%adjoint_case%f_out%file_%get_base_fname())
181
182 ! Start the profiler
183 call profiler_start
184
185 select type (fluid => this%neko_case%fluid)
186 type is (fluid_pnpn_t)
187 this%fluid => fluid
188 end select
189
190 select type (adjoint_fluid => this%adjoint_case%fluid_adj)
191 type is (adjoint_fluid_pnpn_t)
192 this%adjoint_fluid => adjoint_fluid
193 end select
194
195 if (allocated(this%neko_case%scalars)) then
196 this%scalars => this%neko_case%scalars
197 end if
198
199 if (allocated(this%adjoint_case%adjoint_scalars)) then
200 this%adjoint_scalars => this%adjoint_case%adjoint_scalars
201 end if
202
203 !---------------------------------------------------------
204 ! Initialize the output types
205
206 ! Read settings for the output types, with some reasonable defaults
207 call json_get_or_default(parameters, 'case.output_directory', &
208 output_directory, '')
209 call json_get_or_default(parameters, 'case.output_precision', precision_s, &
210 'single')
211 call json_get_or_default(parameters, 'case.fluid.output_format', &
212 file_format, 'fld')
213 call json_get_or_default(parameters, 'case.fluid.output_subdivide', &
214 subdivide, .false.)
215
216 if (trim(precision_s) .eq. 'double') then
217 precision = dp
218 else
219 precision = sp
220 end if
221
222 ! Allocate the output type
223 n_scalars = 0
224 if (allocated(this%neko_case%scalars)) then
225 n_scalars = size(this%neko_case%scalars%scalar_fields)
226 end if
227 call this%output_forward%init('forward_fields', 4 + n_scalars, &
228 precision = precision, &
229 path = trim(output_directory), &
230 format = trim(file_format))
231 call this%output_forward%file_%set_subdivide(subdivide)
232
233 call this%output_forward%fields%assign(1, this%fluid%p)
234 call this%output_forward%fields%assign(2, this%fluid%u)
235 call this%output_forward%fields%assign(3, this%fluid%v)
236 call this%output_forward%fields%assign(4, this%fluid%w)
237
238 ! Assign all scalar fields
239 if (allocated(this%neko_case%scalars)) then
240 do i = 1, n_scalars
241 call this%output_forward%fields%assign(4 + i, &
242 this%scalars%scalar_fields(i)%scalar%s)
243 end do
244 end if
245
246 ! Read settings for the output types, with some reasonable defaults
247 call json_get_or_default(parameters, &
248 'case.adjoint_fluid.output_format', file_format, 'fld')
249 call json_get_or_default(parameters, &
250 'case.adjoint_fluid.output_subdivide', subdivide, .false.)
251
252 n_scalars = 0
253 if (allocated(this%adjoint_case%adjoint_scalars)) then
254 n_scalars = size(this%adjoint_case%adjoint_scalars%adjoint_scalar_fields)
255 end if
256 call this%output_adjoint%init('adjoint_fields', 4 + n_scalars, &
257 precision = precision, &
258 path = trim(output_directory), &
259 format = trim(file_format))
260 call this%output_adjoint%file_%set_subdivide(subdivide)
261
262 call this%output_adjoint%fields%assign(1, this%adjoint_fluid%p_adj)
263 call this%output_adjoint%fields%assign(2, this%adjoint_fluid%u_adj)
264 call this%output_adjoint%fields%assign(3, this%adjoint_fluid%v_adj)
265 call this%output_adjoint%fields%assign(4, this%adjoint_fluid%w_adj)
266
267 ! Assign all scalar fields
268 if (allocated(this%adjoint_case%adjoint_scalars)) then
269 do i = 1, n_scalars
270 call this%output_adjoint%fields%assign(4 + i, &
271 this%adjoint_scalars%adjoint_scalar_fields(i)%s_adj)
272 end do
273 end if
274
275 ! Check if the simulation is steady or unsteady
276 call json_get_or_default(parameters, "unsteady", unsteady, .false.)
277 this%unsteady = unsteady
278
279 ! Ensure there is a means to deal with unsteadiness
280 if (this%unsteady) then
281 unsteady_support = 0
282 if ("checkpoints" .in. parameters) then
283 unsteady_support = unsteady_support + 1
284 end if
285
286 if (unsteady_support .eq. 0) then
287 call neko_error("No support for unsteady simulation provided, \\ &
288 & \\ current options include enabling checkpoints.")
289 end if
290
291 if (unsteady_support .gt. 1) then
292 call neko_error("Too many supports for unsteady simulation \\ &
293 & \\ provided, please select one.")
294 end if
295 end if
296
297 if ("checkpoints" .in. parameters) then
298 call json_get(parameters, 'checkpoints', checkpoint_params)
299 call this%checkpoint%init(this%neko_case, checkpoint_params)
300 end if
301
302 end subroutine simulation_initialize
303
305 subroutine simulation_free(this)
306 class(simulation_t), intent(inout) :: this
307
308 ! Stop the profiler
309 call profiler_stop
310
311 ! Free the objects
312 call this%neko_case%free()
313 call this%adjoint_case%free()
314 call this%output_forward%free()
315 call this%output_adjoint%free()
316 call this%checkpoint%free()
317
318 ! Nullify pointers
319 nullify(this%fluid)
320 nullify(this%scalars)
321 nullify(this%adjoint_fluid)
322 nullify(this%adjoint_scalars)
323
324 ! Reset flags and counters
325 this%unsteady = .false.
326 this%have_scalar = .false.
327 this%n_timesteps = 0
328 this%current_design_iteration = 0
329 if (allocated(this%forward_field_base_fname)) then
330 deallocate(this%forward_field_base_fname)
331 end if
332 if (allocated(this%adjoint_field_base_fname)) then
333 deallocate(this%adjoint_field_base_fname)
334 end if
335
336 ! Close global objects
337 call neko_simcomps%free()
338
339 end subroutine simulation_free
340
342 subroutine simulation_run_forward(this)
343 class(simulation_t), intent(inout) :: this
344 type(time_step_controller_t) :: dt_controller
345 real(kind=dp) :: loop_start
346
347 call dt_controller%init(this%neko_case%params)
348
349 call this%neko_case%time%reset()
350 call simulation_init(this%neko_case, dt_controller)
351
352 call profiler_start_region("Forward simulation")
353 loop_start = mpi_wtime()
354 this%n_timesteps = 0
355 do while (.not. this%neko_case%time%is_done())
356 this%n_timesteps = this%n_timesteps + 1
357
358 call simulation_step(this%neko_case, dt_controller, loop_start)
359
360 call this%checkpoint%save(this%neko_case)
361 end do
362 call profiler_end_region("Forward simulation")
363
364 call simulation_finalize(this%neko_case)
365
366 end subroutine simulation_run_forward
367
369 subroutine simulation_run_backward(this)
370 class(simulation_t), intent(inout) :: this
371 type(time_step_controller_t) :: dt_controller
372 real(kind=dp) :: loop_start
373 real(kind=rp) :: cfl
374 integer :: i
375
376 call dt_controller%init(this%neko_case%params)
377
378 call simulation_adjoint_init(this%adjoint_case, dt_controller)
379
380 call profiler_start_region("Adjoint simulation")
381 cfl = this%adjoint_case%fluid_adj%compute_cfl(this%adjoint_case%time%dt)
382 loop_start = mpi_wtime()
383 do i = this%n_timesteps, 1, -1
384 call this%checkpoint%restore(this%neko_case, i)
385
386 call simulation_adjoint_step(this%adjoint_case, dt_controller, cfl, &
387 loop_start)
388 end do
389 call profiler_end_region("Adjoint simulation")
390
391 call simulation_adjoint_finalize(this%adjoint_case)
392
393 end subroutine simulation_run_backward
394
396 subroutine simulation_reset(this)
397 class(simulation_t), intent(inout) :: this
398
399 call reset(this%neko_case, this%current_design_iteration, &
400 this%forward_field_base_fname)
401 call reset_adjoint(this%adjoint_case, this%neko_case, &
402 this%current_design_iteration, this%adjoint_field_base_fname)
403 call this%checkpoint%reset()
404
405 end subroutine simulation_reset
406
412 subroutine simulation_set_design_iteration(this, iteration)
413 class(simulation_t), intent(inout) :: this
414 integer, intent(in) :: iteration
415
416 this%current_design_iteration = iteration
417
418 end subroutine simulation_set_design_iteration
419
420 subroutine simulation_set_output_counter(this, idx)
421 class(simulation_t), intent(inout) :: this
422 integer, intent(in) :: idx
423
424 call this%output_forward%set_counter(idx)
425 call this%output_adjoint%set_counter(idx)
426
427 end subroutine simulation_set_output_counter
428
430 subroutine simulation_write(this, idx)
431 class(simulation_t), intent(inout) :: this
432 integer, intent(in) :: idx
433
434 call this%output_forward%sample(real(idx, kind=rp))
435 call this%output_adjoint%sample(real(idx, kind=rp))
436
437 end subroutine simulation_write
438
440 subroutine simulation_write_forward(this, idx)
441 class(simulation_t), intent(inout) :: this
442 integer, intent(in) :: idx
443
444 call this%output_forward%sample(real(idx, kind=rp))
445
446 end subroutine simulation_write_forward
447
449 subroutine simulation_write_adjoint(this, idx)
450 class(simulation_t), intent(inout) :: this
451 integer, intent(in) :: idx
452
453 call this%output_adjoint%sample(real(idx, kind=rp))
454
455 end subroutine simulation_write_adjoint
456
457end module simulation_m
Adjoint Pn/Pn formulation.
Contains the adjoint_scalar_pnpn_t type.
Contains the adjoint_scalars_t type that manages multiple scalar fields.
Contains extensions to the neko library required to run the topology optimization code.
Definition neko_ext.f90:42
subroutine, public reset(neko_case, design_iteration, output_base_fname)
Reset the case data structure.
Definition neko_ext.f90:96
subroutine, public reset_adjoint(adjoint_case, neko_case, design_iteration, output_base_fname)
Reset the adjoint case data structure.
Definition neko_ext.f90:273
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.
Adjoint case type. Todo: This should Ideally be a subclass of case_t, however, that is not yet suppor...
Type to manage multiple adjoint scalar transport equations.