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 implicit none
29 private
30
31 public :: iteration_counter_t
32
60 integer :: iteration = 0
61 integer(int64) :: step = -1
62 integer(int64) :: global_iteration = 0
63 procedure(get_value), pointer, public :: value => null()
64 ! !! in the global reference frame (e.g., the time of a clock)
65 contains
66 procedure :: set => iteration_counter_set
67 procedure :: counter => iteration_counter_counter
68 procedure :: global_step => iteration_counter_global_step
69 procedure :: reset => iteration_counter_reset
70 procedure :: add => iteration_counter_add
71 procedure :: subtract => iteration_counter_subtract
72 procedure :: is_equal => iteration_counter_is_equal
73 procedure :: is_different => iteration_counter_is_different
74 procedure :: is_earlier => iteration_counter_is_earlier
75 procedure :: is_later => iteration_counter_is_later
76 procedure :: is_equal_or_earlier => iteration_counter_is_equal_or_earlier
77 procedure :: is_equal_or_later => iteration_counter_is_equal_or_later
78 procedure :: restart_write => iteration_counter_restart_write
79 procedure :: restart_read => iteration_counter_restart_read
80 ! Operators
81 generic :: operator(+) => add
82 generic :: operator(-) => subtract
83 generic :: operator(.eq.) => is_equal
84 generic :: operator(/=) => is_different
85 generic :: operator(.lt.) => is_earlier
86 generic :: operator(.gt.) => is_later
87 generic :: operator(.le.) => is_equal_or_earlier
88 generic :: operator(.ge.) => is_equal_or_later
91 abstract interface
92 pure real(real64) function get_value(this)
93 import real64
95 class(iteration_counter_t), intent(in) :: this
96 end function get_value
97 end interface
99 interface iteration_counter_t
100 module procedure iteration_counter_constructor
101 end interface iteration_counter_t
102
103contains
104
105 pure type(iteration_counter_t) function iteration_counter_constructor(step, initial_iteration) result(counter)
106 integer(int64), optional, intent(in) :: step
107 integer, optional, intent(in) :: initial_iteration
108
109 if (present(initial_iteration)) then
110 counter%iteration = initial_iteration
111 end if
112 if (present(step)) then
113 counter%step = step
114 else
115 counter%step = 1
116 end if
117 counter%global_iteration = counter%iteration * counter%step
118
119 counter%value => iteration_counter_value
120
122
123 ! ---------------------------------------------------------
124 subroutine iteration_counter_set(this, counter)
125 class(iteration_counter_t), intent(inout) :: this
126 type(iteration_counter_t), intent(in) :: counter
127
128 ! Sanity check: the new iteration must be commensurable with the step
129 if (mod(counter%global_iteration, this%step) /= 0) then
130 message(1) = 'Cannot set iteration counter, as the new iteration is not commensurable with counter step.'
131 call messages_fatal(1)
132 end if
133
134 this%iteration = int(counter%global_iteration / this%step)
135 this%global_iteration = counter%global_iteration
136
137 end subroutine iteration_counter_set
138
139 ! ---------------------------------------------------------
144 pure real(real64) function iteration_counter_value(this) result(value)
145 class(iteration_counter_t), intent(in) :: this
146
147 value = real(this%global_iteration, real64)
148
149 end function iteration_counter_value
151 ! ---------------------------------------------------------
153 pure integer function iteration_counter_counter(this) result(counter)
154 class(iteration_counter_t), intent(in) :: this
155
156 counter = this%iteration
157
158 end function iteration_counter_counter
160 ! ---------------------------------------------------------
161 pure integer(int64) function iteration_counter_global_step(this) result(step)
162 class(iteration_counter_t), intent(in) :: this
163
164 step = this%step
165
168 ! ---------------------------------------------------------
169 function iteration_counter_add(this, n) result(new_counter)
170 class(iteration_counter_t), intent(in) :: this
171 integer, intent(in) :: n
172 type(iteration_counter_t) :: new_counter
173
174 new_counter = this
175 new_counter%iteration = new_counter%iteration + n
176 new_counter%global_iteration = new_counter%iteration * new_counter%step
177
178 end function iteration_counter_add
179
180 ! ---------------------------------------------------------
181 function iteration_counter_subtract(this, n) result(new_counter)
182 class(iteration_counter_t), intent(in) :: this
183 integer, intent(in) :: n
184 type(iteration_counter_t) :: new_counter
185
186 new_counter = this
187 new_counter%iteration = new_counter%iteration - n
188 new_counter%global_iteration = new_counter%iteration * new_counter%step
189
190 end function iteration_counter_subtract
191
192 ! ---------------------------------------------------------
193 pure subroutine iteration_counter_reset(this)
194 class(iteration_counter_t), intent(inout) :: this
195
196 this%iteration = 0
197 this%global_iteration = 0
198
200
201 ! ---------------------------------------------------------
202 elemental logical function iteration_counter_is_earlier(counter_a, counter_b) result(is_earlier)
203 class(iteration_counter_t), intent(in) :: counter_a, counter_b
204
205 is_earlier = counter_a%global_iteration < counter_b%global_iteration
206
209 ! ---------------------------------------------------------
210 elemental logical function iteration_counter_is_later(counter_a, counter_b) result(is_later)
211 class(iteration_counter_t), intent(in) :: counter_a, counter_b
212
213 is_later = counter_a%global_iteration > counter_b%global_iteration
214
215 end function iteration_counter_is_later
217 ! ---------------------------------------------------------
218 elemental logical function iteration_counter_is_equal_or_earlier(counter_a, counter_b) result(is_equal_or_earlier)
219 class(iteration_counter_t), intent(in) :: counter_a, counter_b
220
221 is_equal_or_earlier = counter_a%global_iteration <= counter_b%global_iteration
222
225 ! ---------------------------------------------------------
226 elemental logical function iteration_counter_is_equal_or_later(counter_a, counter_b) result(is_equal_or_later)
227 class(iteration_counter_t), intent(in) :: counter_a, counter_b
228
229 is_equal_or_later = counter_a%global_iteration >= counter_b%global_iteration
230
233 ! ---------------------------------------------------------
234 elemental logical function iteration_counter_is_equal(counter_a, counter_b) result(are_equal)
235 class(iteration_counter_t), intent(in) :: counter_a, counter_b
236
237 are_equal = counter_a%global_iteration == counter_b%global_iteration
238
239 end function iteration_counter_is_equal
241 ! ---------------------------------------------------------
242 elemental logical function iteration_counter_is_different(counter_a, counter_b) result(are_diff)
243 class(iteration_counter_t), intent(in) :: counter_a, counter_b
244
245 are_diff = counter_a%global_iteration /= counter_b%global_iteration
246
249 ! ---------------------------------------------------------
250 subroutine iteration_counter_restart_write(this, filename, namespace)
251 class(iteration_counter_t), intent(in) :: this
252 character(len=*), intent(in) :: filename
253 type(namespace_t), intent(in) :: namespace
254
255 integer :: restart_file_unit
257 call io_mkdir("restart", namespace, parents=.true.)
258 restart_file_unit = io_open("restart/"//filename, namespace, form="unformatted", action='write')
259 write(restart_file_unit) this%iteration, this%step
260 call io_close(restart_file_unit)
261
263
264 ! ---------------------------------------------------------
265 logical function iteration_counter_restart_read(this, filename, namespace) result(restart_read)
266 class(iteration_counter_t), intent(inout) :: this
267 character(len=*), intent(in) :: filename
268 type(namespace_t), intent(in) :: namespace
269
270 integer :: restart_file_unit
272 restart_file_unit = io_open("restart/"//filename, namespace, form="unformatted", action='read', die=.false.)
273 if (restart_file_unit /= -1) then
274 read(restart_file_unit) this%iteration, this%step
275 call io_close(restart_file_unit)
276
277 this%global_iteration = this%iteration * this%step
278 restart_read = .true.
279 else
280 ! could not open file
281 restart_read = .false.
282 end if
283
285
Definition: io.F90:114
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...
int true(void)