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 integer,
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
248 integer,
allocatable :: updated_quantities(:)
254 do while (.not. at_barrier)
256 operation = this%algo%get_current_operation()
259 system_iteration=this%iteration, algo_iteration=this%algo%iteration)
262 operation_done = this%do_algorithmic_operation(operation, updated_quantities)
263 if (
allocated(updated_quantities))
then
265 do iuq = 1,
size(updated_quantities)
266 iq = updated_quantities(iuq)
267 call this%quantities(iq)%iteration%set(this%algo%iteration + 1)
269 this%quantities(iq)%iteration,
"set"))
274 if (.not. operation_done)
then
275 operation_done = this%algo%do_operation(operation)
277 call this%algo%next()
281 if (.not. operation_done)
then
283 select case (operation%id)
286 call this%algo%next()
290 this%iteration = this%iteration + 1
294 call this%update_total_energy()
297 call this%output_write()
300 call this%algo%update_elapsed_time()
305 call this%iteration_info()
307 call this%algo%next()
310 if (.not. this%algo%finished())
then
311 if (.not. this%arrived_at_any_barrier())
then
313 call this%algo%rewind()
318 if (this%algo%continues_after_finished())
then
319 call this%algo%rewind()
327 this%algo%iteration = this%algo%iteration + 1
329 this%algo%iteration,
"tick"))
332 all_updated = this%update_couplings()
336 if (all_updated)
then
337 call this%algo%next()
339 this%algo%iteration = this%algo%iteration - 1
341 this%algo%iteration,
"reverse"))
349 call this%update_interactions()
350 call this%algo%next()
353 message(1) =
"Unsupported algorithmic operation."
354 write(
message(2),
'(A,A,A)') trim(operation%id),
": ", trim(operation%label)
367 class(
system_t),
intent(inout) :: this
368 integer,
intent(in) :: accumulated_iterations
374 character(len=MAX_INFO_LEN) :: extended_label
379 this%algo%iteration = this%algo%iteration - accumulated_iterations
383 call iter%start(this%interactions)
384 do while (iter%has_next())
385 interaction => iter%get_next()
386 interaction%iteration = interaction%iteration - accumulated_iterations
388 extended_label = trim(interaction%label)//
"-"//trim(interaction%partner%namespace%get())
390 interaction%iteration,
"reset"))
395 if (this%quantities(iq)%required)
then
396 this%quantities(iq)%iteration = this%quantities(iq)%iteration - accumulated_iterations
398 this%quantities(iq)%iteration,
"reset"))
420 class(
system_t),
intent(inout) :: this
425 integer :: i, ip, interaction_type
435 assert(
allocated(this%supported_interactions))
436 assert(
allocated(this%supported_interactions_as_partner))
442 call iter%start(available_partners)
443 do while (iter%has_next())
444 partner => iter%get_next()
445 call partner%add_partners_to_list(partners)
448 call iter%start(partners)
449 do while (iter%has_next())
450 partner => iter%get_next()
453 if (partner%namespace%get() == this%namespace%get()) cycle
464 call partners%empty()
468 options = interaction_factory%options(this%namespace, this%supported_interactions)
471 do i = 1,
size(this%supported_interactions)
472 interaction_type = this%supported_interactions(i)
477 assert(count(this%supported_interactions == interaction_type) == 1)
480 call iter%start(available_partners)
481 do while (iter%has_next())
482 partner => iter%get_next()
483 call partner%add_partners_to_list(partners, interaction_type)
487 select case (options(i)%mode)
493 call partners%empty()
497 call iter%start(partners)
498 do while (iter%has_next())
499 partner => iter%get_next()
501 do ip = 1,
size(options(i)%partners)
502 if (partner%namespace%is_contained_in(options(i)%partners(ip)))
then
507 if (.not. in_list)
then
508 call partners%delete(partner)
514 do ip = 1,
size(options(i)%partners)
515 call iter%start(partners)
516 do while (iter%has_next())
517 partner => iter%get_next()
518 if (partner%namespace%is_contained_in(options(i)%partners(ip)))
then
519 call partners%delete(partner)
527 call iter%start(partners)
528 do while (iter%has_next())
529 partner => iter%get_next()
531 interaction => interaction_factory%create(interaction_type, partner)
535 interaction%intra_interaction = partner%namespace%get() == this%namespace%get()
538 interaction%timing = options(i)%timing
540 select type (partner => interaction%partner)
542 if (this%algo%iteration%global_step() /= partner%algo%iteration%global_step() .and. &
543 .not. all(partner%quantities(interaction%couplings_from_partner)%always_available))
then
544 write(
message(1),
'(2a)')
"InteractionTiming was set to exact timing, but systems ", &
545 trim(this%namespace%get())
546 write(
message(2),
'(3a)')
"and ", trim(partner%namespace%get()),
" have incompatible steps."
553 call this%init_interaction(interaction)
554 call interaction%partner%init_interaction_as_partner(interaction)
557 if (
allocated(interaction%system_quantities))
then
558 this%quantities(interaction%system_quantities)%required = .
true.
560 if (
allocated(interaction%couplings_from_partner))
then
561 partner%quantities(interaction%couplings_from_partner)%required = .
true.
565 call this%interactions%add(interaction)
569 call partners%empty()
582 class(
system_t),
intent(inout) :: this
590 call iter%start(this%interactions)
591 do while (iter%has_next())
592 interaction => iter%get_next()
594 select type (partner => interaction%partner)
598 if (partner%algo%iteration + 1 >= this%algo%iteration)
then
599 call interaction%update_partner_couplings(this%algo%iteration)
604 call interaction%update_partner_couplings(this%algo%iteration)
607 all_updated = all_updated .and. interaction%partner_couplings_up_to_date
619 class(
system_t),
intent(inout) :: this
621 integer :: iq, q_id, n_quantities
629 call this%update_interactions_start()
632 call iter%start(this%interactions)
633 do while (iter%has_next())
634 interaction => iter%get_next()
637 if (
allocated(interaction%system_quantities))
then
638 n_quantities =
size(interaction%system_quantities)
642 do iq = 1, n_quantities
644 q_id = interaction%system_quantities(iq)
646 if (.not. this%quantities(q_id)%iteration == this%algo%iteration)
then
649 if (.not. this%quantities(q_id)%updated_on_demand)
then
652 if (.not. this%quantities(q_id)%iteration == this%algo%iteration .and. &
653 .not. this%quantities(q_id)%always_available)
then
654 write(
message(1),
'(5a)')
"Interaction ", trim(interaction%label),
" is incompatible with the selected algorithm."
656 " at a iteration it is not available."
668 if (this%quantities(q_id)%iteration > this%algo%iteration)
then
669 message(1) =
"The quantity iteration is in advance compared to the requested iteration."
673 call this%update_quantity(q_id)
675 this%quantities(q_id)%iteration,
"set"))
680 call interaction%update(this%algo%iteration)
685 call this%update_interactions_finish()
692 class(
system_t),
intent(inout) :: this
704 class(
system_t),
intent(inout) :: this
716 class(
system_t),
intent(inout) :: this
718 logical :: restart_write
727 if (restart_write)
then
730 call this%iteration%restart_write(
'restart_iteration_system', this%namespace)
731 call this%algo%iteration%restart_write(
'restart_iteration_algorithm', this%namespace)
732 call iter%start(this%interactions)
733 do while (iter%has_next())
734 interaction => iter%get_next()
735 call interaction%restart_write(this%namespace)
738 if (this%quantities(ii)%required)
then
739 call this%quantities(ii)%iteration%restart_write(
'restart_iteration_quantity_'//trim(
quantity_label(ii)), &
744 call this%restart_write_data()
745 message(1) =
"Wrote restart data for system "//trim(this%namespace%get())
755 class(
system_t),
intent(inout) :: this
765 system_restart_read = this%iteration%restart_read(
'restart_iteration_system', this%namespace)
767 this%algo%iteration%restart_read(
'restart_iteration_algorithm', this%namespace)
768 call iter%start(this%interactions)
769 do while (iter%has_next())
770 interaction => iter%get_next()
773 interaction%iteration = interaction%iteration - 1
776 if (this%quantities(ii)%required)
then
778 this%quantities(ii)%iteration%restart_read(
'restart_iteration_quantity_'//trim(
quantity_label(ii)), &
781 if (this%quantities(ii)%updated_on_demand)
then
783 this%quantities(ii)%iteration = this%quantities(ii)%iteration - 1
790 message(1) =
"Successfully read restart data for system "//trim(this%namespace%get())
799 class(
system_t),
intent(inout) :: this
811 class(
system_t),
intent(inout) :: this
823 class(
system_t),
intent(inout) :: this
835 class(
system_t),
intent(inout) :: this
844 this%algo => factory%create(this)
846 call this%init_iteration_counters()
848 do ii = 1, number_barriers
849 this%barrier(ii)%active = .false.
850 this%barrier(ii)%target_time =
m_zero
861 finished = this%algo%finished()
873 class(
system_t),
intent(inout) :: this
881 call this%algo%init_iteration_counters()
884 call iter%start(this%interactions)
885 do while (iter%has_next())
886 interaction => iter%get_next()
887 interaction%iteration = this%algo%iteration - 1
891 where (this%quantities%required)
892 this%quantities%iteration = this%algo%iteration
897 where (this%quantities%updated_on_demand)
898 this%quantities%iteration = this%algo%iteration - 1
906 class(
system_t),
intent(inout) :: this
908 logical :: all_updated
910 integer,
allocatable :: updated_quantities(:)
915 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
918 all_updated = this%update_couplings()
919 if (.not. all_updated)
then
920 message(1) =
"Unable to update interactions when initializing the algorithm."
923 call this%update_interactions()
926 if (this%algo%start_operation%id /=
skip)
then
927 if (.not. this%do_algorithmic_operation(this%algo%start_operation, updated_quantities))
then
928 message(1) =
"Unsupported algorithmic operation."
929 write(
message(2),
'(A,A,A)') trim(this%algo%start_operation%id),
": ", trim(this%algo%start_operation%label)
931 else if (
allocated(updated_quantities))
then
932 message(1) =
"Update of quantities not allowed in algorithmic operation."
933 write(
message(2),
'(A,A,A)') trim(this%algo%start_operation%id),
": ", trim(this%algo%start_operation%label)
939 call this%update_total_energy()
942 call this%output_start()
945 call this%algo%write_output_header()
948 call this%algo%rewind()
957 class(
system_t),
intent(inout) :: this
960 integer,
allocatable :: updated_quantities(:)
965 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
968 call this%output_finish()
971 if (this%algo%final_operation%id /=
skip)
then
972 if (.not. this%do_algorithmic_operation(this%algo%final_operation, updated_quantities))
then
973 message(1) =
"Unsupported algorithmic operation."
974 write(
message(2),
'(A,A,A)') trim(this%algo%final_operation%id),
": ", trim(this%algo%final_operation%label)
976 else if (
allocated(updated_quantities))
then
977 message(1) =
"Update of quantities not allowed in algorithmic operation."
978 write(
message(2),
'(A,A,A)') trim(this%algo%final_operation%id),
": ", trim(this%algo%final_operation%label)
992 real(real64) :: energy
993 character(len=40) :: fmt
998 if (abs(energy) >= 1e5)
then
999 fmt =
'(i7,1x,f14.6,1X,es13.6,1X,i9,1X,'
1001 fmt =
'(i7,1x,f14.6,1X,f13.6,1X,i9,1X,'
1003 if (this%algo%elapsed_time < 1e-3)
then
1004 fmt = trim(fmt)//
'es13.3)'
1006 fmt = trim(fmt)//
'f13.3)'
1009 write(
message(1), fmt) this%iteration%counter(), &
1011 0, this%algo%elapsed_time
1019 class(
system_t),
intent(in) :: this
1031 class(
system_t),
intent(inout) :: this
1039 if (
associated(this%algo))
then
1040 deallocate(this%algo)
1043 call iter%start(this%interactions)
1044 do while (iter%has_next())
1045 interaction => iter%get_next()
1046 if (
associated(interaction))
then
1047 deallocate(interaction)
1062 select type (partner)
1064 call this%add_ptr(partner)
1084 select type (partner)
1087 call iterator%start(this)
1088 do while (iterator%has_next() .and. .not. contains)
1089 system => iterator%get_next()
1090 contains =
associated(system, partner)
1107 select type (ptr => this%get_next_ptr())
1122 class(
system_t),
intent(inout) :: this
1137 class(
system_t),
intent(inout) :: this
1138 real(real64),
intent(in) :: target_time
1139 integer,
intent(in) :: barrier_index
1143 this%barrier(barrier_index)%active = .
true.
1144 this%barrier(barrier_index)%target_time = target_time
1151 class(
system_t),
intent(inout) :: this
1152 integer,
intent(in) :: barrier_index
1156 this%barrier(barrier_index)%active = .false.
1157 this%barrier(barrier_index)%target_time =
m_zero
1164 class(
system_t),
intent(inout) :: this
1165 integer,
intent(in) :: barrier_index
1172 if (this%barrier(barrier_index)%active)
then
1173 iteration = this%iteration + 1
1174 if (iteration%value() > this%barrier(barrier_index)%target_time)
then
1184 class(
system_t),
intent(inout) :: this
1191 do ii = 1, number_barriers
1193 .or. this%arrived_at_barrier(ii)
1206 class(
system_t),
intent(inout) :: this
1213 this%potential_energy =
m_zero
1215 call iter%start(this%interactions)
1216 do while (iter%has_next())
1217 interaction => iter%get_next()
1218 if(.not. interaction%intra_interaction)
then
1219 call interaction%calculate_energy()
1220 this%potential_energy = this%potential_energy + interaction%energy
1233 class(
system_t),
intent(inout) :: this
1240 this%internal_energy =
m_zero
1241 call iter%start(this%interactions)
1242 do while (iter%has_next())
1243 interaction => iter%get_next()
1244 if(interaction%intra_interaction)
then
1245 call interaction%calculate_energy()
1246 this%internal_energy = this%internal_energy + interaction%energy
1258 class(
system_t),
intent(inout) :: this
1262 call this%update_kinetic_energy()
1263 this%total_energy = this%kinetic_energy
1266 call this%update_potential_energy()
1267 this%total_energy = this%total_energy + this%potential_energy
1270 call this%update_internal_energy()
1271 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...
character(len=17), dimension(max_quantities), parameter, public quantity_label
integer, parameter, public max_quantities
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
These classes extends the list and list iterator to create a system list.
Abstract class for systems.