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