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 adjoint_case, only: adjoint_case_t
41 use fluid_scheme_incompressible, only: fluid_scheme_incompressible_t
42 use adjoint_fluid_scheme, only: adjoint_fluid_scheme_t
44 use scalar_pnpn, only: scalar_pnpn_t
47 use scalars, only: scalars_t
48 use scalar_scheme, only: scalar_scheme_t
49 use fluid_pnpn, only: fluid_pnpn_t
50 use time_step_controller, only: time_step_controller_t
51 use time_state, only: time_state_t
52 use field_output, only: field_output_t
53 use chkp_output, only: chkp_output_t
54 use simcomp_executor, only: neko_simcomps
55 use neko_ext, only: reset, reset_adjoint
56 use field, only: field_t
57 use registry, only: neko_registry
58 use field_math, only: field_rzero, field_copy
59 use checkpoint, only: chkp_t
60 use file, only: file_t
61 use utils, only: neko_warning, neko_error
62 use comm, only: pe_rank
63 use json_file_module, only: json_file
64 use json_utils, only: json_get, json_get_or_default
65 use num_types, only: rp, sp, dp
66 use logger, only: log_size, neko_log
67 use mpi_f08, only: mpi_wtime
68 use jobctrl, only: jobctrl_time_limit
69 use profiler, only: profiler_start, profiler_stop, &
70 profiler_start_region, profiler_end_region
73 use simulation, only: simulation_init, simulation_step, simulation_finalize, &
74 simulation_restart
75 use simulation_checkpoint, only: simulation_checkpoint_t
76 use runtime_stats, only: neko_rt_stats
77 use scratch_registry, only: neko_scratch_registry
78 use registry, only: neko_registry
79 implicit none
80 private
81
83
85 type(case_t), public :: neko_case
87 type(adjoint_case_t), public :: adjoint_case
89 class(fluid_scheme_incompressible_t), public, pointer :: fluid => null()
91 type(scalars_t), public, pointer :: scalars => null()
93 class(adjoint_fluid_scheme_t), public, pointer :: adjoint_fluid => null()
95 type(adjoint_scalars_t), public, pointer :: adjoint_scalars => null()
98 type(field_output_t), public :: output_forward
101 type(field_output_t), public :: output_adjoint
103 logical :: unsteady = .false.
104
105 logical :: have_scalar = .false.
106 integer :: n_timesteps = 0
107
108 ! ----------------------------------------------------------------------- !
109 ! Checkpoint system
110
112 type(simulation_checkpoint_t) :: checkpoint
113
114 contains
116 procedure, pass(this) :: init => simulation_initialize
118 procedure, pass(this) :: free => simulation_free
120 procedure, pass(this) :: run_forward => simulation_run_forward
122 procedure, pass(this) :: run_backward => simulation_run_backward
124 procedure, pass(this) :: reset => simulation_reset
126 procedure, pass(this) :: set_output_counter => &
127 simulation_set_output_counter
129 procedure, pass(this) :: write => simulation_write
131 procedure, pass(this) :: write_forward => simulation_write_forward
133 procedure, pass(this) :: write_adjoint => simulation_write_adjoint
134
135 end type simulation_t
136 public :: simulation_t
137contains
138
140 subroutine simulation_initialize(this, parameters)
141 class(simulation_t), intent(inout), target :: this
142 type(json_file), intent(inout) :: parameters
143 type(json_file) :: checkpoint_params
144 integer :: i, n_scalars, unsteady_support
145 character(len=:), allocatable :: output_directory, precision_s, file_format
146 integer :: precision
147 logical :: unsteady, subdivide
148
149 ! initialize the primal Neko objects
150 call this%neko_case%init(parameters)
151 call neko_rt_stats%init(parameters)
152 call neko_simcomps%init(this%neko_case)
153
154 ! initialize the adjoint
155 call this%adjoint_case%init(this%neko_case)
156
157 ! Start the profiler
158 call profiler_start
159
160 select type (fluid => this%neko_case%fluid)
161 type is (fluid_pnpn_t)
162 this%fluid => fluid
163 end select
164
165 select type (adjoint_fluid => this%adjoint_case%fluid_adj)
166 type is (adjoint_fluid_pnpn_t)
167 this%adjoint_fluid => adjoint_fluid
168 end select
169
170 if (allocated(this%neko_case%scalars)) then
171 this%scalars => this%neko_case%scalars
172 end if
173
174 if (allocated(this%adjoint_case%adjoint_scalars)) then
175 this%adjoint_scalars => this%adjoint_case%adjoint_scalars
176 end if
177
178 !---------------------------------------------------------
179 ! Initialize the output types
180
181 ! Read settings for the output types, with some reasonable defaults
182 call json_get_or_default(parameters, 'case.output_directory', &
183 output_directory, '')
184 call json_get_or_default(parameters, 'case.output_precision', precision_s, &
185 'single')
186 call json_get_or_default(parameters, 'case.fluid.output_format', &
187 file_format, 'fld')
188 call json_get_or_default(parameters, 'case.fluid.output_subdivide', &
189 subdivide, .false.)
190
191 if (trim(precision_s) .eq. 'double') then
192 precision = dp
193 else
194 precision = sp
195 end if
196
197 ! Allocate the output type
198 n_scalars = 0
199 if (allocated(this%neko_case%scalars)) then
200 n_scalars = size(this%neko_case%scalars%scalar_fields)
201 end if
202 call this%output_forward%init('forward_fields', 4 + n_scalars, &
203 precision = precision, &
204 path = trim(output_directory), &
205 format = trim(file_format))
206 call this%output_forward%file_%set_subdivide(subdivide)
207
208 call this%output_forward%fields%assign(1, this%fluid%p)
209 call this%output_forward%fields%assign(2, this%fluid%u)
210 call this%output_forward%fields%assign(3, this%fluid%v)
211 call this%output_forward%fields%assign(4, this%fluid%w)
212
213 ! Assign all scalar fields
214 if (allocated(this%neko_case%scalars)) then
215 do i = 1, n_scalars
216 call this%output_forward%fields%assign(4 + i, &
217 this%scalars%scalar_fields(i)%scalar%s)
218 end do
219 end if
220
221 ! Read settings for the output types, with some reasonable defaults
222 call json_get_or_default(parameters, &
223 'case.adjoint_fluid.output_format', file_format, 'fld')
224 call json_get_or_default(parameters, &
225 'case.adjoint_fluid.output_subdivide', subdivide, .false.)
226
227 n_scalars = 0
228 if (allocated(this%adjoint_case%adjoint_scalars)) then
229 n_scalars = size(this%adjoint_case%adjoint_scalars%adjoint_scalar_fields)
230 end if
231 call this%output_adjoint%init('adjoint_fields', 4 + n_scalars, &
232 precision = precision, &
233 path = trim(output_directory), &
234 format = trim(file_format))
235 call this%output_adjoint%file_%set_subdivide(subdivide)
236
237 call this%output_adjoint%fields%assign(1, this%adjoint_fluid%p_adj)
238 call this%output_adjoint%fields%assign(2, this%adjoint_fluid%u_adj)
239 call this%output_adjoint%fields%assign(3, this%adjoint_fluid%v_adj)
240 call this%output_adjoint%fields%assign(4, this%adjoint_fluid%w_adj)
241
242 ! Assign all scalar fields
243 if (allocated(this%adjoint_case%adjoint_scalars)) then
244 do i = 1, n_scalars
245 call this%output_adjoint%fields%assign(4 + i, &
246 this%adjoint_scalars%adjoint_scalar_fields(i)%s_adj)
247 end do
248 end if
249
250 ! Check if the simulation is steady or unsteady
251 call json_get_or_default(parameters, "unsteady", unsteady, .false.)
252 this%unsteady = unsteady
253
254 ! Ensure there is a means to deal with unsteadiness
255 if (this%unsteady) then
256 unsteady_support = 0
257 if ("checkpoints" .in. parameters) then
258 unsteady_support = unsteady_support + 1
259 end if
260
261 if (unsteady_support .eq. 0) then
262 call neko_error("No support for unsteady simulation provided, \\ &
263 & \\ current options include enabling checkpoints.")
264 end if
265
266 if (unsteady_support .gt. 1) then
267 call neko_error("Too many supports for unsteady simulation \\ &
268 & \\ provided, please select one.")
269 end if
270 end if
271
272 if ("checkpoints" .in. parameters) then
273 call json_get(parameters, 'checkpoints', checkpoint_params)
274 call this%checkpoint%init(this%neko_case, checkpoint_params)
275 end if
276
277 end subroutine simulation_initialize
278
280 subroutine simulation_free(this)
281 class(simulation_t), intent(inout) :: this
282
283 ! Stop the profiler
284 call profiler_stop
285
286 ! Free the objects
287 call this%neko_case%free()
288 call this%adjoint_case%free()
289 call this%output_forward%free()
290 call this%output_adjoint%free()
291 call this%checkpoint%free()
292
293 ! Nullify pointers
294 nullify(this%fluid)
295 nullify(this%scalars)
296 nullify(this%adjoint_fluid)
297 nullify(this%adjoint_scalars)
298
299 ! Reset flags and counters
300 this%unsteady = .false.
301 this%have_scalar = .false.
302 this%n_timesteps = 0
303
304 ! Close global objects
305 call neko_simcomps%free()
306
307 end subroutine simulation_free
308
310 subroutine simulation_run_forward(this)
311 class(simulation_t), intent(inout) :: this
312 type(time_step_controller_t) :: dt_controller
313 real(kind=dp) :: loop_start
314
315 call dt_controller%init(this%neko_case%params)
316
317 call this%neko_case%time%reset()
318 call simulation_init(this%neko_case, dt_controller)
319
320 call profiler_start_region("Forward simulation")
321 loop_start = mpi_wtime()
322 this%n_timesteps = 0
323 do while (.not. this%neko_case%time%is_done())
324 this%n_timesteps = this%n_timesteps + 1
325
326 call simulation_step(this%neko_case, dt_controller, loop_start)
327
328 call this%checkpoint%save(this%neko_case)
329 end do
330 call profiler_end_region("Forward simulation")
331
332 call simulation_finalize(this%neko_case)
333
334 end subroutine simulation_run_forward
335
337 subroutine simulation_run_backward(this)
338 class(simulation_t), intent(inout) :: this
339 type(time_step_controller_t) :: dt_controller
340 real(kind=dp) :: loop_start
341 real(kind=rp) :: cfl
342 integer :: i
343
344 call dt_controller%init(this%neko_case%params)
345
346 call simulation_adjoint_init(this%adjoint_case, dt_controller)
347
348 call profiler_start_region("Adjoint simulation")
349 cfl = this%adjoint_case%fluid_adj%compute_cfl(this%adjoint_case%time%dt)
350 loop_start = mpi_wtime()
351 do i = this%n_timesteps, 1, -1
352 call this%checkpoint%restore(this%neko_case, i)
353
354 call simulation_adjoint_step(this%adjoint_case, dt_controller, cfl, &
355 loop_start)
356 end do
357 call profiler_end_region("Adjoint simulation")
358
359 call simulation_adjoint_finalize(this%adjoint_case)
360
361 end subroutine simulation_run_backward
362
364 subroutine simulation_reset(this)
365 class(simulation_t), intent(inout) :: this
366
367 call reset(this%neko_case)
368 call reset_adjoint(this%adjoint_case, this%neko_case)
369 call this%checkpoint%reset()
370
371 end subroutine simulation_reset
372
373 subroutine simulation_set_output_counter(this, idx)
374 class(simulation_t), intent(inout) :: this
375 integer, intent(in) :: idx
376
377 call this%output_forward%set_counter(idx)
378 call this%output_adjoint%set_counter(idx)
379
380 end subroutine simulation_set_output_counter
381
383 subroutine simulation_write(this, idx)
384 class(simulation_t), intent(inout) :: this
385 integer, intent(in) :: idx
386
387 call this%output_forward%sample(real(idx, kind=rp))
388 call this%output_adjoint%sample(real(idx, kind=rp))
389
390 end subroutine simulation_write
391
393 subroutine simulation_write_forward(this, idx)
394 class(simulation_t), intent(inout) :: this
395 integer, intent(in) :: idx
396
397 call this%output_forward%sample(real(idx, kind=rp))
398
399 end subroutine simulation_write_forward
400
402 subroutine simulation_write_adjoint(this, idx)
403 class(simulation_t), intent(inout) :: this
404 integer, intent(in) :: idx
405
406 call this%output_adjoint%sample(real(idx, kind=rp))
407
408 end subroutine simulation_write_adjoint
409
410end 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.