Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
checkpoint_linear.f90
1
34!
35
45submodule(state_recover_checkpoint) checkpoint_linear
46 use num_types, only: dp
47 use simulation, only: simulation_step, simulation_restart
48 use time_step_controller, only: time_step_controller_t
49 use profiler, only: profiler_start_region, profiler_end_region
50
51contains
52
56 module subroutine checkpoint_save_linear(this)
57 class(state_recover_checkpoint_t), intent(inout) :: this
58 integer :: index, tstep, counter, n_total
59 real(kind=rp) :: time, start_time, end_time, dt
60
61 time = this%neko_case%time%t
62 dt = this%neko_case%time%dt
63 tstep = this%neko_case%time%tstep
64 start_time = this%neko_case%time%start_time
65 end_time = this%neko_case%time%end_time
66
67 ! We save to disc only every n_saves_memory time steps
68 index = modulo(tstep, this%n_saves_memory)
69 if (index .eq. 0 .or. tstep .le. this%first_valid_timestep) then
70 this%loaded_checkpoint = tstep
71
72 counter = determine_counter(tstep, this%n_saves_memory, &
73 this%first_valid_timestep)
74
75 call this%chkp_output%set_counter(counter)
76 call profiler_start_region("Checkpoint write to disk")
77 call this%chkp_output%sample(time)
78 call profiler_end_region("Checkpoint write to disk")
79 this%n_saves_disc = this%n_saves_disc + 1
80 end if
81
82 ! Only save to RAM from the last disc checkpoint to the end of the forward
83 ! simulation. With fixed timesteps, the total count and the last disc-save
84 ! timestep are known from the time object.
85 ! Note: the plus 0.5 is to round up to the next integer, as the division can
86 ! be slightly smaller than the actual number of steps due to floating point
87 ! errors.
88 n_total = int(((end_time - start_time) / dt) + 0.5_rp)
89 if (tstep .ge. n_total - modulo(n_total, this%n_saves_memory)) then
90 call this%save_data(index + 1)
91 end if
92
93 end subroutine checkpoint_save_linear
94
99 module subroutine checkpoint_restore_linear(this, tstep)
100 class(state_recover_checkpoint_t), intent(inout) :: this
101 integer, intent(in) :: tstep
102 type(time_step_controller_t) :: dt_controller
103 real(kind=dp) :: loop_start
104 integer :: k, previous_save, next_save, local_idx, counter
105
106 loop_start = mpi_wtime()
107
108 ! Determine the nearest save states on both sides
109 previous_save = tstep - modulo(tstep, this%n_saves_memory)
110 next_save = previous_save + this%n_saves_memory
111
112 ! Before the first valid state we always load from disc and we do not step
113 ! forward in time.
114 if (tstep .lt. this%first_valid_timestep) then
115 previous_save = tstep
116 next_save = previous_save + 1
117 else if (previous_save .lt. this%first_valid_timestep) then
118 previous_save = this%first_valid_timestep
119 end if
120
121 ! Load a new batch of checkpoints if needed
122 if (this%loaded_checkpoint .ne. previous_save) then
123
124 ! Restart the simulation form the checkpoint file
125 counter = determine_counter(previous_save, this%n_saves_memory, &
126 this%first_valid_timestep)
127 call this%chkp_output%set_counter(counter)
128 call profiler_start_region("Checkpoint read from disk")
129 call this%chkp_output%file_%read(this%neko_case%chkp)
130 call profiler_end_region("Checkpoint read from disk")
131 call simulation_restart(this%neko_case, this%neko_case%chkp)
132
133 ! Initialize the time step controller and set the time step
134 call dt_controller%init(this%neko_case%params)
135 this%neko_case%time%tstep = previous_save
136 this%loaded_checkpoint = this%neko_case%time%tstep
137
138 call profiler_start_region("Checkpoint recompute")
139 ! Step through the simulation and store field states in memory
140 do k = previous_save, min(next_save - 1, this%get_n_timesteps())
141
142 ! Do not run simulation step on the first iteration
143 if (k .ne. previous_save) then
144 if (this%neko_case%time%t .ge. this%neko_case%time%end_time) exit
145 call simulation_step(this%neko_case, dt_controller, loop_start)
146 end if
147
148 ! Save the restored state in memory
149 local_idx = modulo(k, this%n_saves_memory) + 1
150 call this%save_data(local_idx)
151 end do
152 call profiler_end_region("Checkpoint recompute")
153 end if
154
155 ! Restore the required time step from memory
156 local_idx = modulo(tstep, this%n_saves_memory) + 1
157 call this%load_data(local_idx)
158 end subroutine checkpoint_restore_linear
159
160 pure function determine_counter(tstep, n_memory, first) result(counter)
161 integer, intent(in) :: tstep, n_memory, first
162 integer :: counter
163
164 if (tstep .le. first) then
165 counter = tstep
166 else
167 counter = first + tstep / n_memory
168 end if
169
170 end function determine_counter
171
172end submodule checkpoint_linear
Checkpoint-based state recovery for adjoint runs.