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
104 logical :: unsteady = .false.
105
106 logical :: have_scalar = .false.
107 integer :: n_timesteps = 0
108
109 ! ----------------------------------------------------------------------- !
110 ! Checkpoint system
111
113 type(simulation_checkpoint_t) :: checkpoint
114
115 contains
117 procedure, pass(this) :: init => simulation_initialize
119 procedure, pass(this) :: free => simulation_free
121 procedure, pass(this) :: run_forward => simulation_run_forward
123 procedure, pass(this) :: run_backward => simulation_run_backward
125 procedure, pass(this) :: reset => simulation_reset
127 procedure, pass(this) :: set_output_counter => &
128 simulation_set_output_counter
130 procedure, pass(this) :: write => simulation_write
132 procedure, pass(this) :: write_forward => simulation_write_forward
134 procedure, pass(this) :: write_adjoint => simulation_write_adjoint
135
136 end type simulation_t
137 public :: simulation_t
138contains
139
141 subroutine simulation_initialize(this, parameters)
142 class(simulation_t), intent(inout), target :: this
143 type(json_file), intent(inout) :: parameters
144 type(json_file) :: checkpoint_params
145 integer :: i, n_scalars, unsteady_support
146 character(len=:), allocatable :: output_directory, precision_s, file_format
147 integer :: precision
148 logical :: unsteady, subdivide
149
150 ! initialize the primal Neko objects
151 call this%neko_case%init(parameters)
152 call neko_user_access%init(this%neko_case)
153
154 call neko_rt_stats%init(parameters)
155 call neko_simcomps%init(this%neko_case)
156
157 ! initialize the adjoint
158 call this%adjoint_case%init(this%neko_case)
159
160 ! Start the profiler
161 call profiler_start
162
163 select type (fluid => this%neko_case%fluid)
164 type is (fluid_pnpn_t)
165 this%fluid => fluid
166 end select
167
168 select type (adjoint_fluid => this%adjoint_case%fluid_adj)
169 type is (adjoint_fluid_pnpn_t)
170 this%adjoint_fluid => adjoint_fluid
171 end select
172
173 if (allocated(this%neko_case%scalars)) then
174 this%scalars => this%neko_case%scalars
175 end if
176
177 if (allocated(this%adjoint_case%adjoint_scalars)) then
178 this%adjoint_scalars => this%adjoint_case%adjoint_scalars
179 end if
180
181 !---------------------------------------------------------
182 ! Initialize the output types
183
184 ! Read settings for the output types, with some reasonable defaults
185 call json_get_or_default(parameters, 'case.output_directory', &
186 output_directory, '')
187 call json_get_or_default(parameters, 'case.output_precision', precision_s, &
188 'single')
189 call json_get_or_default(parameters, 'case.fluid.output_format', &
190 file_format, 'fld')
191 call json_get_or_default(parameters, 'case.fluid.output_subdivide', &
192 subdivide, .false.)
193
194 if (trim(precision_s) .eq. 'double') then
195 precision = dp
196 else
197 precision = sp
198 end if
199
200 ! Allocate the output type
201 n_scalars = 0
202 if (allocated(this%neko_case%scalars)) then
203 n_scalars = size(this%neko_case%scalars%scalar_fields)
204 end if
205 call this%output_forward%init('forward_fields', 4 + n_scalars, &
206 precision = precision, &
207 path = trim(output_directory), &
208 format = trim(file_format))
209 call this%output_forward%file_%set_subdivide(subdivide)
210
211 call this%output_forward%fields%assign(1, this%fluid%p)
212 call this%output_forward%fields%assign(2, this%fluid%u)
213 call this%output_forward%fields%assign(3, this%fluid%v)
214 call this%output_forward%fields%assign(4, this%fluid%w)
215
216 ! Assign all scalar fields
217 if (allocated(this%neko_case%scalars)) then
218 do i = 1, n_scalars
219 call this%output_forward%fields%assign(4 + i, &
220 this%scalars%scalar_fields(i)%scalar%s)
221 end do
222 end if
223
224 ! Read settings for the output types, with some reasonable defaults
225 call json_get_or_default(parameters, &
226 'case.adjoint_fluid.output_format', file_format, 'fld')
227 call json_get_or_default(parameters, &
228 'case.adjoint_fluid.output_subdivide', subdivide, .false.)
229
230 n_scalars = 0
231 if (allocated(this%adjoint_case%adjoint_scalars)) then
232 n_scalars = size(this%adjoint_case%adjoint_scalars%adjoint_scalar_fields)
233 end if
234 call this%output_adjoint%init('adjoint_fields', 4 + n_scalars, &
235 precision = precision, &
236 path = trim(output_directory), &
237 format = trim(file_format))
238 call this%output_adjoint%file_%set_subdivide(subdivide)
239
240 call this%output_adjoint%fields%assign(1, this%adjoint_fluid%p_adj)
241 call this%output_adjoint%fields%assign(2, this%adjoint_fluid%u_adj)
242 call this%output_adjoint%fields%assign(3, this%adjoint_fluid%v_adj)
243 call this%output_adjoint%fields%assign(4, this%adjoint_fluid%w_adj)
244
245 ! Assign all scalar fields
246 if (allocated(this%adjoint_case%adjoint_scalars)) then
247 do i = 1, n_scalars
248 call this%output_adjoint%fields%assign(4 + i, &
249 this%adjoint_scalars%adjoint_scalar_fields(i)%s_adj)
250 end do
251 end if
252
253 ! Check if the simulation is steady or unsteady
254 call json_get_or_default(parameters, "unsteady", unsteady, .false.)
255 this%unsteady = unsteady
256
257 ! Ensure there is a means to deal with unsteadiness
258 if (this%unsteady) then
259 unsteady_support = 0
260 if ("checkpoints" .in. parameters) then
261 unsteady_support = unsteady_support + 1
262 end if
263
264 if (unsteady_support .eq. 0) then
265 call neko_error("No support for unsteady simulation provided, \\ &
266 & \\ current options include enabling checkpoints.")
267 end if
268
269 if (unsteady_support .gt. 1) then
270 call neko_error("Too many supports for unsteady simulation \\ &
271 & \\ provided, please select one.")
272 end if
273 end if
274
275 if ("checkpoints" .in. parameters) then
276 call json_get(parameters, 'checkpoints', checkpoint_params)
277 call this%checkpoint%init(this%neko_case, checkpoint_params)
278 end if
279
280 end subroutine simulation_initialize
281
283 subroutine simulation_free(this)
284 class(simulation_t), intent(inout) :: this
285
286 ! Stop the profiler
287 call profiler_stop
288
289 ! Free the objects
290 call this%neko_case%free()
291 call this%adjoint_case%free()
292 call this%output_forward%free()
293 call this%output_adjoint%free()
294 call this%checkpoint%free()
295
296 ! Nullify pointers
297 nullify(this%fluid)
298 nullify(this%scalars)
299 nullify(this%adjoint_fluid)
300 nullify(this%adjoint_scalars)
301
302 ! Reset flags and counters
303 this%unsteady = .false.
304 this%have_scalar = .false.
305 this%n_timesteps = 0
306
307 ! Close global objects
308 call neko_simcomps%free()
309
310 end subroutine simulation_free
311
313 subroutine simulation_run_forward(this)
314 class(simulation_t), intent(inout) :: this
315 type(time_step_controller_t) :: dt_controller
316 real(kind=dp) :: loop_start
317
318 call dt_controller%init(this%neko_case%params)
319
320 call this%neko_case%time%reset()
321 call simulation_init(this%neko_case, dt_controller)
322
323 call profiler_start_region("Forward simulation")
324 loop_start = mpi_wtime()
325 this%n_timesteps = 0
326 do while (.not. this%neko_case%time%is_done())
327 this%n_timesteps = this%n_timesteps + 1
328
329 call simulation_step(this%neko_case, dt_controller, loop_start)
330
331 call this%checkpoint%save(this%neko_case)
332 end do
333 call profiler_end_region("Forward simulation")
334
335 call simulation_finalize(this%neko_case)
336
337 end subroutine simulation_run_forward
338
340 subroutine simulation_run_backward(this)
341 class(simulation_t), intent(inout) :: this
342 type(time_step_controller_t) :: dt_controller
343 real(kind=dp) :: loop_start
344 real(kind=rp) :: cfl
345 integer :: i
346
347 call dt_controller%init(this%neko_case%params)
348
349 call simulation_adjoint_init(this%adjoint_case, dt_controller)
350
351 call profiler_start_region("Adjoint simulation")
352 cfl = this%adjoint_case%fluid_adj%compute_cfl(this%adjoint_case%time%dt)
353 loop_start = mpi_wtime()
354 do i = this%n_timesteps, 1, -1
355 call this%checkpoint%restore(this%neko_case, i)
356
357 call simulation_adjoint_step(this%adjoint_case, dt_controller, cfl, &
358 loop_start)
359 end do
360 call profiler_end_region("Adjoint simulation")
361
362 call simulation_adjoint_finalize(this%adjoint_case)
363
364 end subroutine simulation_run_backward
365
367 subroutine simulation_reset(this)
368 class(simulation_t), intent(inout) :: this
369
370 call reset(this%neko_case)
371 call reset_adjoint(this%adjoint_case, this%neko_case)
372 call this%checkpoint%reset()
373
374 end subroutine simulation_reset
375
376 subroutine simulation_set_output_counter(this, idx)
377 class(simulation_t), intent(inout) :: this
378 integer, intent(in) :: idx
379
380 call this%output_forward%set_counter(idx)
381 call this%output_adjoint%set_counter(idx)
382
383 end subroutine simulation_set_output_counter
384
386 subroutine simulation_write(this, idx)
387 class(simulation_t), intent(inout) :: this
388 integer, intent(in) :: idx
389
390 call this%output_forward%sample(real(idx, kind=rp))
391 call this%output_adjoint%sample(real(idx, kind=rp))
392
393 end subroutine simulation_write
394
396 subroutine simulation_write_forward(this, idx)
397 class(simulation_t), intent(inout) :: this
398 integer, intent(in) :: idx
399
400 call this%output_forward%sample(real(idx, kind=rp))
401
402 end subroutine simulation_write_forward
403
405 subroutine simulation_write_adjoint(this, idx)
406 class(simulation_t), intent(inout) :: this
407 integer, intent(in) :: idx
408
409 call this%output_adjoint%sample(real(idx, kind=rp))
410
411 end subroutine simulation_write_adjoint
412
413end 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)
Reset the case data structure.
Definition neko_ext.f90:91
subroutine, public reset_adjoint(adjoint_case, neko_case)
Reset the adjoint case data structure.
Definition neko_ext.f90:243
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.