69 real(real64) :: target_time
72 integer,
parameter,
public :: &
73 NUMBER_BARRIERS = 1, &
81 type(iteration_counter_t),
public :: iteration
82 class(algorithm_t),
pointer,
public :: algo => null()
84 integer,
allocatable,
public :: supported_interactions(:)
85 type(interaction_list_t),
public :: interactions
87 type(mpi_grp_t),
public :: grp
89 type(barrier_t) :: barrier(NUMBER_BARRIERS)
90 real(real64),
public :: kinetic_energy
91 real(real64),
public :: potential_energy
92 real(real64),
public :: internal_energy
93 real(real64),
public :: total_energy
123 procedure(system_init_interaction),
deferred :: init_interaction
124 procedure(system_initialize),
deferred :: initialize
125 procedure(system_do_algorithmic_operation),
deferred :: do_algorithmic_operation
126 procedure(system_is_tolerance_reached),
deferred :: is_tolerance_reached
127 procedure(system_restart_write_data),
deferred :: restart_write_data
128 procedure(system_restart_read_data),
deferred :: restart_read_data
129 procedure(system_update_kinetic_energy),
deferred :: update_kinetic_energy
143 class(system_t),
target,
intent(inout) :: this
144 class(interaction_t),
intent(inout) :: interaction
151 class(system_t),
intent(inout) :: this
167 class(
system_t),
intent(inout) :: this
169 character(len=:),
allocatable,
intent(out) :: updated_quantities(:)
175 use,
intrinsic :: iso_fortran_env
178 real(real64),
intent(in) :: tol
187 class(
system_t),
intent(inout) :: this
245 logical :: all_updated, at_barrier, operation_done
249 character(len=:),
allocatable :: updated_quantities(:)
255 do while (.not. at_barrier)
257 operation = this%algo%get_current_operation()
260 system_iteration=this%iteration, algo_iteration=this%algo%iteration)
263 operation_done = this%do_algorithmic_operation(operation, updated_quantities)
264 if (
allocated(updated_quantities))
then
266 do i = 1,
size(updated_quantities)
267 quantity => this%quantities%get(updated_quantities(i))
268 call quantity%iteration%set(this%algo%iteration + 1)
270 quantity%iteration,
"set"))
275 if (.not. operation_done)
then
276 operation_done = this%algo%do_operation(operation)
278 call this%algo%next()
282 if (.not. operation_done)
then
284 select case (operation%id)
287 call this%algo%next()
291 this%iteration = this%iteration + 1
295 call this%update_total_energy()
298 call this%output_write()
301 call this%algo%update_elapsed_time()
306 call this%iteration_info()
308 call this%algo%next()
311 if (.not. this%algo%finished())
then
312 if (.not. this%arrived_at_any_barrier())
then
314 call this%algo%rewind()
319 if (this%algo%continues_after_finished())
then
320 call this%algo%rewind()
328 this%algo%iteration = this%algo%iteration + 1
330 this%algo%iteration,
"tick"))
333 all_updated = this%update_couplings()
337 if (all_updated)
then
338 call this%algo%next()
340 this%algo%iteration = this%algo%iteration - 1
342 this%algo%iteration,
"reverse"))
350 call this%update_interactions()
351 call this%algo%next()
354 message(1) =
"Unsupported algorithmic operation."
355 write(
message(2),
'(A,A,A)') trim(operation%id),
": ", trim(operation%label)
368 class(
system_t),
intent(inout) :: this
369 integer,
intent(in) :: accumulated_iterations
376 character(len=MAX_INFO_LEN) :: extended_label
381 this%algo%iteration = this%algo%iteration - accumulated_iterations
385 call iter%start(this%interactions)
386 do while (iter%has_next())
387 interaction => iter%get_next()
388 interaction%iteration = interaction%iteration - accumulated_iterations
390 extended_label = trim(interaction%label)//
"-"//trim(interaction%partner%namespace%get())
392 interaction%iteration,
"reset"))
396 call qiter%start(this%interactions)
397 do while(qiter%has_next())
398 quantity => qiter%get_next()
399 quantity%iteration = quantity%iteration - accumulated_iterations
401 quantity%iteration,
"reset"))
422 class(
system_t),
intent(inout) :: this
427 integer :: i, ip, iq, interaction_type
437 assert(
allocated(this%supported_interactions))
438 assert(
allocated(this%supported_interactions_as_partner))
444 call iter%start(available_partners)
445 do while (iter%has_next())
446 partner => iter%get_next()
447 call partner%add_partners_to_list(partners)
450 call iter%start(partners)
451 do while (iter%has_next())
452 partner => iter%get_next()
455 if (partner%namespace%get() == this%namespace%get()) cycle
466 call partners%empty()
470 options = interaction_factory%options(this%namespace, this%supported_interactions)
473 do i = 1,
size(this%supported_interactions)
474 interaction_type = this%supported_interactions(i)
479 assert(count(this%supported_interactions == interaction_type) == 1)
482 call iter%start(available_partners)
483 do while (iter%has_next())
484 partner => iter%get_next()
485 call partner%add_partners_to_list(partners, interaction_type)
489 select case (options(i)%mode)
495 call partners%empty()
499 call iter%start(partners)
500 do while (iter%has_next())
501 partner => iter%get_next()
503 do ip = 1,
size(options(i)%partners)
504 if (partner%namespace%is_contained_in(options(i)%partners(ip)))
then
509 if (.not. in_list)
then
510 call partners%delete(partner)
516 do ip = 1,
size(options(i)%partners)
517 call iter%start(partners)
518 do while (iter%has_next())
519 partner => iter%get_next()
520 if (partner%namespace%is_contained_in(options(i)%partners(ip)))
then
521 call partners%delete(partner)
529 call iter%start(partners)
530 do while (iter%has_next())
531 partner => iter%get_next()
533 interaction => interaction_factory%create(interaction_type, partner)
537 interaction%intra_interaction = partner%namespace%get() == this%namespace%get()
540 interaction%timing = options(i)%timing
542 select type (partner => interaction%partner)
544 if (this%algo%iteration%global_step() /= partner%algo%iteration%global_step() .and. &
545 .not. all(partner%quantities%always_available(interaction%couplings_from_partner)))
then
546 write(
message(1),
'(2a)')
"InteractionTiming was set to exact timing, but systems ", &
547 trim(this%namespace%get())
548 write(
message(2),
'(3a)')
"and ", trim(partner%namespace%get()),
" have incompatible steps."
555 call this%init_interaction(interaction)
556 call interaction%partner%init_interaction_as_partner(interaction)
559 if (
allocated(interaction%system_quantities))
then
560 do iq = 1,
size(interaction%system_quantities)
561 if (.not.
associated(this%quantities%get(interaction%system_quantities(iq))))
then
562 write(
message(1),
'(5a)')
"Interaction '", trim(interaction%label),
"' requires quantity '", &
563 trim(interaction%system_quantities(iq)),
"'"
564 write(
message(2),
'(3a)')
"from system '", trim(this%namespace%get()),
"' but it is not available."
569 if (
allocated(interaction%couplings_from_partner))
then
570 do iq = 1,
size(interaction%couplings_from_partner)
571 if (.not.
associated(partner%quantities%get(interaction%couplings_from_partner(iq))))
then
572 write(
message(1),
'(5a)')
"Interaction '", trim(interaction%label),
"' requires coupling '", &
573 trim(interaction%couplings_from_partner(iq)),
"'"
574 write(
message(2),
'(3a)')
"from partner '", trim(partner%namespace%get()),
"' but it is not available."
581 call this%interactions%add(interaction)
585 call partners%empty()
598 class(
system_t),
intent(inout) :: this
606 call iter%start(this%interactions)
607 do while (iter%has_next())
608 interaction => iter%get_next()
610 select type (partner => interaction%partner)
614 if (partner%algo%iteration + 1 >= this%algo%iteration)
then
615 call interaction%update_partner_couplings(this%algo%iteration)
620 call interaction%update_partner_couplings(this%algo%iteration)
623 all_updated = all_updated .and. interaction%partner_couplings_up_to_date
635 class(
system_t),
intent(inout) :: this
637 integer :: iq, n_quantities
646 call this%update_interactions_start()
649 call iter%start(this%interactions)
650 do while (iter%has_next())
651 interaction => iter%get_next()
654 if (
allocated(interaction%system_quantities))
then
655 n_quantities =
size(interaction%system_quantities)
659 do iq = 1, n_quantities
661 quantity => this%quantities%get(interaction%system_quantities(iq))
663 if (.not. quantity%iteration == this%algo%iteration)
then
668 if (quantity%iteration > this%algo%iteration)
then
669 message(1) =
"The quantity "//trim(quantity%label)//
" is in advance compared to the requested iteration."
670 message(2) =
"The interaction is "//trim(interaction%label)//
"."
675 if (quantity%updated_on_demand)
then
676 call this%update_on_demand_quantity(quantity, this%algo%iteration)
681 if (.not. quantity%iteration == this%algo%iteration .and. .not. quantity%always_available)
then
682 write(
message(1),
'(5a)')
"Interaction ", trim(interaction%label),
" is incompatible with the selected algorithm."
683 write(
message(2),
'(3a)')
"The interaction requires the ", trim(quantity%label), &
684 " at an iteration it is not available."
692 call interaction%update(this%algo%iteration)
697 call this%update_interactions_finish()
704 class(
system_t),
intent(inout) :: this
716 class(
system_t),
intent(inout) :: this
728 class(
system_t),
intent(inout) :: this
730 logical :: restart_write
741 if (restart_write)
then
744 call this%iteration%restart_write(
'restart_iteration_system', this%namespace)
745 call this%algo%iteration%restart_write(
'restart_iteration_algorithm', this%namespace)
746 call iter%start(this%interactions)
747 do while (iter%has_next())
748 interaction => iter%get_next()
749 call interaction%restart_write(this%namespace)
751 call qiter%start(this%quantities)
752 do while (qiter%has_next())
753 quantity => qiter%get_next()
754 call quantity%iteration%restart_write(
'restart_iteration_quantity_'//trim(quantity%label), &
758 call this%restart_write_data()
759 message(1) =
"Wrote restart data for system "//trim(this%namespace%get())
769 class(
system_t),
intent(inout) :: this
780 system_restart_read = this%iteration%restart_read(
'restart_iteration_system', this%namespace)
782 this%algo%iteration%restart_read(
'restart_iteration_algorithm', this%namespace)
783 call iter%start(this%interactions)
784 do while (iter%has_next())
785 interaction => iter%get_next()
788 interaction%iteration = interaction%iteration - 1
790 call qiter%start(this%quantities)
791 do while (qiter%has_next())
792 quantity => qiter%get_next()
794 quantity%iteration%restart_read(
'restart_iteration_quantity_'//trim(quantity%label), &
796 if (quantity%updated_on_demand)
then
798 quantity%iteration = quantity%iteration - 1
805 message(1) =
"Successfully read restart data for system "//trim(this%namespace%get())
814 class(
system_t),
intent(inout) :: this
826 class(
system_t),
intent(inout) :: this
838 class(
system_t),
intent(inout) :: this
850 class(
system_t),
intent(inout) :: this
859 this%algo => factory%create(this)
861 call this%init_iteration_counters()
863 do ii = 1, number_barriers
864 this%barrier(ii)%active = .false.
865 this%barrier(ii)%target_time =
m_zero
876 finished = this%algo%finished()
888 class(
system_t),
intent(inout) :: this
898 call this%algo%init_iteration_counters()
901 call iter%start(this%interactions)
902 do while (iter%has_next())
903 interaction => iter%get_next()
904 interaction%iteration = this%algo%iteration - 1
908 call qiter%start(this%quantities)
909 do while (qiter%has_next())
910 quantity => qiter%get_next()
911 if (quantity%updated_on_demand)
then
914 quantity%iteration = this%algo%iteration - 1
916 quantity%iteration = this%algo%iteration
925 class(
system_t),
intent(inout) :: this
927 logical :: all_updated
929 character(len=:),
allocatable :: updated_quantities(:)
934 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
937 all_updated = this%update_couplings()
938 if (.not. all_updated)
then
939 message(1) =
"Unable to update interactions when initializing the algorithm."
942 call this%update_interactions()
945 if (this%algo%start_operation%id /=
skip)
then
946 if (.not. this%do_algorithmic_operation(this%algo%start_operation, updated_quantities))
then
947 message(1) =
"Unsupported algorithmic operation."
948 write(
message(2),
'(A,A,A)') trim(this%algo%start_operation%id),
": ", trim(this%algo%start_operation%label)
951 if (
allocated(updated_quantities))
then
952 message(1) =
"Update of quantities not allowed in algorithmic operation."
953 write(
message(2),
'(A,A,A)') trim(this%algo%start_operation%id),
": ", trim(this%algo%start_operation%label)
959 call this%update_total_energy()
962 call this%output_start()
965 call this%algo%write_output_header()
968 call this%algo%rewind()
977 class(
system_t),
intent(inout) :: this
980 character(len=:),
allocatable :: updated_quantities(:)
985 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
988 call this%output_finish()
991 if (this%algo%final_operation%id /=
skip)
then
992 if (.not. this%do_algorithmic_operation(this%algo%final_operation, updated_quantities))
then
993 message(1) =
"Unsupported algorithmic operation."
994 write(
message(2),
'(A,A,A)') trim(this%algo%final_operation%id),
": ", trim(this%algo%final_operation%label)
997 if (
allocated(updated_quantities))
then
998 message(1) =
"Update of quantities not allowed in algorithmic operation."
999 write(
message(2),
'(A,A,A)') trim(this%algo%final_operation%id),
": ", trim(this%algo%final_operation%label)
1011 class(
system_t),
intent(in) :: this
1013 real(real64) :: energy
1014 character(len=40) :: fmt
1019 if (abs(energy) >= 1e5)
then
1020 fmt =
'(i7,1x,f14.6,1X,es13.6,1X,i9,1X,'
1022 fmt =
'(i7,1x,f14.6,1X,f13.6,1X,i9,1X,'
1024 if (this%algo%elapsed_time < 1e-3)
then
1025 fmt = trim(fmt)//
'es13.3)'
1027 fmt = trim(fmt)//
'f13.3)'
1030 write(
message(1), fmt) this%iteration%counter(), &
1032 0, this%algo%elapsed_time
1040 class(
system_t),
intent(in) :: this
1052 class(
system_t),
intent(inout) :: this
1060 if (
associated(this%algo))
then
1061 deallocate(this%algo)
1064 call iter%start(this%interactions)
1065 do while (iter%has_next())
1066 interaction => iter%get_next()
1067 if (
associated(interaction))
then
1068 deallocate(interaction)
1083 select type (partner)
1085 call this%add_ptr(partner)
1105 select type (partner)
1108 call iterator%start(this)
1109 do while (iterator%has_next() .and. .not. contains)
1110 system => iterator%get_next()
1111 contains =
associated(system, partner)
1128 select type (ptr => this%get_next_ptr())
1143 class(
system_t),
intent(inout) :: this
1158 class(
system_t),
intent(inout) :: this
1159 real(real64),
intent(in) :: target_time
1160 integer,
intent(in) :: barrier_index
1164 this%barrier(barrier_index)%active = .
true.
1165 this%barrier(barrier_index)%target_time = target_time
1172 class(
system_t),
intent(inout) :: this
1173 integer,
intent(in) :: barrier_index
1177 this%barrier(barrier_index)%active = .false.
1178 this%barrier(barrier_index)%target_time =
m_zero
1185 class(
system_t),
intent(inout) :: this
1186 integer,
intent(in) :: barrier_index
1193 if (this%barrier(barrier_index)%active)
then
1194 iteration = this%iteration + 1
1195 if (iteration%value() > this%barrier(barrier_index)%target_time)
then
1205 class(
system_t),
intent(inout) :: this
1212 do ii = 1, number_barriers
1214 .or. this%arrived_at_barrier(ii)
1227 class(
system_t),
intent(inout) :: this
1234 this%potential_energy =
m_zero
1236 call iter%start(this%interactions)
1237 do while (iter%has_next())
1238 interaction => iter%get_next()
1239 if(.not. interaction%intra_interaction)
then
1240 call interaction%calculate_energy()
1241 this%potential_energy = this%potential_energy + interaction%energy
1254 class(
system_t),
intent(inout) :: this
1261 this%internal_energy =
m_zero
1262 call iter%start(this%interactions)
1263 do while (iter%has_next())
1264 interaction => iter%get_next()
1265 if(interaction%intra_interaction)
then
1266 call interaction%calculate_energy()
1267 this%internal_energy = this%internal_energy + interaction%energy
1279 class(
system_t),
intent(inout) :: this
1283 call this%update_kinetic_energy()
1284 this%total_energy = this%kinetic_energy
1287 call this%update_potential_energy()
1288 this%total_energy = this%total_energy + this%potential_energy
1291 call this%update_internal_energy()
1292 this%total_energy = this%total_energy + this%internal_energy
Execute one operation that is part of a larger algorithm. Returns true if the operation was successfu...
initialize a given interaction of the system
set initial conditions for a system
check whether a system has reached a given tolerance
For some algorithms it might be necessary to store the status of a system at a given algorithmic step...
This module defines the abstract interfact for algorithm factories.
This module implements the basic elements defining algorithms.
character(len=algo_label_len), parameter, public update_interactions
character(len=algo_label_len), parameter, public rewind_algorithm
character(len=algo_label_len), parameter, public update_couplings
character(len=algo_label_len), parameter, public iteration_done
character(len=algo_label_len), parameter, public skip
Operations that can be used by any algorithm and, therefore, should be implemented by all systems.
real(real64), parameter, public m_zero
This module defines the abstract interaction_t class, and some auxiliary classes for interactions.
integer, parameter, public timing_exact
This module defines classes and functions for interaction partners.
This module defines the abstract class for the interaction factory.
integer, parameter, public no_partners
integer, parameter, public all_except
integer, parameter, public only_partners
integer, parameter, public all_partners
This module implements fully polymorphic linked lists, and some specializations thereof.
subroutine, public messages_update_mpi_grp(namespace, mpigrp)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_experimental(name, namespace)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
subroutine mpi_grp_copy(mpi_grp_out, mpi_grp_in)
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...
This module implements the abstract system type.
subroutine, public system_algorithm_start(this)
subroutine, public system_update_total_energy(this)
Calculate the total energy of the system. The total energy is defined as the sum of the kinetic,...
subroutine system_iteration_info(this)
subroutine, public system_init_iteration_counters(this)
Initialize the iteration counters of the system and its interactions, algorithms and quantities.
integer, parameter, public barrier_restart
subroutine system_update_internal_energy(this)
Calculate the internal energy of the system. The internal energy is defined as the sum of all energie...
logical function system_arrived_at_any_barrier(this)
recursive logical function system_list_contains(this, partner)
subroutine, public system_restart_write(this)
subroutine, public system_update_potential_energy(this)
Calculate the potential energy of the system. The potential energy is defined as the sum of all energ...
subroutine, public system_init_parallelization(this, grp)
Basic functionality: copy the MPI group. This function needs to be implemented by extended types that...
subroutine system_output_start(this)
subroutine system_update_interactions_start(this)
subroutine, public system_algorithm_finish(this)
subroutine system_start_barrier(this, target_time, barrier_index)
recursive subroutine, public system_create_interactions(this, interaction_factory, available_partners)
create the interactions of the system
subroutine, public system_end(this)
subroutine system_output_write(this)
subroutine system_update_interactions_finish(this)
subroutine, public system_execute_algorithm(this)
perform one or more algorithmic operations
subroutine system_update_interactions(this)
Attempt to update all interactions of the system.
class(system_t) function, pointer system_iterator_get_next(this)
logical function system_update_couplings(this)
Update the couplings (quantities) of the interaction partners.
logical function system_process_is_slave(this)
logical function system_arrived_at_barrier(this, barrier_index)
recursive logical function system_algorithm_finished(this)
logical function, public system_restart_read(this)
subroutine, public system_new_algorithm(this, factory)
subroutine system_output_finish(this)
subroutine system_list_add_node(this, partner)
add system to list
subroutine, public system_reset_iteration_counters(this, accumulated_iterations)
subroutine system_end_barrier(this, barrier_index)
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
Abstract class for the algorithm factories.
Descriptor of one algorithmic operation.
The ghost ineraction is a dummy interaction, which needs to be setup between otherwise non-interactin...
These class extend the list and list iterator to make an interaction list.
abstract interaction class
abstract class for general interaction partners
iterator for the list of partners
abstract class for interaction factories
type for storing options to be used when creating a given interaction
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 is defined even when running serial.
events marking a function call
handle to keep track of in- out- events
events marking an iteration update
Systems (system_t) can expose quantities that can be used to calculate interactions with other system...
These classes extends the list and list iterator to create a system list.
Abstract class for systems.