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 type(integer_list_t), public :: supported_interactions_as_partner
48
49 type(quantity_t), public :: quantities(MAX_QUANTITIES)
52 contains
53 procedure :: update_quantity => interaction_partner_update_quantity
54 procedure :: update_on_demand_quantities => interaction_partner_update_on_demand_quantities
55 procedure :: check_couplings_status => interaction_partner_check_couplings_status
56 procedure(interaction_partner_init_interaction_as_partner), deferred :: init_interaction_as_partner
57
58 procedure(interaction_partner_copy_quantities_to_interaction), deferred :: copy_quantities_to_interaction
59
61
62 abstract interface
63 ! ---------------------------------------------------------
64 subroutine interaction_partner_init_interaction_as_partner(partner, interaction)
67 class(interaction_partner_t), intent(in) :: partner
68 class(interaction_surrogate_t), intent(inout) :: interaction
70
71 ! ---------------------------------------------------------
72 subroutine interaction_partner_copy_quantities_to_interaction(partner, interaction)
75 class(interaction_partner_t), intent(inout) :: partner
76 class(interaction_surrogate_t), intent(inout) :: interaction
78
79 end interface
80
84 type, extends(linked_list_t) :: partner_list_t
85 private
86 contains
87 procedure :: add => partner_list_add_node
88 end type partner_list_t
89
94 private
95 contains
96 procedure :: get_next => partner_iterator_get_next
98
99contains
100
101 ! ---------------------------------------------------------
109 subroutine interaction_partner_update_quantity(this, iq)
110 class(interaction_partner_t), intent(inout) :: this
111 integer, intent(in) :: iq
112
114
115 write(message(1), '(a,a,a,a,a)') 'Interation partner "', trim(this%namespace%get()), &
116 '"does not know how to update quantity"', trim(quantity_label(iq)), '".'
117 call messages_fatal(1, namespace=this%namespace)
118
121
122 ! ---------------------------------------------------------
130 subroutine interaction_partner_update_on_demand_quantities(this, quantities, requested_iteration, retardation_allowed)
131 class(interaction_partner_t), target, intent(inout) :: this
132 integer, intent(in) :: quantities(:)
133 class(iteration_counter_t), intent(in) :: requested_iteration
134 logical, intent(in) :: retardation_allowed
135
136 integer :: iq, q_id
137 type(quantity_t), pointer :: quantity
139 do iq = 1, size(quantities)
140 ! Get the requested quantity ID and a shortcut to the quantity
141 q_id = quantities(iq)
142 quantity => this%quantities(q_id)
143
144 ! We are only updating on demand quantities that are behind the requested iteration
145 if (quantity%iteration >= requested_iteration .or. .not. quantity%updated_on_demand) cycle
146
147 if (quantity%always_available) then
148 ! We set the quantity iteration to the requested one, so that the partner
149 ! can use this information when updating the quantity
150 quantity%iteration = requested_iteration
151
152 call multisystem_debug_write_marker(this%namespace, event_iteration_update_t("quantity", quantity_label(q_id), &
153 quantity%iteration, "set"))
154 call this%update_quantity(q_id)
155
156 else if (quantity%iteration + 1 <= requested_iteration .or. &
157 (retardation_allowed .and. quantity%iteration + 1 > requested_iteration)) then
158 ! We can update because the partner will reach this iteration in the next algorithmic step
159 ! For retarded interactions, we need to allow the quantity to get ahead by one iteration
160 quantity%iteration = quantity%iteration + 1
161
162 call multisystem_debug_write_marker(this%namespace, event_iteration_update_t("quantity", quantity_label(q_id), &
163 quantity%iteration, "set"))
164 call this%update_quantity(q_id)
165 end if
166 end do
167
169
170 ! ---------------------------------------------------------
178 integer function interaction_partner_check_couplings_status(this, couplings, requested_iteration) result(status)
179 class(interaction_partner_t), intent(inout) :: this
180 integer, intent(in) :: couplings(:)
181 class(iteration_counter_t), intent(in) :: requested_iteration
182
183 integer, allocatable :: relevant_couplings(:)
184 integer :: ahead, on_time
185
187
188 ! Couplings that are available at any time do not affect the status, so we will ignore them
189 relevant_couplings = pack(couplings, .not. this%quantities(couplings)%always_available)
190
191 ! Count couplings behind, on time and ahead
192 on_time = count(this%quantities(relevant_couplings)%iteration == requested_iteration)
193 ahead = count(this%quantities(relevant_couplings)%iteration > requested_iteration)
194
195 ! Determine status
196 if (on_time > 0 .and. ahead > 0) then
197 status = couplings_undefined
198 else if (on_time + ahead < size(relevant_couplings)) then
200 else if (on_time == size(relevant_couplings)) then
201 status = couplings_on_time
202 else if (ahead == size(relevant_couplings)) then
204 end if
205
208
209 ! ---------------------------------------------------------
212 subroutine partner_list_add_node(this, partner)
213 class(partner_list_t) :: this
214 class(interaction_partner_t), target :: partner
215
216 push_sub(partner_list_add_node)
217
218 call this%add_ptr(partner)
219
220 pop_sub(partner_list_add_node)
221 end subroutine partner_list_add_node
222
223 ! ---------------------------------------------------------
226 function partner_iterator_get_next(this) result(partner)
227 class(partner_iterator_t), intent(inout) :: this
228 class(interaction_partner_t), pointer :: partner
229
231
232 select type (ptr => this%get_next_ptr())
233 class is (interaction_partner_t)
234 partner => ptr
235 class default
236 assert(.false.)
237 end select
238
240 end function partner_iterator_get_next
241
243
244!! Local Variables:
245!! mode: f90
246!! coding: utf-8
247!! End:
This module defines classes and functions for interaction partners.
integer, parameter, public couplings_on_time
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.
Definition: linked_list.F90:96
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:151
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:400
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:107
character(len=17), dimension(max_quantities), parameter, public quantity_label
Definition: quantity.F90:134
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:157