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 to ensure the labels are unique.
83
84 type(iteration_counter_t), public :: iteration
85 ! !!
86 ! !! @note The iteration counter is initialized automatically
87 ! !! for extensions of system_t, but needs to be initialized explicitly for extensions of
88 ! !! interaction_partner_t, which are not systems. This can be done via the constructor of quantity_t.
89
90 logical, public :: always_available = .false.
91 ! !!
92 ! !! (e.g., this will be true for a static quantity,
93 ! !! but false for a quantity that is only updated at specific iterations)
94
95 logical, public :: updated_on_demand = .true.
96 ! !!
97 ! !! If true, the quantity is only updated when requested. The quantity should be calculated (updated)
98 ! !! in the systems update_quantity() routine.
99 ! !!
100 ! !! If false, the quantity is updated automatically during the execution of an algorithm.
101 ! !! In this case, the quantity should be updated inside the do_algorithmic_operation() routine.
102
103 character(len=100), allocatable, public :: parents(:)
104 end type quantity_t
105
106 interface quantity_t
107 module procedure quantity_constructor
108 end interface quantity_t
109
110contains
111
112 function quantity_constructor(label, always_available, updated_on_demand, iteration, parents) result(quantity)
113 character(len=*), intent(in) :: label
114 logical, optional, intent(in) :: always_available
115 logical, optional, intent(in) :: updated_on_demand
116 type(iteration_counter_t), optional, intent(in) :: iteration
117 character(len=*), optional, intent(in) :: parents(:)
118 type(quantity_t) :: quantity
119
120 integer :: i
121
122 quantity%label = trim(label)
123 if (present(always_available)) then
124 quantity%always_available = always_available
125 end if
126 if (present(updated_on_demand)) then
127 quantity%updated_on_demand = updated_on_demand
128 end if
129 if (present(iteration)) then
130 quantity%iteration = iteration
131 end if
132 if (present(parents)) then
133 allocate(quantity%parents(size(parents)))
134 do i = 1, size(parents)
135 quantity%parents(i) = trim(parents(i))
136 end do
137 else
138 allocate(quantity%parents(0))
139 end if
140
141 end function quantity_constructor
142
143 ! ---------------------------------------------------------
146 subroutine quantity_list_add_node(this, quantity)
147 class(quantity_list_t) :: this
148 class(quantity_t), target :: quantity
149
150 call this%add_copy(quantity)
151
152 end subroutine quantity_list_add_node
154 ! ---------------------------------------------------------
157 function quantity_list_get(this, label) result(quantity)
158 class(quantity_list_t), intent(in) :: this
159 character(len=*), intent(in) :: label
160 class(quantity_t), pointer :: quantity
161
162 logical :: have
163 type(quantity_iterator_t) :: iterator
164
165 ! The following loop is not very efficient, but lists of quantities should
166 ! not be larger than a few dozen at most
167 have = .false.
168 call iterator%start(this)
169 do while (iterator%has_next() .and. .not. have)
170 quantity => iterator%get_next()
171 have = trim(quantity%label) == trim(label)
172 end do
173 if (.not. have) then
174 nullify(quantity)
175 end if
176
177 end function quantity_list_get
178
179 ! ---------------------------------------------------------
182 function quantity_list_always_available(this, labels) result(always_available)
183 class(quantity_list_t), intent(in) :: this
184 character(len=*), intent(in) :: labels(:)
185 logical :: always_available(size(labels))
186
187 integer :: i
188 class(quantity_t), pointer :: quantity
189
190 do i = 1, size(labels)
191 quantity => this%get(labels(i))
192 always_available(i) = quantity%always_available
193 end do
194
197 ! ---------------------------------------------------------
199 function quantity_list_iteration_equal(this, labels, iteration) result(equal)
200 class(quantity_list_t), intent(in) :: this
201 character(len=*), intent(in) :: labels(:)
202 type(iteration_counter_t), intent(in) :: iteration
203 logical :: equal(size(labels))
204
205 integer :: i
206 class(quantity_t), pointer :: quantity
207
208 do i = 1, size(labels)
209 quantity => this%get(labels(i))
210 ! We need to ignore static quantities:
211 equal(i) = quantity%iteration == iteration
212 end do
213
215
216 ! ---------------------------------------------------------
219 function quantity_iterator_get_next(this) result(quantity)
220 class(quantity_iterator_t), intent(inout) :: this
221 class(quantity_t), pointer :: quantity
222
223 select type (ptr => this%get_next_ptr())
224 class is (quantity_t)
225 quantity => ptr
226 class default
227 assert(.false.)
228 end select
229
230 end function quantity_iterator_get_next
231
232end module quantity_oct_m
233
234!! Local Variables:
235!! mode: f90
236!! coding: utf-8
237!! 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:276
subroutine quantity_list_add_node(this, quantity)
add a quantity to the list
Definition: quantity.F90:240
class(quantity_t) function, pointer quantity_iterator_get_next(this)
get next quantity from the list
Definition: quantity.F90:313
class(quantity_t) function, pointer quantity_list_get(this, label)
get pointer to quantity with given label
Definition: quantity.F90:251
type(quantity_t) function quantity_constructor(label, always_available, updated_on_demand, iteration, parents)
Definition: quantity.F90:206
logical function, dimension(size(labels)) quantity_list_iteration_equal(this, labels, iteration)
Return if given quantities are at a given iteration.
Definition: quantity.F90:293
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)