Octopus
interaction.F90
Go to the documentation of this file.
1!! Copyright (C) 2020-2023 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#include "global.h"
8
96!
98 use debug_oct_m
99 use global_oct_m
108 implicit none
109
110 private
111 public :: &
116
117 integer, parameter, public :: &
118 TIMING_EXACT = 1, &
120
130 !
131 type, extends(interaction_surrogate_t), abstract :: interaction_t
132 ! General information about the interaction
133 type(iteration_counter_t) :: iteration
134 character(len=:), allocatable :: label
135 logical :: intra_interaction
136 integer :: timing
138 real(real64) :: energy
139
140 ! The interaction requires access to some quantities from a system to be evaluated.
141 integer, allocatable :: system_quantities(:)
142
143 ! Information regarding the partner
144 class(interaction_partner_t), pointer :: partner => null()
145 integer, allocatable :: couplings_from_partner(:)
146 logical :: partner_couplings_up_to_date = .false.
147
148 contains
149 procedure(interaction_calculate), deferred :: calculate
150 procedure(interaction_calculate_energy), deferred :: calculate_energy
151 procedure :: update => interaction_update
152 procedure :: update_partner_couplings => interaction_update_partner_couplings
153 procedure :: restart_read => interaction_restart_read
154 procedure :: restart_write => interaction_restart_write
155 end type interaction_t
156
157 abstract interface
158
161 subroutine interaction_calculate(this)
162 import interaction_t
163 class(interaction_t), intent(inout) :: this
164 end subroutine interaction_calculate
165
169 subroutine interaction_calculate_energy(this)
170 import interaction_t
171 class(interaction_t), intent(inout) :: this
172 end subroutine interaction_calculate_energy
173 end interface
174
175
177 type, extends(linked_list_t) :: interaction_list_t
178 private
179 contains
180 procedure :: add => interaction_list_add_node
181 end type interaction_list_t
182
185 private
186 contains
187 procedure :: get_next => interaction_iterator_get_next
189
190contains
191
192 ! ---------------------------------------------------------
194 subroutine interaction_update_partner_couplings(this, requested_iteration)
195 class(interaction_t), intent(inout) :: this
196 class(iteration_counter_t), intent(in) :: requested_iteration
197
198 type(event_handle_t) :: debug_handle
199
201
202 if (this%partner_couplings_up_to_date) then
203 ! Couplings have already been updated
205 return
206 end if
207
208 if (.not. allocated(this%couplings_from_partner)) then
209 ! No couplings to update
210 this%partner_couplings_up_to_date = .true.
212 return
213 end if
214
215 debug_handle = multisystem_debug_write_event_in(system_namespace = this%partner%namespace, &
216 event = event_function_call_t("system_update_exposed_quantities"), &
217 requested_iteration = requested_iteration, &
218 interaction_iteration = this%iteration)
219
220 ! Update all the necessary couplings that are updated on demand
221 call this%partner%update_on_demand_quantities(this%couplings_from_partner, requested_iteration, &
222 retardation_allowed = this%timing == timing_retarded)
223
224 ! Check the status of all the couplings and take the appropriate actions
225 select case (this%partner%check_couplings_status(this%couplings_from_partner, requested_iteration))
227 ! Update was successful and we need to copy the couplings to the interaction
228 this%partner_couplings_up_to_date = .true.
229 call this%partner%copy_quantities_to_interaction(this)
230
232 ! Update is successful, only if retarded interaction is allowed. If that
233 ! is the case, the interaction should use the couplings it already has, so
234 ! there is no need to copy them to the interaction
235 this%partner_couplings_up_to_date = (this%timing == timing_retarded)
236
238 ! For now we will mark this case as unsuccessfu, but it could be
239 ! successfull if interpolation was allowed
240 this%partner_couplings_up_to_date = .false.
241
243 ! Partner couplings are in an undefined state (some are ahead of the
244 ! requested iteration and some are at the requested iteration). This
245 ! should never happen!
246 assert(.false.)
247 end select
248
249 call multisystem_debug_write_event_out(debug_handle, update=this%partner_couplings_up_to_date, &
250 requested_iteration = requested_iteration, &
251 interaction_iteration = this%iteration)
252
256
257 ! ---------------------------------------------------------
259 subroutine interaction_update(this, requested_iteration)
260 class(interaction_t), intent(inout) :: this
261 class(iteration_counter_t), intent(in) :: requested_iteration
263 type(event_handle_t) :: debug_handle
264
265 push_sub(interaction_update)
266
267 ! We should only try to update the interaction if it is not yet at the requested iteration
268 assert(.not. (this%iteration == requested_iteration))
269
270 debug_handle = multisystem_debug_write_event_in(event = event_function_call_t("interaction_update"), &
271 extra="target: "//trim(this%label)//"-"//trim(this%partner%namespace%get()), &
272 interaction_iteration = this%iteration, &
273 requested_iteration = requested_iteration)
274
275 call this%calculate()
276
277 ! Set new interaction iteration
278 call this%iteration%set(requested_iteration)
279 call multisystem_debug_write_marker(event = event_iteration_update_t( "interaction", &
280 trim(this%label)//"-"//trim(this%partner%namespace%get()), &
281 this%iteration, "set"))
282
283 ! After leaving this routine, the partner quantities will need to updated
284 ! again for the next interaction update
285 this%partner_couplings_up_to_date = .false.
286
287 call multisystem_debug_write_event_out(debug_handle, update = .true., &
288 interaction_iteration = this%iteration, &
289 requested_iteration = requested_iteration)
290
291 pop_sub(interaction_update)
292 end subroutine interaction_update
293
294 ! ---------------------------------------------------------
295 subroutine interaction_end(this)
296 class(interaction_t), intent(inout) :: this
297
298 push_sub(interaction_end)
299
300 if (allocated(this%couplings_from_partner)) then
301 deallocate(this%couplings_from_partner)
302 end if
303 nullify(this%partner)
304
305 if (allocated(this%system_quantities)) then
306 deallocate(this%system_quantities)
307 end if
308
309 if (allocated(this%label)) then
310 deallocate(this%label)
311 end if
312
313 pop_sub(interaction_end)
314 end subroutine interaction_end
315
316 ! ---------------------------------------------------------
320 logical function interaction_restart_read(this, namespace)
321 class(interaction_t), intent(inout) :: this
322 type(namespace_t), intent(in) :: namespace
323
325
326 interaction_restart_read = this%iteration%restart_read('restart_iteration_interaction_'//trim(this%label), &
327 namespace)
328
330 end function interaction_restart_read
331
332 ! ---------------------------------------------------------
333 subroutine interaction_restart_write(this, namespace)
334 class(interaction_t), intent(inout) :: this
335 type(namespace_t), intent(in) :: namespace
336
338
339 call this%iteration%restart_write('restart_iteration_interaction_'//trim(this%label), namespace)
340
342 end subroutine interaction_restart_write
343
344 ! ---------------------------------------------------------
345 subroutine interaction_list_add_node(this, interaction)
346 class(interaction_list_t) :: this
347 class(interaction_t), target :: interaction
348
350
351 call this%add_ptr(interaction)
354 end subroutine interaction_list_add_node
355
356 ! ---------------------------------------------------------
357 function interaction_iterator_get_next(this) result(interaction)
358 class(interaction_iterator_t), intent(inout) :: this
359 class(interaction_t), pointer :: interaction
360
362
363 select type (ptr => this%get_next_ptr())
364 class is (interaction_t)
365 interaction => ptr
366 class default
367 assert(.false.)
368 end select
369
372
373end module interaction_oct_m
374
375!! Local Variables:
376!! mode: f90
377!! coding: utf-8
378!! End:
All interactions need to implement the following deferred method, which takes information form the in...
All interactions need to implement the following deferred method, which takes information form the in...
This module defines the abstract interaction_t class, and some auxiliary classes for interactions.
subroutine interaction_update_partner_couplings(this, requested_iteration)
Try to update all the couplings needed from the partner to update the interaction.
subroutine, public interaction_end(this)
subroutine interaction_update(this, requested_iteration)
Update the interaction to the requested_iteration.
logical function interaction_restart_read(this, namespace)
read restart information
class(interaction_t) function, pointer interaction_iterator_get_next(this)
integer, parameter, public timing_retarded
subroutine interaction_restart_write(this, namespace)
subroutine interaction_list_add_node(this, interaction)
This module defines classes and functions for interaction partners.
integer, parameter, public couplings_on_time
integer, parameter, public couplings_behind_in_time
integer, parameter, public couplings_ahead_in_time
integer, parameter, public couplings_undefined
This module implements fully polymorphic linked lists, and some specializations thereof.
This module implements the multisystem debug functionality.
subroutine, public multisystem_debug_write_marker(system_namespace, event)
type(event_handle_t) function, public multisystem_debug_write_event_in(system_namespace, event, extra, system_iteration, algo_iteration, interaction_iteration, partner_iteration, requested_iteration)
subroutine, public multisystem_debug_write_event_out(handle, extra, update, system_iteration, algo_iteration, interaction_iteration, partner_iteration, requested_iteration)
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
Definition: quantity.F90:137
These class extend the list and list iterator to make an interaction list.
These classes extend the list and list iterator to make an interaction list.
abstract interaction class
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.
handle to keep track of in- out- events
int true(void)