Octopus
quantity.F90
Go to the documentation of this file.
1!! Copyright (C) 2020 N. Tancogne-Dejean
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
44
45module quantity_oct_m
48 implicit none
49
50 private
51 public :: &
52 quantity_t, &
55
57 type, extends(linked_list_t) :: quantity_list_t
58 private
59 contains
60 procedure :: add => quantity_list_add_node
61 procedure :: get => quantity_list_get
62 procedure :: always_available => quantity_list_always_available
63 procedure :: iteration_equal => quantity_list_iteration_equal
64 end type quantity_list_t
65
67 private
68 contains
69 procedure :: get_next => quantity_iterator_get_next
70 end type quantity_iterator_t
71
78 type quantity_t
79 private
80 character(len=:), allocatable, public :: label
81 ! !!
82 ! !! @note It is the responsibility of the developers
83 ! !! to ensure the labels are unique.
84
85 type(iteration_counter_t), public :: iteration
86 ! !! the quantity was last updated.
87 ! !!
88 ! !! @note The iteration counter is initialized automatically
89 ! !! for extensions of system_t, but needs to be initialized explicitly
90 ! !! for extensions of interaction_partner_t, which are not systems.
91 ! !! This can be done via the constructor of quantity_t.
92
93 logical, public :: always_available = .false.
94 ! !!
95 ! !! (e.g., this will be true for a static quantity,
96 ! !! but false for a quantity that is only updated at specific iterations)
97
98 logical, public :: updated_on_demand = .true.
99 ! !!
100 ! !! If true, the quantity is only updated when requested.
101 ! !! The quantity should be calculated (updated)
102 ! !! in the systems update_quantity() routine.
103 ! !!
104 ! !! If false, the quantity is updated automatically during the execution of
105 ! !! an algorithm. In this case, the quantity should be updated inside the
106 ! !! do_algorithmic_operation() routine.
107
108 character(len=100), allocatable, public :: parents(:)
109 end type quantity_t
110
111 interface quantity_t
112 module procedure quantity_constructor
113 end interface quantity_t
114
115contains
116
117 function quantity_constructor(label, always_available, updated_on_demand, iteration, parents) result(quantity)
118 character(len=*), intent(in) :: label
119 logical, optional, intent(in) :: always_available
120 logical, optional, intent(in) :: updated_on_demand
121 type(iteration_counter_t), optional, intent(in) :: iteration
122 character(len=*), optional, intent(in) :: parents(:)
123 type(quantity_t) :: quantity
124
125 integer :: i
126
127 quantity%label = trim(label)
128 if (present(always_available)) then
129 quantity%always_available = always_available
130 end if
131 if (present(updated_on_demand)) then
132 quantity%updated_on_demand = updated_on_demand
133 end if
134 if (present(iteration)) then
135 quantity%iteration = iteration
136 end if
137 if (present(parents)) then
138 allocate(quantity%parents(size(parents)))
139 do i = 1, size(parents)
140 quantity%parents(i) = trim(parents(i))
141 end do
142 else
143 allocate(quantity%parents(0))
144 end if
145
146 end function quantity_constructor
147
148 ! ---------------------------------------------------------
151 subroutine quantity_list_add_node(this, quantity)
152 class(quantity_list_t) :: this
153 class(quantity_t), target :: quantity
155 call this%add_copy(quantity)
157 end subroutine quantity_list_add_node
158
159 ! ---------------------------------------------------------
162 function quantity_list_get(this, label) result(quantity)
163 class(quantity_list_t), intent(in) :: this
164 character(len=*), intent(in) :: label
165 class(quantity_t), pointer :: quantity
166
167 logical :: have
168 type(quantity_iterator_t) :: iterator
169
170 ! The following loop is not very efficient, but lists of quantities should
171 ! not be larger than a few dozen at most
172 have = .false.
173 call iterator%start(this)
174 do while (iterator%has_next() .and. .not. have)
175 quantity => iterator%get_next()
176 have = trim(quantity%label) == trim(label)
177 end do
178 if (.not. have) then
179 nullify(quantity)
180 end if
181
182 end function quantity_list_get
183
184 ! ---------------------------------------------------------
187 function quantity_list_always_available(this, labels) result(always_available)
188 class(quantity_list_t), intent(in) :: this
189 character(len=*), intent(in) :: labels(:)
190 logical :: always_available(size(labels))
192 integer :: i
193 class(quantity_t), pointer :: quantity
194
195 do i = 1, size(labels)
196 quantity => this%get(labels(i))
197 always_available(i) = quantity%always_available
198 end do
199
202 ! ---------------------------------------------------------
204 function quantity_list_iteration_equal(this, labels, iteration) result(equal)
205 class(quantity_list_t), intent(in) :: this
206 character(len=*), intent(in) :: labels(:)
207 type(iteration_counter_t), intent(in) :: iteration
208 logical :: equal(size(labels))
209
210 integer :: i
211 class(quantity_t), pointer :: quantity
212
213 do i = 1, size(labels)
214 quantity => this%get(labels(i))
215 ! We need to ignore static quantities:
216 equal(i) = quantity%iteration == iteration
217 end do
218
220
221 ! ---------------------------------------------------------
224 function quantity_iterator_get_next(this) result(quantity)
225 class(quantity_iterator_t), intent(inout) :: this
226 class(quantity_t), pointer :: quantity
227
228 select type (ptr => this%get_next_ptr())
229 class is (quantity_t)
230 quantity => ptr
231 class default
232 assert(.false.)
233 end select
234
235 end function quantity_iterator_get_next
236
237end module quantity_oct_m
238
239!! Local Variables:
240!! mode: f90
241!! coding: utf-8
242!! End:
This module implements fully polymorphic linked lists, and some specializations thereof.
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
Definition: quantity.F90:138
logical function, dimension(size(labels)) quantity_list_always_available(this, labels)
Return if given quantities are always available or not.
Definition: quantity.F90:281
subroutine quantity_list_add_node(this, quantity)
add a quantity to the list
Definition: quantity.F90:245
class(quantity_t) function, pointer quantity_iterator_get_next(this)
get next quantity from the list
Definition: quantity.F90:318
class(quantity_t) function, pointer quantity_list_get(this, label)
get pointer to quantity with given label
Definition: quantity.F90:256
type(quantity_t) function quantity_constructor(label, always_available, updated_on_demand, iteration, parents)
Definition: quantity.F90:211
logical function, dimension(size(labels)) quantity_list_iteration_equal(this, labels, iteration)
Return if given quantities are at a given iteration.
Definition: quantity.F90:298
This class implements the iteration counter used by the multisystem algorithms. As any iteration coun...
This class implements an iterator for the polymorphic linked list.
This class implements a linked list of unlimited polymorphic values.
These classes extends the list and list iterator to create a quantity list.
Definition: quantity.F90:150
Systems (system_t) can expose quantities that can be used to calculate interactions with other system...
Definition: quantity.F90:171
int true(void)