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 :: initial_iteration = 0
63 integer(int64) :: step = -1
64 integer(int64) :: global_iteration = 0
65 procedure(get_value), pointer, public :: value => null()
66 ! !! in the global reference frame (e.g., the time of a clock)
67 contains
68 procedure :: set => iteration_counter_set
69 procedure :: counter => iteration_counter_counter
70 procedure :: global_step => iteration_counter_global_step
71 procedure :: reset => iteration_counter_reset
72 procedure :: add => iteration_counter_add
73 procedure :: subtract => iteration_counter_subtract
74 procedure :: is_equal => iteration_counter_is_equal
75 procedure :: is_different => iteration_counter_is_different
76 procedure :: is_earlier => iteration_counter_is_earlier
77 procedure :: is_later => iteration_counter_is_later
78 procedure :: is_equal_or_earlier => iteration_counter_is_equal_or_earlier
79 procedure :: is_equal_or_later => iteration_counter_is_equal_or_later
80 procedure :: restart_write => iteration_counter_restart_write
81 procedure :: restart_read => iteration_counter_restart_read
82 ! Operators
83 generic :: operator(+) => add
84 generic :: operator(-) => subtract
85 generic :: operator(.eq.) => is_equal
86 generic :: operator(/=) => is_different
87 generic :: operator(.lt.) => is_earlier
88 generic :: operator(.gt.) => is_later
89 generic :: operator(.le.) => is_equal_or_earlier
90 generic :: operator(.ge.) => is_equal_or_later
93 abstract interface
94 pure real(real64) function get_value(this, elapsed)
95 import real64
97 class(iteration_counter_t), intent(in) :: this
98 logical, optional, intent(in) :: elapsed
99 end function get_value
100 end interface
101
102 interface iteration_counter_t
103 module procedure iteration_counter_constructor
104 end interface iteration_counter_t
105
106contains
107
108 pure type(iteration_counter_t) function iteration_counter_constructor(step, initial_iteration) result(counter)
109 integer(int64), optional, intent(in) :: step
110 integer, optional, intent(in) :: initial_iteration
111
112 if (present(initial_iteration)) then
113 counter%iteration = initial_iteration
114 end if
115 if (present(step)) then
116 counter%step = step
117 else
118 counter%step = 1
119 end if
120 counter%global_iteration = counter%iteration * counter%step
121
122 counter%value => iteration_counter_value
123
125
126 ! ---------------------------------------------------------
127 subroutine iteration_counter_set(this, counter)
128 class(iteration_counter_t), intent(inout) :: this
129 type(iteration_counter_t), intent(in) :: counter
130
131 ! Sanity check: the new iteration must be commensurable with the step
132 if (mod(counter%global_iteration, this%step) /= 0) then
133 message(1) = 'Cannot set iteration counter, as the new iteration is not commensurable with counter step.'
134 call messages_fatal(1)
135 end if
136
137 this%iteration = int(counter%global_iteration / this%step)
138 this%global_iteration = counter%global_iteration
139
140 end subroutine iteration_counter_set
141
142 ! ---------------------------------------------------------
147 pure real(real64) function iteration_counter_value(this, elapsed) result(value)
148 class(iteration_counter_t), intent(in) :: this
149 logical, optional, intent(in) :: elapsed
150
151 value = real(this%global_iteration, real64)
152 if (optional_default(elapsed, .false.)) then
153 value = value - real(this%initial_iteration*this%step, real64)
154 end if
155
156 end function iteration_counter_value
157
158 ! ---------------------------------------------------------
160 pure integer function iteration_counter_counter(this) result(counter)
161 class(iteration_counter_t), intent(in) :: this
162
163 counter = this%iteration
164
165 end function iteration_counter_counter
167 ! ---------------------------------------------------------
168 pure integer(int64) function iteration_counter_global_step(this) result(step)
169 class(iteration_counter_t), intent(in) :: this
170
171 step = this%step
172
175 ! ---------------------------------------------------------
176 function iteration_counter_add(this, n) result(new_counter)
177 class(iteration_counter_t), intent(in) :: this
178 integer, intent(in) :: n
179 type(iteration_counter_t) :: new_counter
180
181 new_counter = this
182 new_counter%iteration = new_counter%iteration + n
183 new_counter%global_iteration = new_counter%iteration * new_counter%step
184
185 end function iteration_counter_add
186
187 ! ---------------------------------------------------------
188 function iteration_counter_subtract(this, n) result(new_counter)
189 class(iteration_counter_t), intent(in) :: this
190 integer, intent(in) :: n
191 type(iteration_counter_t) :: new_counter
192
193 new_counter = this
194 new_counter%iteration = new_counter%iteration - n
195 new_counter%global_iteration = new_counter%iteration * new_counter%step
196
197 end function iteration_counter_subtract
198
199 ! ---------------------------------------------------------
200 pure subroutine iteration_counter_reset(this)
201 class(iteration_counter_t), intent(inout) :: this
202
203 this%iteration = 0
204 this%global_iteration = 0
205
207
208 ! ---------------------------------------------------------
209 elemental logical function iteration_counter_is_earlier(counter_a, counter_b) result(is_earlier)
210 class(iteration_counter_t), intent(in) :: counter_a, counter_b
211
212 is_earlier = counter_a%global_iteration < counter_b%global_iteration
213
216 ! ---------------------------------------------------------
217 elemental logical function iteration_counter_is_later(counter_a, counter_b) result(is_later)
218 class(iteration_counter_t), intent(in) :: counter_a, counter_b
219
220 is_later = counter_a%global_iteration > counter_b%global_iteration
221
222 end function iteration_counter_is_later
224 ! ---------------------------------------------------------
225 elemental logical function iteration_counter_is_equal_or_earlier(counter_a, counter_b) result(is_equal_or_earlier)
226 class(iteration_counter_t), intent(in) :: counter_a, counter_b
227
228 is_equal_or_earlier = counter_a%global_iteration <= counter_b%global_iteration
229
232 ! ---------------------------------------------------------
233 elemental logical function iteration_counter_is_equal_or_later(counter_a, counter_b) result(is_equal_or_later)
234 class(iteration_counter_t), intent(in) :: counter_a, counter_b
235
236 is_equal_or_later = counter_a%global_iteration >= counter_b%global_iteration
237
240 ! ---------------------------------------------------------
241 elemental logical function iteration_counter_is_equal(counter_a, counter_b) result(are_equal)
242 class(iteration_counter_t), intent(in) :: counter_a, counter_b
243
244 are_equal = counter_a%global_iteration == counter_b%global_iteration
245
246 end function iteration_counter_is_equal
248 ! ---------------------------------------------------------
249 elemental logical function iteration_counter_is_different(counter_a, counter_b) result(are_diff)
250 class(iteration_counter_t), intent(in) :: counter_a, counter_b
251
252 are_diff = counter_a%global_iteration /= counter_b%global_iteration
253
256 ! ---------------------------------------------------------
257 subroutine iteration_counter_restart_write(this, filename, namespace)
258 class(iteration_counter_t), intent(in) :: this
259 character(len=*), intent(in) :: filename
260 type(namespace_t), intent(in) :: namespace
261
262 type(restart_basic_t) :: restart
263 integer :: restart_file_unit
264 integer :: ierr
265
266 call restart%init(namespace, restart_iteration, restart_type_dump, ierr)
267
268 if (ierr == 0) then
269 restart_file_unit = restart%open(filename)
270 if (restart%do_i_write()) write(restart_file_unit, *) this%iteration, this%step
271 call restart%close(restart_file_unit)
272 else
273 write(message(1), *) "Could not write restart file '",trim(filename),"'."
274 call messages_warning(1)
275 end if
276 call restart%end()
277
279
280 ! ---------------------------------------------------------
281 logical function iteration_counter_restart_read(this, filename, namespace) result(success)
282 class(iteration_counter_t), intent(inout) :: this
283 character(len=*), intent(in) :: filename
284 type(namespace_t), intent(in) :: namespace
285
286 type(restart_basic_t) :: restart
287 integer :: restart_file_unit
288 integer :: ierr
289
290 call restart%init(namespace, restart_iteration, restart_type_load, ierr)
291
292 if (ierr == 0) then
293 restart_file_unit = restart%open(filename)
294 read(restart_file_unit, *) this%iteration, this%step
295 call restart%close(restart_file_unit)
296 this%global_iteration = this%iteration * this%step
297 this%initial_iteration = this%iteration
298 end if
299
300 call restart%end()
301
302 success = (ierr == 0)
303
305
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 integer function iteration_counter_counter(this)
Returns the value of the counter in the local reference frame.
pure real(real64) function iteration_counter_value(this, elapsed)
Returns the value of the counter in the common 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...