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 use math, only: neko_eps
56
57 implicit none
58 private
59
61 type, abstract, public :: optimizer_t
62
64 character(len=64), private :: optimizer_type = ''
66 integer, private :: max_iterations = 0
68 integer, private :: current_iteration = 0
70 real(kind=rp), private :: stop_design_change = neko_eps
72 real(kind=rp), public :: max_design_change = 0.0_rp
74 real(kind=rp), public :: norm2_design_change = 0.0_rp
75
76 ! ----------------------------------------------------------------------- !
77 ! Restart related members
78
80 character(len=256), private :: checkpoint_file = ''
81
82 ! Checkpoint related information
83 character(len=256), private :: checkpoint_path = './checkpoints/'
84 character(len=256), private :: checkpoint_base = 'optimizer_checkpoint'
85 character(len=256), private :: checkpoint_format = 'hdf5'
86 integer, private :: checkpoint_interval = -1
87
88 ! Variables for the runtime-based stopping criteria
89 real(kind=rp), private :: max_runtime = -1.0_rp
90 real(kind=rp), private :: start_time = 0.0_rp
91 real(kind=rp), private :: average_time = 0.0_rp
92 real(kind=rp), private :: step_count = 0.0_rp
93
94 ! Logging state
95 logical, private :: log_initialized = .false.
96 logical, private :: log_include_constraints = .true.
97 integer, private :: log_extra_size = 0
98 type(csv_file_t), private :: log_file
99 type(vector_t), private :: log_data
100
101 contains
102
103 ! ---------------------------------------------------------------------- !
104 ! Deferred procedures for specific optimizers
105
107 procedure(optimizer_init_from_json), pass(this), public, deferred :: &
108 init_from_json
110 procedure(optimizer_free), pass(this), public, deferred :: free
111
113 procedure(optimizer_initialize), pass(this), public, deferred :: initialize
115 procedure(optimizer_step), pass(this), public, deferred :: step
117 procedure(optimizer_validate), pass(this), public, deferred :: validate
118
120 procedure(optimizer_write), pass(this), public, deferred :: write
122 procedure(optimizer_save_checkpoint_components), pass(this), deferred :: &
123 save_checkpoint_components
125 procedure(optimizer_load_checkpoint_components), pass(this), deferred :: &
126 load_checkpoint_components
127
129 procedure, pass(this) :: save_checkpoint => optimizer_save_checkpoint
131 procedure, pass(this) :: load_checkpoint => optimizer_load_checkpoint
132
133 ! ----------------------------------------------------------------------- !
134 ! Public procedures
135
137 procedure, pass(this), public :: run => optimizer_run
138
139 ! ----------------------------------------------------------------------- !
140 ! Private procedures
141
143 procedure, pass(this) :: init_base => optimizer_init_base
145 procedure, pass(this) :: free_base => optimizer_free_base
147 procedure, pass(this) :: read_base_settings => optimizer_read_base_settings
149 procedure, pass(this) :: print_status => optimizer_print_status
151 procedure, pass(this) :: out_of_time => optimizer_out_of_time
153 procedure, pass(this) :: init_log => optimizer_init_log
155 procedure, pass(this) :: write_log => optimizer_write_log
156 end type optimizer_t
157
158 ! -------------------------------------------------------------------------- !
159 ! Interface for the optimizer module.
160
161 abstract interface
162
163 subroutine optimizer_init_from_json(this, parameters, problem, design, &
164 simulation)
165 import optimizer_t, json_file, simulation_t, problem_t, design_t, rp
166 class(optimizer_t), intent(inout) :: this
167 type(json_file), intent(inout) :: parameters
168 class(problem_t), intent(inout) :: problem
169 class(design_t), intent(in) :: design
170 type(simulation_t), optional, intent(in) :: simulation
171 end subroutine optimizer_init_from_json
172
176 subroutine optimizer_initialize(this, problem, design, simulation)
178 class(optimizer_t), intent(inout) :: this
179 class(problem_t), intent(inout) :: problem
180 class(design_t), intent(inout) :: design
181 type(simulation_t), optional, intent(inout) :: simulation
182 end subroutine optimizer_initialize
183
185 subroutine optimizer_free(this)
186 import optimizer_t
187 class(optimizer_t), intent(inout) :: this
188 end subroutine optimizer_free
189
191 logical function optimizer_step(this, iter, problem, design, simulation)
193 class(optimizer_t), intent(inout) :: this
194 integer, intent(in) :: iter
195 class(problem_t), intent(inout) :: problem
196 class(design_t), intent(inout) :: design
197 type(simulation_t), optional, intent(inout) :: simulation
198 end function optimizer_step
199
201 subroutine optimizer_validate(this, problem, design)
203 class(optimizer_t), intent(inout) :: this
204 class(problem_t), intent(in) :: problem
205 class(design_t), intent(in) :: design
206 end subroutine optimizer_validate
207
209 subroutine optimizer_write(this, iter, problem)
211 class(optimizer_t), intent(inout) :: this
212 integer, intent(in) :: iter
213 class(problem_t), intent(inout) :: problem
214 end subroutine optimizer_write
215
217 subroutine optimizer_save_checkpoint_components(this, filename, overwrite)
218 import optimizer_t
219 class(optimizer_t), intent(inout) :: this
220 character(len=*), intent(in) :: filename
221 logical, intent(in), optional :: overwrite
222 end subroutine optimizer_save_checkpoint_components
223
225 subroutine optimizer_load_checkpoint_components(this, filename)
226 import optimizer_t
227 class(optimizer_t), intent(inout) :: this
228 character(len=*), intent(in) :: filename
229 end subroutine optimizer_load_checkpoint_components
230
231 end interface
232
233 ! -------------------------------------------------------------------------- !
234 ! Interfaces for the factory functions
235
243 module subroutine optimizer_factory(object, parameters, problem, design, &
244 simulation)
245 class(optimizer_t), allocatable, intent(inout) :: object
246 type(json_file), intent(inout) :: parameters
247 class(problem_t), intent(inout) :: problem
248 class(design_t), intent(in) :: design
249 type(simulation_t), optional, intent(in) :: simulation
250 end subroutine optimizer_factory
251 end interface optimizer_factory
252
253 ! -------------------------------------------------------------------------- !
254 ! IO routines for HDF5 checkpoints
255
256 interface
257
258 module subroutine optimizer_save_checkpoint_hdf5(object, filename, iter, &
259 overwrite)
260 class(optimizer_t), intent(inout) :: object
261 character(len=*), intent(in) :: filename
262 integer, intent(in) :: iter
263 logical, intent(in), optional :: overwrite
264 end subroutine optimizer_save_checkpoint_hdf5
265
267 module subroutine optimizer_load_checkpoint_hdf5(object, filename, iter)
268 class(optimizer_t), intent(inout) :: object
269 character(len=*), intent(in) :: filename
270 integer, intent(out) :: iter
271 end subroutine optimizer_load_checkpoint_hdf5
272 end interface
273
274 public :: optimizer_factory
275
276contains
277
278 ! -------------------------------------------------------------------------- !
279 ! Base initializer and free routines
280
293 subroutine optimizer_init_base(this, optimizer_type, max_iterations, &
294 max_runtime, stop_design_change, checkpoint_file, checkpoint_path, &
295 checkpoint_base, checkpoint_format, checkpoint_interval)
296 class(optimizer_t), intent(inout) :: this
297 character(len=*), intent(in) :: optimizer_type
298 integer, intent(in) :: max_iterations
299 real(kind=rp), intent(in), optional :: max_runtime
300 real(kind=rp), intent(in), optional :: stop_design_change
301 character(len=*), intent(in), optional :: checkpoint_file
302 character(len=*), intent(in), optional :: checkpoint_path
303 character(len=*), intent(in), optional :: checkpoint_base
304 character(len=*), intent(in), optional :: checkpoint_format
305 integer, intent(in), optional :: checkpoint_interval
306
307 ! Mandatory settings
308 this%optimizer_type = optimizer_type
309 this%max_iterations = max_iterations
310
311 ! Optional settings
312 if (present(max_runtime)) this%max_runtime = max_runtime
313 if (present(stop_design_change)) this%stop_design_change = stop_design_change
314 if (present(checkpoint_file)) this%checkpoint_file = checkpoint_file
315 if (present(checkpoint_path)) this%checkpoint_path = checkpoint_path
316 if (present(checkpoint_base)) this%checkpoint_base = checkpoint_base
317 if (present(checkpoint_format)) this%checkpoint_format = checkpoint_format
318 if (present(checkpoint_interval)) then
319 this%checkpoint_interval = checkpoint_interval
320 end if
321
322 ! Initialize internals
323 this%start_time = mpi_wtime()
324
325 end subroutine optimizer_init_base
326
329 subroutine optimizer_free_base(this)
330 class(optimizer_t), intent(inout) :: this
331
332 this%optimizer_type = ''
333 this%max_iterations = 0
334 this%max_runtime = -1.0_rp
335 this%stop_design_change = -1.0_rp
336 this%max_design_change = 0.0_rp
337 this%checkpoint_file = ''
338 this%checkpoint_path = './checkpoints/'
339 this%checkpoint_base = 'optimizer_checkpoint'
340 this%checkpoint_format = 'hdf5'
341 this%checkpoint_interval = -1
342
343 this%start_time = 0.0_rp
344 this%current_iteration = 0
345 call this%log_data%free()
346 this%log_initialized = .false.
347 this%log_extra_size = 0
348 this%log_include_constraints = .true.
349
350 ! Most files have no "free" method, must be done manually here
351 this%log_file%header = ''
352 this%log_file%header_is_written = .false.
353 call this%log_file%set_overwrite(.false.)
354
355 end subroutine optimizer_free_base
356
360 subroutine optimizer_read_base_settings(this, solver_params)
361 class(optimizer_t), intent(inout) :: this
362 type(json_file), intent(inout) :: solver_params
363 integer :: read_int
364 character(len=:), allocatable :: read_str
365
366 call json_get_or_default(solver_params, 'max_runtime', read_str, "")
367 call read_duration(read_str, this%max_runtime)
368 call json_get_or_default(solver_params, 'stop_design_change', &
369 this%stop_design_change, neko_eps)
370
371 call json_get_or_default(solver_params, 'restart_file', read_str, &
372 this%checkpoint_file)
373 this%checkpoint_file = read_str
374
375 call json_get_or_default(solver_params, 'checkpoint.path', read_str, &
376 this%checkpoint_path)
377 this%checkpoint_path = read_str
378 call json_get_or_default(solver_params, 'checkpoint.base', read_str, &
379 this%checkpoint_base)
380 this%checkpoint_base = read_str
381 call json_get_or_default(solver_params, 'checkpoint.format', read_str, &
382 this%checkpoint_format)
383 this%checkpoint_format = read_str
384 call json_get_or_default(solver_params, 'checkpoint.interval', read_int, &
385 this%checkpoint_interval)
386 this%checkpoint_interval = read_int
387
388 end subroutine optimizer_read_base_settings
389
390 ! -------------------------------------------------------------------------- !
391 ! Optimization loop routine
392
405 subroutine optimizer_run(this, problem, design, simulation)
406 class(optimizer_t), intent(inout) :: this
407 class(problem_t), intent(inout) :: problem
408 class(design_t), intent(inout) :: design
409 type(simulation_t), optional, intent(inout) :: simulation
410 real(kind=rp) :: iteration_time
411 character(len=1024) :: checkpoint_file
412 logical :: converged, file_exists
413 integer :: stop_flag
414
415 ! Initialize variables
416 stop_flag = 1
417 converged = .false.
418
419 ! Restart from checkpoint if available
420 if (trim(this%checkpoint_file) .ne. '') then
421 checkpoint_file = trim(this%checkpoint_file)
422 else
423 checkpoint_file = optimizer_checkpoint_filename(this, &
424 basename = 'optimizer_rt_checkpoint')
425 end if
426
427 inquire(file = checkpoint_file, exist = file_exists)
428 if (file_exists) then
429 call this%load_checkpoint(checkpoint_file, this%current_iteration, &
430 design)
431 end if
432
433 ! compute potential internals for for a potential restart
434 if (this%current_iteration .ne. 0) then
435 call design%set_output_counter(this%current_iteration - 1)
436 if (present(simulation)) then
437 call simulation%set_output_counter(this%current_iteration - 1)
438 end if
439 end if
440
441 ! Prepare the problem state before starting the optimization
442 if (present(simulation)) then
443 call simulation%set_design_iteration(this%current_iteration)
444 end if
445 call this%initialize(problem, design, simulation)
446
447 ! Log the initial state of the problem.
448 if (this%current_iteration .eq. 0) then
449 call this%write(this%current_iteration, problem)
450 end if
451
452 ! Save the current design state.
453 call design%write(this%current_iteration)
454
455 call neko_log%section('Optimization Loop')
456
457 do while (this%current_iteration .lt. this%max_iterations)
458 this%current_iteration = this%current_iteration + 1
459 if (pe_rank .eq. 0) then
460 write(*,*) 'Starting iteration ', this%current_iteration
461 end if
462
463 call profiler_start_region('Optimizer iteration')
464 iteration_time = mpi_wtime()
465
466 ! Update the parameters in continuation scheduler
467 call nekotop_continuation%update(this%current_iteration)
468
469 if (present(simulation)) then
470 call simulation%set_design_iteration(this%current_iteration)
471 end if
472 converged = this%step(this%current_iteration, problem, design, &
473 simulation)
474
475 iteration_time = mpi_wtime() - iteration_time
476 call profiler_end_region('Optimizer iteration')
477
478 ! Log the progress and outputs
479 call this%write(this%current_iteration, problem)
480 call design%write(this%current_iteration)
481
482 ! Save checkpoint if enabled
483 if (this%checkpoint_interval .gt. 0 .and. &
484 mod(this%current_iteration, this%checkpoint_interval) == 0) then
485 call this%save_checkpoint(this%current_iteration, design, .false.)
486 end if
487
488 ! --------------------------------------------------------------------- !
489 ! Check stopping criteria
490
491 if (converged) then
492 stop_flag = 0
493 exit
494 else if (this%current_iteration .ge. this%max_iterations) then
495 stop_flag = 1
496 exit
497 else if (this%max_design_change .lt. this%stop_design_change) then
498 stop_flag = 2
499 exit
500 else if (this%out_of_time(iteration_time)) then
501 call this%save_checkpoint(this%current_iteration, design, .true., &
502 basename = 'optimizer_rt_checkpoint')
503 stop_flag = 3
504 exit
505 end if
506 end do
507
508 ! Check that the final design is valid
509 call this%validate(problem, design)
510 call this%print_status(stop_flag, this%current_iteration)
511
512 call neko_log%end_section()
513
514 end subroutine optimizer_run
515
516 ! ========================================================================== !
517 ! Helper routines
518
528 subroutine optimizer_print_status(this, stop_flag, iter)
529 class(optimizer_t), intent(in) :: this
530 integer, intent(in) :: stop_flag
531 integer, intent(in) :: iter
532 character(len=256) :: msg
533
534 select case (stop_flag)
535 case (0)
536 write(msg, '(A,I0,A)') 'Optimizer converged successfully after ', &
537 iter, ' iterations.'
538 call neko_log%message(msg)
539 case (1)
540 write(msg, '(A,I0,A)') 'Optimizer did not converge in ', &
541 this%max_iterations, ' iterations.'
542 call neko_log%warning(msg)
543 case (2)
544 write(msg, '(A,A,F8.2,A)') 'Optimizer stopped, design change ', &
545 'below threshold of: ', this%stop_design_change, '.'
546 call neko_log%warning(msg)
547 case (3)
548 write(msg, '(A)') 'Optimizer stopped due to runtime limit.'
549 call neko_error(msg)
550
551 case default
552 write(msg, '(A)') 'Optimizer stopped for an unknown reason.'
553 call neko_error(msg)
554 end select
555 end subroutine optimizer_print_status
556
563 function optimizer_out_of_time(this, step_time) result(out_of_time)
564 class(optimizer_t), intent(inout) :: this
565 real(kind=rp), intent(in) :: step_time
566 logical :: out_of_time
567 real(kind=rp) :: elapsed_time, time, old_avg_weight
568
569 out_of_time = .false.
570
571 if (this%max_runtime .lt. 0.0_rp) then
572 return
573 end if
574
575 call mpi_allreduce(step_time, time, 1, mpi_real_precision, mpi_max, &
576 neko_comm)
577
578 elapsed_time = mpi_wtime() - this%start_time
579 this%step_count = this%step_count + 1.0_rp
580 old_avg_weight = (this%step_count - 1) / this%step_count
581
582 ! Estimate Cumulative Average iteration time
583 this%average_time = time / this%step_count + &
584 this%average_time * old_avg_weight
585
586 ! Determine if next iteration would exceed max runtime
587 out_of_time = (elapsed_time + this%average_time) .gt. this%max_runtime
588
589 end function optimizer_out_of_time
590
591 ! ========================================================================== !
592 ! Logging helpers
593
602 subroutine optimizer_init_log(this, problem, extra_headers, &
603 include_constraints, filename)
604 class(optimizer_t), intent(inout) :: this
605 class(problem_t), intent(in) :: problem
606 character(len=*), intent(in), optional :: extra_headers(:)
607 logical, intent(in), optional :: include_constraints
608 character(len=*), intent(in), optional :: filename
609
610 character(len=4096) :: header
611 integer :: total_size, base_size, i, n_cont
612 character(len=256) :: log_name
613
614 if (present(include_constraints)) then
615 this%log_include_constraints = include_constraints
616 end if
617
618 n_cont = nekotop_continuation%get_n_params()
619 base_size = problem%get_log_size(this%log_include_constraints)
620 this%log_extra_size = 0
621 if (present(extra_headers)) this%log_extra_size = size(extra_headers)
622
623 total_size = 1 + base_size + this%log_extra_size + 2 + n_cont
624 call this%log_data%init(total_size)
625
626 if (present(filename)) then
627 log_name = trim(filename)
628 else
629 log_name = 'optimization_data.csv'
630 end if
631
632 call this%log_file%init(trim(log_name))
633
634 header = 'iter, ' // &
635 trim(problem%get_log_header(this%log_include_constraints))
636 if (present(extra_headers)) then
637 do i = 1, size(extra_headers)
638 if (trim(extra_headers(i)) .eq. '') then
639 call neko_error('some headers are empty')
640 end if
641 header = trim(header) // ', ' // trim(extra_headers(i))
642 end do
643 end if
644
645 header = trim(header) // ', max_design_change, norm2_design_change'
646
647 ! continuation parameters
648 do i = 1, n_cont
649 header = trim(header) // ', ' // &
650 trim(nekotop_continuation%get_param_name(i))
651 end do
652 call this%log_file%set_header(trim(header))
653
654 this%log_initialized = .true.
655 end subroutine optimizer_init_log
656
662 subroutine optimizer_write_log(this, iter, problem, extra_values)
663 class(optimizer_t), intent(inout) :: this
664 integer, intent(in) :: iter
665 class(problem_t), intent(in) :: problem
666 real(kind=rp), intent(in), optional :: extra_values(:)
667 integer :: base_size, offset, n_cont, i
668
669 if (.not. this%log_initialized) return
670
671 ! Iteration 0 starts a new log; later iterations append to the existing
672 ! log without writing its header again.
673 if (this%current_iteration .eq. 0) then
674 call this%log_file%set_overwrite(.true.)
675 this%log_file%header_is_written = .false.
676 else
677 call this%log_file%set_overwrite(.false.)
678 this%log_file%header_is_written = .true.
679 end if
680
681 ! Number of continuation parameters
682 n_cont = nekotop_continuation%get_n_params()
683
684 base_size = problem%get_log_size(this%log_include_constraints)
685 this%log_data%x(1) = real(iter, kind=rp)
686
687 call problem%get_log_values( &
688 this%log_data%x(2:1 + base_size), &
689 this%log_include_constraints)
690
691 offset = 2 + base_size
692 if (present(extra_values)) then
693 if (this%log_extra_size .eq. 0) then
694 call neko_error('got extra values but no headers')
695 end if
696 this%log_data%x(offset:offset + size(extra_values) - 1) = extra_values
697 end if
698
699 ! Save maximum design change
700 offset = offset + this%log_extra_size
701 this%log_data%x(offset:offset + 1 - 1) = this%max_design_change
702 this%log_data%x(offset + 1:offset + 2 - 1) = this%norm2_design_change
703
704 ! Continuation parameter values
705 offset = offset + 2
706 do i = 1, n_cont
707 this%log_data%x(offset + i) = &
708 nekotop_continuation%params(i)%target
709 end do
710
711 call this%log_file%write(this%log_data)
712
713 end subroutine optimizer_write_log
714
715 ! ========================================================================== !
716 ! IO Functions
717
727 function optimizer_checkpoint_filename(this, path, basename, format) &
728 result(file_full)
729 class(optimizer_t), intent(in) :: this
730 character(len=*), intent(in), optional :: path
731 character(len=*), intent(in), optional :: basename
732 character(len=*), intent(in), optional :: format
733 character(len=256) :: file_full
734 character(len=:), allocatable :: checkpoint_format
735 character(len=256) :: file_path, file_base, file_ext
736
737 file_path = trim(this%checkpoint_path)
738 file_base = trim(this%checkpoint_base)
739 checkpoint_format = trim(this%checkpoint_format)
740
741 if (present(path)) file_path = trim(path)
742 if (present(basename)) file_base = trim(basename)
743 if (present(format)) checkpoint_format = trim(format)
744
745 if (len_trim(file_path) .eq. 0) then
746 file_path = './'
747 else if (file_path(len_trim(file_path):len_trim(file_path)) &
748 .ne. '/') then
749 file_path = trim(file_path) // '/'
750 end if
751
752 select case (trim(checkpoint_format))
753 case ('h5', 'hdf5', 'hf5', 'hdf')
754 file_ext = 'h5'
755 case default
756 call neko_error('optimizer: Unsupported checkpoint format: "' // &
757 trim(checkpoint_format) // '"')
758 end select
759
760 write(file_full, '(4A)') &
761 trim(file_path), trim(file_base), ".", trim(file_ext)
762
763 end function optimizer_checkpoint_filename
764
773 subroutine optimizer_save_checkpoint(this, iter, design, overwrite, &
774 path, basename, format)
775 class(optimizer_t), intent(inout) :: this
776 integer, intent(in) :: iter
777 class(design_t), intent(inout) :: design
778 logical, intent(in) :: overwrite
779 character(len=*), intent(in), optional :: path
780 character(len=*), intent(in), optional :: basename
781 character(len=*), intent(in), optional :: format
782 character(len=:), allocatable :: checkpoint_format
783 character(len=256) :: file_path, file_base, file_ext, file_full
784 character(len=LOG_SIZE) :: msg
785 real(kind=rp) :: t_start, t_total
786 logical :: exist
787
788 call neko_log%section('Optimizer checkpoint')
789 t_start = mpi_wtime()
790
791 ! Set default behaviour
792 file_path = trim(this%checkpoint_path)
793 file_base = trim(this%checkpoint_base)
794 checkpoint_format = trim(this%checkpoint_format)
795
796 ! Overwrite any user supplied components
797 if (present(path)) file_path = trim(path)
798 if (present(basename)) file_base = trim(basename)
799 if (present(format)) checkpoint_format = trim(format)
800
801 ! Make sure path is valid and exists
802 if (len_trim(file_path) .eq. 0) then
803 file_path = './'
804 else if (file_path(len_trim(file_path):len_trim(file_path)) .ne. '/') then
805 file_path = trim(file_path) // '/'
806 end if
807
808 inquire(file=file_path, exist=exist)
809 if (.not. exist) then
810 call execute_command_line('mkdir -p "' // trim(file_path) // '"')
811 end if
812
813 select case (trim(checkpoint_format))
814 case ('h5', 'hdf5', 'hf5', 'hdf')
815 file_ext = 'h5'
816 case default
817 call neko_error('optimizer: Unsupported checkpoint format: "' // &
818 trim(checkpoint_format) // '"')
819 end select
820
821 ! Construct the full filename based on overwrite flag
822 if (overwrite) then
823 write(file_full, '(4A)') &
824 trim(file_path), trim(file_base), ".", trim(file_ext)
825 else
826 write(file_full, '(3A,I5.5,2A)') &
827 trim(file_path), trim(file_base), "_", iter, ".", trim(file_ext)
828 end if
829
830 call neko_log%message('Save general optimizer components')
831 select case (trim(file_ext))
832 case ('h5', 'hdf5', 'hf5')
833 call optimizer_save_checkpoint_hdf5(this, file_full, iter, overwrite)
834 case default
835 call neko_error('optimizer: Unsupported checkpoint format: "' // &
836 trim(file_ext) // '"')
837 end select
838
839 call neko_log%message('Saving components of ' // this%optimizer_type)
840 call this%save_checkpoint_components(file_full, overwrite)
841
842 call neko_log%message('Save design checkpoint')
843 call design%save_checkpoint(file_full, overwrite)
844
845 t_total = mpi_wtime() - t_start
846 write(msg, '(A,F6.2)') "Checkpoint time: ", t_total
847 call neko_log%end_section(msg)
848
849 end subroutine optimizer_save_checkpoint
850
863 subroutine optimizer_load_checkpoint(this, filename, iter, design, &
864 path, basename, format)
865 class(optimizer_t), intent(inout) :: this
866 character(len=*), intent(in), optional :: filename
867 integer, intent(out) :: iter
868 class(design_t), intent(inout) :: design
869 character(len=*), intent(in), optional :: path
870 character(len=*), intent(in), optional :: basename
871 character(len=*), intent(in), optional :: format
872 character(len=256) :: file_full
873 character(len=12) :: suffix
874
875 if (present(filename)) then
876 file_full = trim(filename)
877 else
878 file_full = optimizer_checkpoint_filename(this, path, basename, format)
879 end if
880
881 ! Get the file extension
882 call filename_suffix(trim(file_full), suffix)
883
884 select case (trim(suffix))
885 case ('h5', 'hdf5', 'hf5')
886 call optimizer_load_checkpoint_hdf5(this, trim(file_full), iter)
887 case default
888 call neko_error('optimizer: Unsupported checkpoint format: "' // &
889 trim(suffix) // '"')
890 end select
891
892 call this%load_checkpoint_components(trim(file_full))
893 call design%load_checkpoint(trim(file_full))
894
895 ! Set the current iteration to the loaded iteration
896 this%current_iteration = iter
897
898 if (pe_rank .eq. 0) then
899 write(*,*) 'Restarted simulation from checkpoint.'
900 write(*,*) ' Checkpoint file: "', trim(file_full), '"'
901 write(*,*) ' Iteration : ', this%current_iteration
902 end if
903
904 end subroutine optimizer_load_checkpoint
905
906 ! ========================================================================== !
907 ! Dummy implementations for module procedures
908
909#if !HAVE_HDF5
910 module subroutine optimizer_save_checkpoint_hdf5(object, filename, iter, &
911 overwrite)
912 class(optimizer_t), intent(inout) :: object
913 character(len=*), intent(in) :: filename
914 integer, intent(in) :: iter
915 logical, intent(in), optional :: overwrite
916 call neko_error('optimizer: HDF5 support not enabled rebuild with ' // &
917 'HAVE_HDF5')
918 end subroutine optimizer_save_checkpoint_hdf5
919
920 module subroutine optimizer_load_checkpoint_hdf5(object, filename, iter)
921 class(optimizer_t), intent(inout) :: object
922 character(len=*), intent(in) :: filename
923 integer, intent(out) :: iter
924 call neko_error('optimizer: HDF5 support not enabled rebuild with ' // &
925 'HAVE_HDF5')
926 end subroutine optimizer_load_checkpoint_hdf5
927#endif
928
929end 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:61
The abstract problem type.
Definition problem.f90:68