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