Octopus
interaction_partner.F90
Go to the documentation of this file.
1!! Copyright (C) 2020 M. Oliveira
2!!
3!! This Source Code Form is subject to the terms of the Mozilla Public
4!! License, v. 2.0. If a copy of the MPL was not distributed with this
5!! file, You can obtain one at https://mozilla.org/MPL/2.0/.
6!!
7
8#include "global.h"
9
14 use debug_oct_m
15 use global_oct_m
23 implicit none
24
25 private
26 public :: &
30
31 integer, parameter, public :: &
32 COUPLINGS_UNDEFINED = 0, &
36
42 type, abstract :: interaction_partner_t
43 private
44 type(namespace_t), public :: namespace
45
46 integer, allocatable, public :: supported_interactions_as_partner(:)
48
49 type(quantity_t), public :: quantities(MAX_QUANTITIES)
52 contains
53 procedure :: add_partners_to_list => interaction_partner_add_partners_to_list
54 procedure :: update_quantity => interaction_partner_update_quantity
55 procedure :: update_on_demand_quantities => interaction_partner_update_on_demand_quantities
56 procedure :: check_couplings_status => interaction_partner_check_couplings_status
57 procedure(interaction_partner_init_interaction_as_partner), deferred :: init_interaction_as_partner
58
59 procedure(interaction_partner_copy_quantities_to_interaction), deferred :: copy_quantities_to_interaction
60
62
63 abstract interface
64 ! ---------------------------------------------------------
65 subroutine interaction_partner_init_interaction_as_partner(partner, interaction)
68 class(interaction_partner_t), intent(in) :: partner
69 class(interaction_surrogate_t), intent(inout) :: interaction
71
72 ! ---------------------------------------------------------
73 subroutine interaction_partner_copy_quantities_to_interaction(partner, interaction)
76 class(interaction_partner_t), intent(inout) :: partner
77 class(interaction_surrogate_t), intent(inout) :: interaction
79
80 end interface
81
85 type, extends(linked_list_t) :: partner_list_t
86 private
87 contains
88 procedure :: add => partner_list_add_node
89 end type partner_list_t
90
95 private
96 contains
97 procedure :: get_next => partner_iterator_get_next
98 end type partner_iterator_t
99
100contains
101
102 ! ---------------------------------------------------------
107 recursive subroutine interaction_partner_add_partners_to_list(this, list, interaction_type)
108 class(interaction_partner_t), intent(in) :: this
109 class(partner_list_t), intent(inout) :: list
110 integer, optional, intent(in) :: interaction_type
111
112 if (present(interaction_type)) then
113 if (any(this%supported_interactions_as_partner == interaction_type)) then
114 call list%add(this)
115 end if
116 else
117 call list%add(this)
118 end if
119
121
122 ! ---------------------------------------------------------
130 subroutine interaction_partner_update_quantity(this, iq)
131 class(interaction_partner_t), intent(inout) :: this
132 integer, intent(in) :: iq
133
136 write(message(1), '(a,a,a,a,a)') 'Interation partner "', trim(this%namespace%get()), &
137 '"does not know how to update quantity"', trim(quantity_label(iq)), '".'
138 call messages_fatal(1, namespace=this%namespace)
143 ! ---------------------------------------------------------
151 subroutine interaction_partner_update_on_demand_quantities(this, quantities, requested_iteration, retardation_allowed)
152 class(interaction_partner_t), target, intent(inout) :: this
153 integer, intent(in) :: quantities(:)
154 class(iteration_counter_t), intent(in) :: requested_iteration
155 logical, intent(in) :: retardation_allowed
156
157 integer :: iq, q_id
158 type(quantity_t), pointer :: quantity
159
160 do iq = 1, size(quantities)
161 ! Get the requested quantity ID and a shortcut to the quantity
162 q_id = quantities(iq)
163 quantity => this%quantities(q_id)
164
165 ! We are only updating on demand quantities that are behind the requested iteration
166 if (quantity%iteration >= requested_iteration .or. .not. quantity%updated_on_demand) cycle
167
168 if (quantity%always_available) then
169 ! We set the quantity iteration to the requested one, so that the partner
170 ! can use this information when updating the quantity
171 quantity%iteration = requested_iteration
172
173 call multisystem_debug_write_marker(this%namespace, event_iteration_update_t("quantity", quantity_label(q_id), &
174 quantity%iteration, "set"))
175 call this%update_quantity(q_id)
176
177 else if (quantity%iteration + 1 <= requested_iteration .or. &
178 (retardation_allowed .and. quantity%iteration + 1 > requested_iteration)) then
179 ! We can update because the partner will reach this iteration in the next algorithmic step
180 ! For retarded interactions, we need to allow the quantity to get ahead by one iteration
181 quantity%iteration = quantity%iteration + 1
182
183 call multisystem_debug_write_marker(this%namespace, event_iteration_update_t("quantity", quantity_label(q_id), &
184 quantity%iteration, "set"))
185 call this%update_quantity(q_id)
186 end if
187 end do
188
191 ! ---------------------------------------------------------
199 integer function interaction_partner_check_couplings_status(this, couplings, requested_iteration) result(status)
200 class(interaction_partner_t), intent(inout) :: this
201 integer, intent(in) :: couplings(:)
202 class(iteration_counter_t), intent(in) :: requested_iteration
203
204 integer, allocatable :: relevant_couplings(:)
205 integer :: ahead, on_time
206
208
209 ! Couplings that are available at any time do not affect the status, so we will ignore them
210 relevant_couplings = pack(couplings, .not. this%quantities(couplings)%always_available)
211
212 ! Count couplings behind, on time and ahead
213 on_time = count(this%quantities(relevant_couplings)%iteration == requested_iteration)
214 ahead = count(this%quantities(relevant_couplings)%iteration > requested_iteration)
215
216 ! Determine status
217 if (on_time > 0 .and. ahead > 0) then
218 status = couplings_undefined
219 else if (on_time + ahead < size(relevant_couplings)) then
221 else if (on_time == size(relevant_couplings)) then
222 status = couplings_on_time
223 else if (ahead == size(relevant_couplings)) then
225 end if
226
229
230 ! ---------------------------------------------------------
233 subroutine partner_list_add_node(this, partner)
234 class(partner_list_t) :: this
235 class(interaction_partner_t), target :: partner
236
237 push_sub(partner_list_add_node)
238
239 call this%add_ptr(partner)
240
241 pop_sub(partner_list_add_node)
242 end subroutine partner_list_add_node
243
244 ! ---------------------------------------------------------
247 function partner_iterator_get_next(this) result(partner)
248 class(partner_iterator_t), intent(inout) :: this
249 class(interaction_partner_t), pointer :: partner
250
252
253 select type (ptr => this%get_next_ptr())
254 class is (interaction_partner_t)
255 partner => ptr
256 class default
257 assert(.false.)
258 end select
259
261 end function partner_iterator_get_next
262
264
265!! Local Variables:
266!! mode: f90
267!! coding: utf-8
268!! End:
This module defines classes and functions for interaction partners.
integer, parameter, public couplings_on_time
recursive subroutine interaction_partner_add_partners_to_list(this, list, interaction_type)
add interaction partner to a list
subroutine interaction_partner_update_quantity(this, iq)
Method to be overriden by interaction partners that have quantities that can be updated on demand.
integer function interaction_partner_check_couplings_status(this, couplings, requested_iteration)
Check the status of some couplings.
class(interaction_partner_t) function, pointer partner_iterator_get_next(this)
get next partner from the list
subroutine partner_list_add_node(this, partner)
add a partner to the list
integer, parameter, public couplings_behind_in_time
subroutine interaction_partner_update_on_demand_quantities(this, quantities, requested_iteration, retardation_allowed)
Given a list of quantities, update the ones that can be update on demand.
integer, parameter, public couplings_ahead_in_time
This module implements fully polymorphic linked lists, and some specializations thereof.
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:420
This module implements the multisystem debug functionality.
subroutine, public multisystem_debug_write_marker(system_namespace, event)
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
Definition: quantity.F90:137
character(len=17), dimension(max_quantities), parameter, public quantity_label
Definition: quantity.F90:165
abstract class for general interaction partners
surrogate interaction class to avoid circular dependencies between modules.
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.
Systems (system_t) can expose quantities that can be used to calculate interactions with other system...
Definition: quantity.F90:189