Octopus
iteration_counter.F90
Go to the documentation of this file.
1!! Copyright (C) 2020 Heiko Appel, M. Oliveira
2!! Copyright (C) 2021 I-Te Lu
3!! Copyright (C) 2023 M. Oliveira
4!!
5!! This program is free software; you can redistribute it and/or modify
6!! it under the terms of the GNU General Public License as published by
7!! the Free Software Foundation; either version 2, or (at your option)
8!! any later version.
9!!
10!! This program is distributed in the hope that it will be useful,
11!! but WITHOUT ANY WARRANTY; without even the implied warranty of
12!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13!! GNU General Public License for more details.
14!!
15!! You should have received a copy of the GNU General Public License
16!! along with this program; if not, write to the Free Software
17!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18!! 02110-1301, USA.
19!!
20
22 use, intrinsic :: iso_fortran_env
23 use global_oct_m
24 use io_oct_m
28
29 implicit none
30 private
31
32 public :: iteration_counter_t
33
61 integer :: iteration = 0
62 integer(int64) :: step = -1
63 integer(int64) :: global_iteration = 0
64 procedure(get_value), pointer, public :: value => null()
65 ! !! in the global reference frame (e.g., the time of a clock)
66 contains
67 procedure :: set => iteration_counter_set
68 procedure :: counter => iteration_counter_counter
69 procedure :: global_step => iteration_counter_global_step
70 procedure :: reset => iteration_counter_reset
71 procedure :: add => iteration_counter_add
72 procedure :: subtract => iteration_counter_subtract
73 procedure :: is_equal => iteration_counter_is_equal
74 procedure :: is_different => iteration_counter_is_different
75 procedure :: is_earlier => iteration_counter_is_earlier
76 procedure :: is_later => iteration_counter_is_later
77 procedure :: is_equal_or_earlier => iteration_counter_is_equal_or_earlier
78 procedure :: is_equal_or_later => iteration_counter_is_equal_or_later
79 procedure :: restart_write => iteration_counter_restart_write
80 procedure :: restart_read => iteration_counter_restart_read
81 ! Operators
82 generic :: operator(+) => add
83 generic :: operator(-) => subtract
84 generic :: operator(.eq.) => is_equal
85 generic :: operator(/=) => is_different
86 generic :: operator(.lt.) => is_earlier
87 generic :: operator(.gt.) => is_later
88 generic :: operator(.le.) => is_equal_or_earlier
89 generic :: operator(.ge.) => is_equal_or_later
92 abstract interface
93 pure real(real64) function get_value(this)
94 import real64
96 class(iteration_counter_t), intent(in) :: this
97 end function get_value
98 end interface
100 interface iteration_counter_t
101 module procedure iteration_counter_constructor
102 end interface iteration_counter_t
103
104contains
105
106 pure type(iteration_counter_t) function iteration_counter_constructor(step, initial_iteration) result(counter)
107 integer(int64), optional, intent(in) :: step
108 integer, optional, intent(in) :: initial_iteration
109
110 if (present(initial_iteration)) then
111 counter%iteration = initial_iteration
112 end if
113 if (present(step)) then
114 counter%step = step
115 else
116 counter%step = 1
117 end if
118 counter%global_iteration = counter%iteration * counter%step
119
120 counter%value => iteration_counter_value
121
123
124 ! ---------------------------------------------------------
125 subroutine iteration_counter_set(this, counter)
126 class(iteration_counter_t), intent(inout) :: this
127 type(iteration_counter_t), intent(in) :: counter
128
129 ! Sanity check: the new iteration must be commensurable with the step
130 if (mod(counter%global_iteration, this%step) /= 0) then
131 message(1) = 'Cannot set iteration counter, as the new iteration is not commensurable with counter step.'
132 call messages_fatal(1)
133 end if
134
135 this%iteration = int(counter%global_iteration / this%step)
136 this%global_iteration = counter%global_iteration
137
138 end subroutine iteration_counter_set
139
140 ! ---------------------------------------------------------
145 pure real(real64) function iteration_counter_value(this) result(value)
146 class(iteration_counter_t), intent(in) :: this
147
148 value = real(this%global_iteration, real64)
149
150 end function iteration_counter_value
152 ! ---------------------------------------------------------
154 pure integer function iteration_counter_counter(this) result(counter)
155 class(iteration_counter_t), intent(in) :: this
156
157 counter = this%iteration
158
159 end function iteration_counter_counter
161 ! ---------------------------------------------------------
162 pure integer(int64) function iteration_counter_global_step(this) result(step)
163 class(iteration_counter_t), intent(in) :: this
164
165 step = this%step
166
169 ! ---------------------------------------------------------
170 function iteration_counter_add(this, n) result(new_counter)
171 class(iteration_counter_t), intent(in) :: this
172 integer, intent(in) :: n
173 type(iteration_counter_t) :: new_counter
174
175 new_counter = this
176 new_counter%iteration = new_counter%iteration + n
177 new_counter%global_iteration = new_counter%iteration * new_counter%step
178
179 end function iteration_counter_add
180
181 ! ---------------------------------------------------------
182 function iteration_counter_subtract(this, n) result(new_counter)
183 class(iteration_counter_t), intent(in) :: this
184 integer, intent(in) :: n
185 type(iteration_counter_t) :: new_counter
186
187 new_counter = this
188 new_counter%iteration = new_counter%iteration - n
189 new_counter%global_iteration = new_counter%iteration * new_counter%step
190
191 end function iteration_counter_subtract
192
193 ! ---------------------------------------------------------
194 pure subroutine iteration_counter_reset(this)
195 class(iteration_counter_t), intent(inout) :: this
196
197 this%iteration = 0
198 this%global_iteration = 0
199
201
202 ! ---------------------------------------------------------
203 elemental logical function iteration_counter_is_earlier(counter_a, counter_b) result(is_earlier)
204 class(iteration_counter_t), intent(in) :: counter_a, counter_b
205
206 is_earlier = counter_a%global_iteration < counter_b%global_iteration
207
210 ! ---------------------------------------------------------
211 elemental logical function iteration_counter_is_later(counter_a, counter_b) result(is_later)
212 class(iteration_counter_t), intent(in) :: counter_a, counter_b
213
214 is_later = counter_a%global_iteration > counter_b%global_iteration
215
216 end function iteration_counter_is_later
218 ! ---------------------------------------------------------
219 elemental logical function iteration_counter_is_equal_or_earlier(counter_a, counter_b) result(is_equal_or_earlier)
220 class(iteration_counter_t), intent(in) :: counter_a, counter_b
221
222 is_equal_or_earlier = counter_a%global_iteration <= counter_b%global_iteration
223
226 ! ---------------------------------------------------------
227 elemental logical function iteration_counter_is_equal_or_later(counter_a, counter_b) result(is_equal_or_later)
228 class(iteration_counter_t), intent(in) :: counter_a, counter_b
229
230 is_equal_or_later = counter_a%global_iteration >= counter_b%global_iteration
231
234 ! ---------------------------------------------------------
235 elemental logical function iteration_counter_is_equal(counter_a, counter_b) result(are_equal)
236 class(iteration_counter_t), intent(in) :: counter_a, counter_b
237
238 are_equal = counter_a%global_iteration == counter_b%global_iteration
239
240 end function iteration_counter_is_equal
242 ! ---------------------------------------------------------
243 elemental logical function iteration_counter_is_different(counter_a, counter_b) result(are_diff)
244 class(iteration_counter_t), intent(in) :: counter_a, counter_b
245
246 are_diff = counter_a%global_iteration /= counter_b%global_iteration
247
250 ! ---------------------------------------------------------
251 subroutine iteration_counter_restart_write(this, filename, namespace)
252 class(iteration_counter_t), intent(in) :: this
253 character(len=*), intent(in) :: filename
254 type(namespace_t), intent(in) :: namespace
255
256 type(restart_basic_t) :: restart
257 integer :: restart_file_unit
258 integer :: ierr
259
260 call restart%init(namespace, restart_iteration, restart_type_dump, ierr)
261
262 if (ierr == 0) then
263 restart_file_unit = restart%open(filename)
264 if (restart%do_i_write()) write(restart_file_unit, *) this%iteration, this%step
265 call restart%close(restart_file_unit)
266 else
267 write(message(1), *) "Could not write restart file '",trim(filename),"'."
268 call messages_warning(1)
269 end if
270 call restart%end()
271
273
274 ! ---------------------------------------------------------
275 logical function iteration_counter_restart_read(this, filename, namespace) result(success)
276 class(iteration_counter_t), intent(inout) :: this
277 character(len=*), intent(in) :: filename
278 type(namespace_t), intent(in) :: namespace
279
280 type(restart_basic_t) :: restart
281 integer :: restart_file_unit
282 integer :: ierr
283
284 call restart%init(namespace, restart_iteration, restart_type_load, ierr)
285
286 if (ierr == 0) then
287 restart_file_unit = restart%open(filename)
288 read(restart_file_unit, *) this%iteration, this%step
289 call restart%close(restart_file_unit)
290 this%global_iteration = this%iteration * this%step
291
292 end if
293
294 call restart%end()
295
296 success = (ierr == 0)
297
299
Definition: io.F90:116
pure subroutine iteration_counter_reset(this)
elemental logical function iteration_counter_is_equal(counter_a, counter_b)
elemental logical function iteration_counter_is_equal_or_earlier(counter_a, counter_b)
elemental logical function iteration_counter_is_different(counter_a, counter_b)
pure integer(int64) function iteration_counter_global_step(this)
logical function iteration_counter_restart_read(this, filename, namespace)
pure real(real64) function iteration_counter_value(this)
Returns the value of the counter in the common reference frame.
pure integer function iteration_counter_counter(this)
Returns the value of the counter in the local reference frame.
subroutine iteration_counter_restart_write(this, filename, namespace)
elemental logical function iteration_counter_is_earlier(counter_a, counter_b)
pure type(iteration_counter_t) function iteration_counter_constructor(step, initial_iteration)
subroutine iteration_counter_set(this, counter)
type(iteration_counter_t) function iteration_counter_subtract(this, n)
elemental logical function iteration_counter_is_equal_or_later(counter_a, counter_b)
type(iteration_counter_t) function iteration_counter_add(this, n)
elemental logical function iteration_counter_is_later(counter_a, counter_b)
This class implements the iteration counter used by the multisystem algorithms. As any iteration coun...