40 use json_module,
only: json_file
44 use num_types,
only: rp
45 use logger,
only: neko_log
46 use profiler,
only: profiler_start_region, profiler_end_region
47 use mpi_f08,
only: mpi_wtime
48 use utils,
only: neko_error, filename_suffix
57 character(len=64),
private :: optimizer_type =
''
59 integer,
private :: max_iterations = 0
65 integer,
private :: current_iteration = 0
66 real(kind=rp),
private :: max_runtime = -1.0_rp
67 real(kind=rp),
private :: start_time = 0.0_rp
68 real(kind=rp),
private :: average_time = 0.0_rp
69 real(kind=rp),
private :: step_count = 0.0_rp
80 procedure(optimizer_free), pass(this),
public,
deferred :: free
83 procedure(optimizer_initialize), pass(this),
public,
deferred :: initialize
85 procedure(optimizer_step), pass(this),
public,
deferred :: step
87 procedure(optimizer_validate), pass(this),
public,
deferred :: validate
90 procedure(optimizer_write), pass(this),
public,
deferred :: write
92 procedure(optimizer_save_checkpoint_components), pass(this),
deferred :: &
93 save_checkpoint_components
95 procedure(optimizer_load_checkpoint_components), pass(this),
deferred :: &
96 load_checkpoint_components
99 procedure, pass(this) :: save_checkpoint => optimizer_save_checkpoint
101 procedure, pass(this) :: load_checkpoint => optimizer_load_checkpoint
107 procedure, pass(this),
public :: run => optimizer_run
113 procedure, pass(this) :: init_base => optimizer_init_base
115 procedure, pass(this) :: free_base => optimizer_free_base
117 procedure, pass(this) :: print_status => optimizer_print_status
119 procedure, pass(this) :: out_of_time => optimizer_out_of_time
130 class(optimizer_t),
intent(inout) :: this
131 type(json_file),
intent(inout) :: parameters
132 class(problem_t),
intent(inout) :: problem
133 class(design_t),
intent(in) :: design
134 type(simulation_t),
optional,
intent(in) :: simulation
140 subroutine optimizer_initialize(this, problem, design, simulation)
142 class(optimizer_t),
intent(inout) :: this
143 class(problem_t),
intent(inout) :: problem
144 class(design_t),
intent(inout) :: design
145 type(simulation_t),
optional,
intent(inout) :: simulation
146 end subroutine optimizer_initialize
149 subroutine optimizer_free(this)
151 class(optimizer_t),
intent(inout) :: this
152 end subroutine optimizer_free
155 logical function optimizer_step(this, iter, problem, design, simulation)
157 class(optimizer_t),
intent(inout) :: this
158 integer,
intent(in) :: iter
159 class(problem_t),
intent(inout) :: problem
160 class(design_t),
intent(inout) :: design
161 type(simulation_t),
optional,
intent(inout) :: simulation
162 end function optimizer_step
165 subroutine optimizer_validate(this, problem, design)
167 class(optimizer_t),
intent(inout) :: this
168 class(problem_t),
intent(in) :: problem
169 class(design_t),
intent(in) :: design
170 end subroutine optimizer_validate
173 subroutine optimizer_write(this, iter, problem)
175 class(optimizer_t),
intent(inout) :: this
176 integer,
intent(in) :: iter
177 class(problem_t),
intent(in) :: problem
178 end subroutine optimizer_write
181 subroutine optimizer_save_checkpoint_components(this, filename, overwrite)
183 class(optimizer_t),
intent(inout) :: this
184 character(len=*),
intent(in) :: filename
185 logical,
intent(in),
optional :: overwrite
186 end subroutine optimizer_save_checkpoint_components
189 subroutine optimizer_load_checkpoint_components(this, filename)
191 class(optimizer_t),
intent(inout) :: this
192 character(len=*),
intent(in) :: filename
193 end subroutine optimizer_load_checkpoint_components
207 module subroutine optimizer_factory(object, parameters,
problem,
design, &
209 class(optimizer_t),
allocatable,
intent(inout) :: object
210 type(json_file),
intent(inout) :: parameters
211 class(problem_t),
intent(inout) :: problem
212 class(design_t),
intent(in) :: design
213 type(simulation_t),
optional,
intent(in) :: simulation
214 end subroutine optimizer_factory
215 end interface optimizer_factory
222 module subroutine optimizer_save_checkpoint_hdf5(object, filename, iter, &
224 class(optimizer_t),
intent(inout) :: object
225 character(len=*),
intent(in) :: filename
226 integer,
intent(in) :: iter
227 logical,
intent(in),
optional :: overwrite
228 end subroutine optimizer_save_checkpoint_hdf5
231 module subroutine optimizer_load_checkpoint_hdf5(object, filename, iter)
232 class(optimizer_t),
intent(inout) :: object
233 character(len=*),
intent(in) :: filename
234 integer,
intent(out) :: iter
235 end subroutine optimizer_load_checkpoint_hdf5
238 public :: optimizer_factory
250 subroutine optimizer_init_base(this, optimizer_type, max_iterations, &
252 class(optimizer_t),
intent(inout) :: this
253 character(len=*),
intent(in) :: optimizer_type
254 integer,
intent(in) :: max_iterations
255 real(kind=rp),
intent(in),
optional :: max_runtime
258 this%optimizer_type = optimizer_type
259 this%max_iterations = max_iterations
262 if (
present(max_runtime)) this%max_runtime = max_runtime
265 this%start_time = mpi_wtime()
267 end subroutine optimizer_init_base
271 subroutine optimizer_free_base(this)
272 class(optimizer_t),
intent(inout) :: this
274 this%optimizer_type =
''
275 this%max_iterations = 0
276 this%max_runtime = -1.0_rp
278 this%start_time = 0.0_rp
279 this%current_iteration = 0
281 end subroutine optimizer_free_base
298 subroutine optimizer_run(this, problem, design, simulation)
299 class(optimizer_t),
intent(inout) :: this
300 class(problem_t),
intent(inout) :: problem
301 class(design_t),
intent(inout) :: design
302 type(simulation_t),
optional,
intent(inout) :: simulation
303 real(kind=rp) :: iteration_time
304 logical :: converged, file_exists
312 if (this%max_runtime .gt. 0.0_rp)
then
313 inquire(file =
'optimizer_rt_checkpoint.hdf5', exist = file_exists)
314 if (file_exists)
then
315 call this%load_checkpoint(
'optimizer_rt_checkpoint.hdf5', &
316 this%current_iteration,
design)
318 write(*,
'(A,I0)')
'Loaded runtime checkpoint: ', &
319 this%current_iteration
326 call this%write(this%current_iteration,
problem)
327 call design%write(this%current_iteration)
329 call neko_log%section(
'Optimization Loop')
331 do while (this%current_iteration .lt. this%max_iterations)
332 this%current_iteration = this%current_iteration + 1
333 call profiler_start_region(
'Optimizer iteration')
334 iteration_time = mpi_wtime()
336 converged = this%step(this%current_iteration,
problem,
design, &
339 iteration_time = mpi_wtime() - iteration_time
340 call profiler_end_region(
'Optimizer iteration')
343 call this%write(this%current_iteration,
problem)
344 call design%write(this%current_iteration)
352 else if (this%out_of_time(iteration_time))
then
353 call this%save_checkpoint(
'optimizer_rt_checkpoint.hdf5', &
354 this%current_iteration,
design, .true.)
362 call this%print_status(stop_flag, this%current_iteration)
364 call neko_log%end_section()
366 end subroutine optimizer_run
380 subroutine optimizer_print_status(this, stop_flag, iter)
381 class(optimizer_t),
intent(in) :: this
382 integer,
intent(in) :: stop_flag
383 integer,
intent(in) :: iter
384 character(len=256) :: msg
386 select case (stop_flag)
388 write(msg,
'(A,I0,A)')
'Optimizer converged successfully after ', &
390 call neko_log%message(msg)
392 write(msg,
'(A,I0,A)')
'Optimizer did not converge in ', &
393 this%max_iterations,
' iterations.'
394 call neko_log%warning(msg)
396 write(msg,
'(A,A,F8.2,A)')
'Optimizer stopped after reaching the ', &
397 'maximum runtime of ', this%max_runtime,
' seconds.'
398 call neko_error(trim(msg))
401 write(msg,
'(A)')
'Optimizer stopped for an unknown reason.'
404 end subroutine optimizer_print_status
412 function optimizer_out_of_time(this, step_time)
result(out_of_time)
413 class(optimizer_t),
intent(inout) :: this
414 real(kind=rp),
intent(in) :: step_time
415 logical :: out_of_time
416 real(kind=rp) :: elapsed_time, old_avg_weight
418 out_of_time = .false.
420 if (this%max_runtime .lt. 0.0_rp)
then
424 elapsed_time = mpi_wtime() - this%start_time
425 this%step_count = this%step_count + 1.0_rp
426 old_avg_weight = (this%step_count - 1) / this%step_count
429 this%average_time = step_time / this%step_count + &
430 this%average_time * old_avg_weight
433 out_of_time = (elapsed_time + this%average_time) .gt. this%max_runtime
435 end function optimizer_out_of_time
446 subroutine optimizer_save_checkpoint(this, filename, iter, design, overwrite)
447 class(optimizer_t),
intent(inout) :: this
448 character(len=*),
intent(in) :: filename
449 integer,
intent(in) :: iter
450 class(design_t),
intent(inout) :: design
451 logical,
intent(in),
optional :: overwrite
452 character(len=12) :: file_ext
455 call filename_suffix(filename, file_ext)
457 select case (trim(file_ext))
458 case (
'h5',
'hdf5',
'hf5')
459 call optimizer_save_checkpoint_hdf5(this, filename, iter, overwrite)
461 call neko_error(
'optimizer: Unsupported checkpoint format: ' // &
465 call this%save_checkpoint_components(filename, overwrite)
466 call design%save_checkpoint(filename, overwrite)
468 end subroutine optimizer_save_checkpoint
475 subroutine optimizer_load_checkpoint(this, filename, iter, design)
476 class(optimizer_t),
intent(inout) :: this
477 character(len=*),
intent(in) :: filename
478 integer,
intent(out) :: iter
479 class(design_t),
intent(inout) :: design
480 character(len=12) :: file_ext
483 call filename_suffix(filename, file_ext)
485 select case (trim(file_ext))
486 case (
'h5',
'hdf5',
'hf5')
487 call optimizer_load_checkpoint_hdf5(this, filename, iter)
489 call neko_error(
'optimizer: Unsupported checkpoint format: ' // &
493 call this%load_checkpoint_components(filename)
494 call design%load_checkpoint(filename)
496 end subroutine optimizer_load_checkpoint
502 module subroutine optimizer_save_checkpoint_hdf5(object, filename, iter, &
504 class(optimizer_t),
intent(inout) :: object
505 character(len=*),
intent(in) :: filename
506 integer,
intent(in) :: iter
507 logical,
intent(in),
optional :: overwrite
508 call neko_error(
'optimizer: HDF5 support not enabled rebuild with ' // &
510 end subroutine optimizer_save_checkpoint_hdf5
512 module subroutine optimizer_load_checkpoint_hdf5(object, filename, iter)
513 class(optimizer_t),
intent(inout) :: object
514 character(len=*),
intent(in) :: filename
515 integer,
intent(out) :: iter
516 call neko_error(
'optimizer: HDF5 support not enabled rebuild with ' // &
518 end subroutine optimizer_load_checkpoint_hdf5
Factory function for the optimizer.
Interface for optimizer initialization.
Defines the abstract type optimizer The optimizer type is defined to provide a generic interface to u...
Module for handling the optimization problem.
Implements the steady_problem_t type.
Abstract optimizer class.
The abstract problem type.