Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
optimizer.f90
Go to the documentation of this file.
1
34
41 use json_module, only: json_file
42 use simulation_m, only: simulation_t
43 use problem, only: problem_t
44 use design, only: design_t
45 use num_types, only: rp
46 use logger, only: neko_log, log_size
47 use profiler, only: profiler_start_region, profiler_end_region
48 use mpi_f08, only: mpi_wtime, mpi_allreduce, mpi_max
49 use utils, only: neko_error, filename_suffix, read_duration
50 use csv_file, only: csv_file_t
51 use vector, only: vector_t
52 use json_utils, only: json_get_or_default
53 use comm, only: pe_rank, mpi_real_precision, neko_comm
54 use continuation_scheduler, only: nekotop_continuation
55
56 implicit none
57 private
58
60 type, abstract, public :: optimizer_t
61
63 character(len=64), private :: optimizer_type = ''
65 integer, private :: max_iterations = 0
67 integer, private :: current_iteration = 0
69 real(kind=rp), private :: stop_design_change = -1.0_rp
71 real(kind=rp), public :: max_design_change = 0.0_rp
72
73 ! ----------------------------------------------------------------------- !
74 ! Restart related members
75
77 character(len=256), private :: checkpoint_file = ''
78
79 ! Checkpoint related information
80 character(len=256), private :: checkpoint_path = './checkpoints/'
81 character(len=256), private :: checkpoint_base = 'optimizer_checkpoint'
82 character(len=256), private :: checkpoint_format = 'hdf5'
83 integer, private :: checkpoint_interval = -1
84
85 ! Variables for the runtime-based stopping criteria
86 real(kind=rp), private :: max_runtime = -1.0_rp
87 real(kind=rp), private :: start_time = 0.0_rp
88 real(kind=rp), private :: average_time = 0.0_rp
89 real(kind=rp), private :: step_count = 0.0_rp
90
91 ! Logging state
92 logical, private :: log_initialized = .false.
93 logical, private :: log_include_constraints = .true.
94 integer, private :: log_extra_size = 0
95 type(csv_file_t), private :: log_file
96 type(vector_t), private :: log_data
97
98 contains
99
100 ! ---------------------------------------------------------------------- !
101 ! Deferred procedures for specific optimizers
102
104 procedure(optimizer_init_from_json), pass(this), public, deferred :: &
105 init_from_json
107 procedure(optimizer_free), pass(this), public, deferred :: free
108
110 procedure(optimizer_initialize), pass(this), public, deferred :: initialize
112 procedure(optimizer_step), pass(this), public, deferred :: step
114 procedure(optimizer_validate), pass(this), public, deferred :: validate
115
117 procedure(optimizer_write), pass(this), public, deferred :: write
119 procedure(optimizer_save_checkpoint_components), pass(this), deferred :: &
120 save_checkpoint_components
122 procedure(optimizer_load_checkpoint_components), pass(this), deferred :: &
123 load_checkpoint_components
124
126 procedure, pass(this) :: save_checkpoint => optimizer_save_checkpoint
128 procedure, pass(this) :: load_checkpoint => optimizer_load_checkpoint
129
130 ! ----------------------------------------------------------------------- !
131 ! Public procedures
132
134 procedure, pass(this), public :: run => optimizer_run
135
136 ! ----------------------------------------------------------------------- !
137 ! Private procedures
138
140 procedure, pass(this) :: init_base => optimizer_init_base
142 procedure, pass(this) :: free_base => optimizer_free_base
144 procedure, pass(this) :: read_base_settings => optimizer_read_base_settings
146 procedure, pass(this) :: print_status => optimizer_print_status
148 procedure, pass(this) :: out_of_time => optimizer_out_of_time
150 procedure, pass(this) :: init_log => optimizer_init_log
152 procedure, pass(this) :: write_log => optimizer_write_log
153 end type optimizer_t
154
155 ! -------------------------------------------------------------------------- !
156 ! Interface for the optimizer module.
157
158 abstract interface
159
160 subroutine optimizer_init_from_json(this, parameters, problem, design, &
161 simulation)
162 import optimizer_t, json_file, simulation_t, problem_t, design_t, rp
163 class(optimizer_t), intent(inout) :: this
164 type(json_file), intent(inout) :: parameters
165 class(problem_t), intent(inout) :: problem
166 class(design_t), intent(in) :: design
167 type(simulation_t), optional, intent(in) :: simulation
168 end subroutine optimizer_init_from_json
169
173 subroutine optimizer_initialize(this, problem, design, simulation)
175 class(optimizer_t), intent(inout) :: this
176 class(problem_t), intent(inout) :: problem
177 class(design_t), intent(inout) :: design
178 type(simulation_t), optional, intent(inout) :: simulation
179 end subroutine optimizer_initialize
180
182 subroutine optimizer_free(this)
183 import optimizer_t
184 class(optimizer_t), intent(inout) :: this
185 end subroutine optimizer_free
186
188 logical function optimizer_step(this, iter, problem, design, simulation)
190 class(optimizer_t), intent(inout) :: this
191 integer, intent(in) :: iter
192 class(problem_t), intent(inout) :: problem
193 class(design_t), intent(inout) :: design
194 type(simulation_t), optional, intent(inout) :: simulation
195 end function optimizer_step
196
198 subroutine optimizer_validate(this, problem, design)
200 class(optimizer_t), intent(inout) :: this
201 class(problem_t), intent(in) :: problem
202 class(design_t), intent(in) :: design
203 end subroutine optimizer_validate
204
206 subroutine optimizer_write(this, iter, problem)
208 class(optimizer_t), intent(inout) :: this
209 integer, intent(in) :: iter
210 class(problem_t), intent(inout) :: problem
211 end subroutine optimizer_write
212
214 subroutine optimizer_save_checkpoint_components(this, filename, overwrite)
215 import optimizer_t
216 class(optimizer_t), intent(inout) :: this
217 character(len=*), intent(in) :: filename
218 logical, intent(in), optional :: overwrite
219 end subroutine optimizer_save_checkpoint_components
220
222 subroutine optimizer_load_checkpoint_components(this, filename)
223 import optimizer_t
224 class(optimizer_t), intent(inout) :: this
225 character(len=*), intent(in) :: filename
226 end subroutine optimizer_load_checkpoint_components
227
228 end interface
229
230 ! -------------------------------------------------------------------------- !
231 ! Interfaces for the factory functions
232
240 module subroutine optimizer_factory(object, parameters, problem, design, &
241 simulation)
242 class(optimizer_t), allocatable, intent(inout) :: object
243 type(json_file), intent(inout) :: parameters
244 class(problem_t), intent(inout) :: problem
245 class(design_t), intent(in) :: design
246 type(simulation_t), optional, intent(in) :: simulation
247 end subroutine optimizer_factory
248 end interface optimizer_factory
249
250 ! -------------------------------------------------------------------------- !
251 ! IO routines for HDF5 checkpoints
252
253 interface
254
255 module subroutine optimizer_save_checkpoint_hdf5(object, filename, iter, &
256 overwrite)
257 class(optimizer_t), intent(inout) :: object
258 character(len=*), intent(in) :: filename
259 integer, intent(in) :: iter
260 logical, intent(in), optional :: overwrite
261 end subroutine optimizer_save_checkpoint_hdf5
262
264 module subroutine optimizer_load_checkpoint_hdf5(object, filename, iter)
265 class(optimizer_t), intent(inout) :: object
266 character(len=*), intent(in) :: filename
267 integer, intent(out) :: iter
268 end subroutine optimizer_load_checkpoint_hdf5
269 end interface
270
271 public :: optimizer_factory
272
273contains
274
275 ! -------------------------------------------------------------------------- !
276 ! Base initializer and free routines
277
290 subroutine optimizer_init_base(this, optimizer_type, max_iterations, &
291 max_runtime, stop_design_change, checkpoint_file, checkpoint_path, &
292 checkpoint_base, checkpoint_format, checkpoint_interval)
293 class(optimizer_t), intent(inout) :: this
294 character(len=*), intent(in) :: optimizer_type
295 integer, intent(in) :: max_iterations
296 real(kind=rp), intent(in), optional :: max_runtime
297 real(kind=rp), intent(in), optional :: stop_design_change
298 character(len=*), intent(in), optional :: checkpoint_file
299 character(len=*), intent(in), optional :: checkpoint_path
300 character(len=*), intent(in), optional :: checkpoint_base
301 character(len=*), intent(in), optional :: checkpoint_format
302 integer, intent(in), optional :: checkpoint_interval
303
304 ! Mandatory settings
305 this%optimizer_type = optimizer_type
306 this%max_iterations = max_iterations
307
308 ! Optional settings
309 if (present(max_runtime)) this%max_runtime = max_runtime
310 if (present(stop_design_change)) this%stop_design_change = stop_design_change
311 if (present(checkpoint_file)) this%checkpoint_file = checkpoint_file
312 if (present(checkpoint_path)) this%checkpoint_path = checkpoint_path
313 if (present(checkpoint_base)) this%checkpoint_base = checkpoint_base
314 if (present(checkpoint_format)) this%checkpoint_format = checkpoint_format
315 if (present(checkpoint_interval)) then
316 this%checkpoint_interval = checkpoint_interval
317 end if
318
319 ! Initialize internals
320 this%start_time = mpi_wtime()
321
322 end subroutine optimizer_init_base
323
326 subroutine optimizer_free_base(this)
327 class(optimizer_t), intent(inout) :: this
328
329 this%optimizer_type = ''
330 this%max_iterations = 0
331 this%max_runtime = -1.0_rp
332 this%stop_design_change = -1.0_rp
333 this%max_design_change = 0.0_rp
334 this%checkpoint_file = ''
335 this%checkpoint_path = './checkpoints/'
336 this%checkpoint_base = 'optimizer_checkpoint'
337 this%checkpoint_format = 'hdf5'
338 this%checkpoint_interval = -1
339
340 this%start_time = 0.0_rp
341 this%current_iteration = 0
342 call this%log_data%free()
343 this%log_initialized = .false.
344 this%log_extra_size = 0
345 this%log_include_constraints = .true.
346
347 end subroutine optimizer_free_base
348
352 subroutine optimizer_read_base_settings(this, solver_params)
353 class(optimizer_t), intent(inout) :: this
354 type(json_file), intent(inout) :: solver_params
355 integer :: read_int
356 character(len=:), allocatable :: read_str
357
358 call json_get_or_default(solver_params, 'max_runtime', read_str, "")
359 call read_duration(read_str, this%max_runtime)
360 call json_get_or_default(solver_params, 'stop_design_change', &
361 this%stop_design_change, -1.0_rp)
362
363 call json_get_or_default(solver_params, 'restart_file', read_str, &
364 this%checkpoint_file)
365 this%checkpoint_file = read_str
366
367 call json_get_or_default(solver_params, 'checkpoint.path', read_str, &
368 this%checkpoint_path)
369 this%checkpoint_path = read_str
370 call json_get_or_default(solver_params, 'checkpoint.base', read_str, &
371 this%checkpoint_base)
372 this%checkpoint_base = read_str
373 call json_get_or_default(solver_params, 'checkpoint.format', read_str, &
374 this%checkpoint_format)
375 this%checkpoint_format = read_str
376 call json_get_or_default(solver_params, 'checkpoint.interval', read_int, &
377 this%checkpoint_interval)
378 this%checkpoint_interval = read_int
379
380 end subroutine optimizer_read_base_settings
381
382 ! -------------------------------------------------------------------------- !
383 ! Optimization loop routine
384
397 subroutine optimizer_run(this, problem, design, simulation)
398 class(optimizer_t), intent(inout) :: this
399 class(problem_t), intent(inout) :: problem
400 class(design_t), intent(inout) :: design
401 type(simulation_t), optional, intent(inout) :: simulation
402 real(kind=rp) :: iteration_time
403 character(len=1024) :: checkpoint_file
404 logical :: converged, file_exists
405 integer :: stop_flag
406
407 ! Initialize variables
408 stop_flag = 1
409 converged = .false.
410
411 ! Restart from checkpoint if available
412 if (trim(this%checkpoint_file) .ne. '') then
413 checkpoint_file = trim(this%checkpoint_file)
414 else
415 checkpoint_file = optimizer_checkpoint_filename(this, &
416 basename = 'optimizer_rt_checkpoint')
417 end if
418
419 inquire(file = checkpoint_file, exist = file_exists)
420 if (file_exists) then
421 call this%load_checkpoint(checkpoint_file, this%current_iteration, &
422 design)
423 end if
424
425 ! compute potential internals for for a potential restart
426 if (this%current_iteration .ne. 0) then
427 call design%set_output_counter(this%current_iteration - 1)
428 if (present(simulation)) then
429 call simulation%set_output_counter(this%current_iteration - 1)
430 end if
431 end if
432
433 ! Prepare the problem state before starting the optimization
434 call this%initialize(problem, design, simulation)
435
436 call this%write(this%current_iteration, problem)
437 call design%write(this%current_iteration)
438
439 call neko_log%section('Optimization Loop')
440
441 do while (this%current_iteration .lt. this%max_iterations)
442 this%current_iteration = this%current_iteration + 1
443 if (pe_rank .eq. 0) then
444 write(*,*) 'Starting iteration ', this%current_iteration
445 end if
446
447 call profiler_start_region('Optimizer iteration')
448 iteration_time = mpi_wtime()
449
450 ! Update the parameters in continuation scheduler
451 call nekotop_continuation%update(this%current_iteration)
452
453 converged = this%step(this%current_iteration, problem, design, &
454 simulation)
455
456 iteration_time = mpi_wtime() - iteration_time
457 call profiler_end_region('Optimizer iteration')
458
459 ! Log the progress and outputs
460 call this%write(this%current_iteration, problem)
461 call design%write(this%current_iteration)
462
463 ! Save checkpoint if enabled
464 if (this%checkpoint_interval .gt. 0 .and. &
465 mod(this%current_iteration, this%checkpoint_interval) == 0) then
466 call this%save_checkpoint(this%current_iteration, design, .false.)
467 end if
468
469 ! --------------------------------------------------------------------- !
470 ! Check stopping criteria
471
472 if (converged) then
473 stop_flag = 0
474 exit
475 else if (this%current_iteration .ge. this%max_iterations) then
476 stop_flag = 1
477 exit
478 else if (this%max_design_change .lt. this%stop_design_change) then
479 stop_flag = 2
480 exit
481 else if (this%out_of_time(iteration_time)) then
482 call this%save_checkpoint(this%current_iteration, design, .true., &
483 basename = 'optimizer_rt_checkpoint')
484 stop_flag = 3
485 exit
486 end if
487 end do
488
489 ! Check that the final design is valid
490 call this%validate(problem, design)
491 call this%print_status(stop_flag, this%current_iteration)
492
493 call neko_log%end_section()
494
495 end subroutine optimizer_run
496
497 ! ========================================================================== !
498 ! Helper routines
499
509 subroutine optimizer_print_status(this, stop_flag, iter)
510 class(optimizer_t), intent(in) :: this
511 integer, intent(in) :: stop_flag
512 integer, intent(in) :: iter
513 character(len=256) :: msg
514
515 select case (stop_flag)
516 case (0)
517 write(msg, '(A,I0,A)') 'Optimizer converged successfully after ', &
518 iter, ' iterations.'
519 call neko_log%message(msg)
520 case (1)
521 write(msg, '(A,I0,A)') 'Optimizer did not converge in ', &
522 this%max_iterations, ' iterations.'
523 call neko_log%warning(msg)
524 case (2)
525 write(msg, '(A,A,F8.2,A)') 'Optimizer stopped after reaching the ', &
526 'maximum runtime of ', this%max_runtime, ' seconds.'
527 call neko_error(trim(msg))
528 case (3)
529 write(msg, '(A)') 'Optimizer stopped due to runtime limit.'
530 call neko_error(msg)
531
532 case default
533 write(msg, '(A)') 'Optimizer stopped for an unknown reason.'
534 call neko_error(msg)
535 end select
536 end subroutine optimizer_print_status
537
544 function optimizer_out_of_time(this, step_time) result(out_of_time)
545 class(optimizer_t), intent(inout) :: this
546 real(kind=rp), intent(in) :: step_time
547 logical :: out_of_time
548 real(kind=rp) :: elapsed_time, time, old_avg_weight
549
550 out_of_time = .false.
551
552 if (this%max_runtime .lt. 0.0_rp) then
553 return
554 end if
555
556 call mpi_allreduce(step_time, time, 1, mpi_real_precision, mpi_max, &
557 neko_comm)
558
559 elapsed_time = mpi_wtime() - this%start_time
560 this%step_count = this%step_count + 1.0_rp
561 old_avg_weight = (this%step_count - 1) / this%step_count
562
563 ! Estimate Cumulative Average iteration time
564 this%average_time = time / this%step_count + &
565 this%average_time * old_avg_weight
566
567 ! Determine if next iteration would exceed max runtime
568 out_of_time = (elapsed_time + this%average_time) .gt. this%max_runtime
569
570 end function optimizer_out_of_time
571
572 ! ========================================================================== !
573 ! Logging helpers
574
581 subroutine optimizer_init_log(this, problem, extra_headers, &
582 include_constraints, filename)
583 class(optimizer_t), intent(inout) :: this
584 class(problem_t), intent(in) :: problem
585 character(len=*), intent(in), optional :: extra_headers(:)
586 logical, intent(in), optional :: include_constraints
587 character(len=*), intent(in), optional :: filename
588
589 character(len=4096) :: header
590 integer :: total_size, base_size, i, n_cont
591 character(len=256) :: log_name
592
593 if (present(include_constraints)) then
594 this%log_include_constraints = include_constraints
595 end if
596
597 n_cont = nekotop_continuation%get_n_params()
598 base_size = problem%get_log_size(this%log_include_constraints)
599 this%log_extra_size = 0
600 if (present(extra_headers)) this%log_extra_size = size(extra_headers)
601
602 total_size = 1 + base_size + this%log_extra_size + 1 + n_cont
603 call this%log_data%init(total_size)
604
605 if (present(filename)) then
606 log_name = trim(filename)
607 else
608 log_name = 'optimization_data.csv'
609 end if
610
611 call this%log_file%init(trim(log_name))
612
613 header = 'iter, ' // &
614 trim(problem%get_log_header(this%log_include_constraints))
615 if (present(extra_headers)) then
616 do i = 1, size(extra_headers)
617 if (trim(extra_headers(i)) .eq. '') then
618 call neko_error('some headers are empty')
619 end if
620 header = trim(header) // ', ' // trim(extra_headers(i))
621 end do
622 end if
623
624 header = trim(header) // ', max_design_change'
625
626 ! continuation parameters
627 do i = 1, n_cont
628 header = trim(header) // ', ' // &
629 trim(nekotop_continuation%get_param_name(i))
630 end do
631 call this%log_file%set_header(trim(header))
632
633 this%log_initialized = .true.
634 end subroutine optimizer_init_log
635
641 subroutine optimizer_write_log(this, iter, problem, extra_values)
642 class(optimizer_t), intent(inout) :: this
643 integer, intent(in) :: iter
644 class(problem_t), intent(in) :: problem
645 real(kind=rp), intent(in), optional :: extra_values(:)
646 integer :: base_size, offset, n_cont, i
647
648 if (.not. this%log_initialized) return
649
650 ! Number of continuation parameters
651 n_cont = nekotop_continuation%get_n_params()
652
653 base_size = problem%get_log_size(this%log_include_constraints)
654 this%log_data%x(1) = real(iter, kind=rp)
655
656 call problem%get_log_values( &
657 this%log_data%x(2:1 + base_size), &
658 this%log_include_constraints)
659
660 offset = 2 + base_size
661 if (present(extra_values)) then
662 if (this%log_extra_size .eq. 0) then
663 call neko_error('got extra values but no headers')
664 end if
665 this%log_data%x(offset:offset + size(extra_values) - 1) = extra_values
666 end if
667
668 ! Save maximum design change
669 offset = offset + this%log_extra_size
670 this%log_data%x(offset:offset + 1 - 1) = this%max_design_change
671
672 ! Continuation parameter values
673 offset = offset + 1
674 do i = 1, n_cont
675 this%log_data%x(offset + i) = &
676 nekotop_continuation%params(i)%target
677 end do
678
679 call this%log_file%write(this%log_data)
680
681 end subroutine optimizer_write_log
682
683 ! ========================================================================== !
684 ! IO Functions
685
695 function optimizer_checkpoint_filename(this, path, basename, format) &
696 result(file_full)
697 class(optimizer_t), intent(in) :: this
698 character(len=*), intent(in), optional :: path
699 character(len=*), intent(in), optional :: basename
700 character(len=*), intent(in), optional :: format
701 character(len=256) :: file_full
702 character(len=:), allocatable :: checkpoint_format
703 character(len=256) :: file_path, file_base, file_ext
704
705 file_path = trim(this%checkpoint_path)
706 file_base = trim(this%checkpoint_base)
707 checkpoint_format = trim(this%checkpoint_format)
708
709 if (present(path)) file_path = trim(path)
710 if (present(basename)) file_base = trim(basename)
711 if (present(format)) checkpoint_format = trim(format)
712
713 if (len_trim(file_path) .eq. 0) then
714 file_path = './'
715 else if (file_path(len_trim(file_path):len_trim(file_path)) &
716 .ne. '/') then
717 file_path = trim(file_path) // '/'
718 end if
719
720 select case (trim(checkpoint_format))
721 case ('h5', 'hdf5', 'hf5', 'hdf')
722 file_ext = 'h5'
723 case default
724 call neko_error('optimizer: Unsupported checkpoint format: "' // &
725 trim(checkpoint_format) // '"')
726 end select
727
728 write(file_full, '(4A)') &
729 trim(file_path), trim(file_base), ".", trim(file_ext)
730
731 end function optimizer_checkpoint_filename
732
741 subroutine optimizer_save_checkpoint(this, iter, design, overwrite, &
742 path, basename, format)
743 class(optimizer_t), intent(inout) :: this
744 integer, intent(in) :: iter
745 class(design_t), intent(inout) :: design
746 logical, intent(in) :: overwrite
747 character(len=*), intent(in), optional :: path
748 character(len=*), intent(in), optional :: basename
749 character(len=*), intent(in), optional :: format
750 character(len=:), allocatable :: checkpoint_format
751 character(len=256) :: file_path, file_base, file_ext, file_full
752 character(len=LOG_SIZE) :: msg
753 real(kind=rp) :: t_start, t_total
754 logical :: exist
755
756 call neko_log%section('Optimizer checkpoint')
757 t_start = mpi_wtime()
758
759 ! Set default behaviour
760 file_path = trim(this%checkpoint_path)
761 file_base = trim(this%checkpoint_base)
762 checkpoint_format = trim(this%checkpoint_format)
763
764 ! Overwrite any user supplied components
765 if (present(path)) file_path = trim(path)
766 if (present(basename)) file_base = trim(basename)
767 if (present(format)) checkpoint_format = trim(format)
768
769 ! Make sure path is valid and exists
770 if (len_trim(file_path) .eq. 0) then
771 file_path = './'
772 else if (file_path(len_trim(file_path):len_trim(file_path)) .ne. '/') then
773 file_path = trim(file_path) // '/'
774 end if
775
776 inquire(file=file_path, exist=exist)
777 if (.not. exist) then
778 call execute_command_line('mkdir -p "' // trim(file_path) // '"')
779 end if
780
781 select case (trim(checkpoint_format))
782 case ('h5', 'hdf5', 'hf5', 'hdf')
783 file_ext = 'h5'
784 case default
785 call neko_error('optimizer: Unsupported checkpoint format: "' // &
786 trim(checkpoint_format) // '"')
787 end select
788
789 ! Construct the full filename based on overwrite flag
790 if (overwrite) then
791 write(file_full, '(4A)') &
792 trim(file_path), trim(file_base), ".", trim(file_ext)
793 else
794 write(file_full, '(3A,I5.5,2A)') &
795 trim(file_path), trim(file_base), "_", iter, ".", trim(file_ext)
796 end if
797
798 call neko_log%message('Save general optimizer components')
799 select case (trim(file_ext))
800 case ('h5', 'hdf5', 'hf5')
801 call optimizer_save_checkpoint_hdf5(this, file_full, iter, overwrite)
802 case default
803 call neko_error('optimizer: Unsupported checkpoint format: "' // &
804 trim(file_ext) // '"')
805 end select
806
807 call neko_log%message('Saving components of ' // this%optimizer_type)
808 call this%save_checkpoint_components(file_full, overwrite)
809
810 call neko_log%message('Save design checkpoint')
811 call design%save_checkpoint(file_full, overwrite)
812
813 t_total = mpi_wtime() - t_start
814 write(msg, '(A,F6.2)') "Checkpoint time: ", t_total
815 call neko_log%end_section(msg)
816
817 end subroutine optimizer_save_checkpoint
818
831 subroutine optimizer_load_checkpoint(this, filename, iter, design, &
832 path, basename, format)
833 class(optimizer_t), intent(inout) :: this
834 character(len=*), intent(in), optional :: filename
835 integer, intent(out) :: iter
836 class(design_t), intent(inout) :: design
837 character(len=*), intent(in), optional :: path
838 character(len=*), intent(in), optional :: basename
839 character(len=*), intent(in), optional :: format
840 character(len=256) :: file_full
841 character(len=12) :: suffix
842
843 if (present(filename)) then
844 file_full = trim(filename)
845 else
846 file_full = optimizer_checkpoint_filename(this, path, basename, format)
847 end if
848
849 ! Get the file extension
850 call filename_suffix(trim(file_full), suffix)
851
852 select case (trim(suffix))
853 case ('h5', 'hdf5', 'hf5')
854 call optimizer_load_checkpoint_hdf5(this, trim(file_full), iter)
855 case default
856 call neko_error('optimizer: Unsupported checkpoint format: "' // &
857 trim(suffix) // '"')
858 end select
859
860 call this%load_checkpoint_components(trim(file_full))
861 call design%load_checkpoint(trim(file_full))
862
863 ! Set the current iteration to the loaded iteration
864 this%current_iteration = iter
865
866 if (pe_rank .eq. 0) then
867 write(*,*) 'Restarted simulation from checkpoint.'
868 write(*,*) ' Checkpoint file: "', trim(file_full), '"'
869 write(*,*) ' Iteration : ', this%current_iteration
870 end if
871
872 end subroutine optimizer_load_checkpoint
873
874 ! ========================================================================== !
875 ! Dummy implementations for module procedures
876
877#if !HAVE_HDF5
878 module subroutine optimizer_save_checkpoint_hdf5(object, filename, iter, &
879 overwrite)
880 class(optimizer_t), intent(inout) :: object
881 character(len=*), intent(in) :: filename
882 integer, intent(in) :: iter
883 logical, intent(in), optional :: overwrite
884 call neko_error('optimizer: HDF5 support not enabled rebuild with ' // &
885 'HAVE_HDF5')
886 end subroutine optimizer_save_checkpoint_hdf5
887
888 module subroutine optimizer_load_checkpoint_hdf5(object, filename, iter)
889 class(optimizer_t), intent(inout) :: object
890 character(len=*), intent(in) :: filename
891 integer, intent(out) :: iter
892 call neko_error('optimizer: HDF5 support not enabled rebuild with ' // &
893 'HAVE_HDF5')
894 end subroutine optimizer_load_checkpoint_hdf5
895#endif
896
897end module optimizer
Factory function for the optimizer.
Interface for optimizer initialization.
Continuation scheduler for the optimization loop.
Implements the design_t.
Definition design.f90:36
Defines the abstract type optimizer.
Definition optimizer.f90:40
Module for handling the optimization problem.
Definition problem.f90:41
Implements the steady_problem_t type.
An abstract design type.
Definition design.f90:53
Abstract optimizer class.
Definition optimizer.f90:60
The abstract problem type.
Definition problem.f90:67