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_initial_conditions),
deferred :: initial_conditions
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
139 class(system_t),
target,
intent(inout) :: this
140 class(interaction_t),
intent(inout) :: interaction
147 class(system_t),
intent(inout) :: this
163 class(
system_t),
intent(inout) :: this
165 integer,
allocatable,
intent(out) :: updated_quantities(:)
171 use,
intrinsic :: iso_fortran_env
173 class(system_t),
intent(in) :: this
174 real(real64),
intent(in) :: tol
241 logical :: all_updated, at_barrier, operation_done
244 integer,
allocatable :: updated_quantities(:)
250 do while (.not. at_barrier)
252 operation = this%algo%get_current_operation()
255 system_iteration=this%iteration, algo_iteration=this%algo%iteration)
258 operation_done = this%do_algorithmic_operation(operation, updated_quantities)
259 if (
allocated(updated_quantities))
then
261 do iuq = 1,
size(updated_quantities)
262 iq = updated_quantities(iuq)
263 call this%quantities(iq)%iteration%set(this%algo%iteration + 1)
265 this%quantities(iq)%iteration,
"set"))
270 if (.not. operation_done)
then
271 operation_done = this%algo%do_operation(operation)
273 call this%algo%next()
277 if (.not. operation_done)
then
279 select case (operation%id)
282 call this%algo%next()
286 this%iteration = this%iteration + 1
290 call this%update_total_energy()
293 call this%output_write()
296 call this%algo%update_elapsed_time()
301 call this%iteration_info()
303 call this%algo%next()
306 if (.not. this%arrived_at_any_barrier() .and. .not. this%algorithm_finished())
then
309 call this%algo%rewind()
316 this%algo%iteration = this%algo%iteration + 1
318 this%algo%iteration,
"tick"))
321 all_updated = this%update_couplings()
325 if (all_updated)
then
326 call this%algo%next()
328 this%algo%iteration = this%algo%iteration - 1
330 this%algo%iteration,
"reverse"))
338 call this%update_interactions()
339 call this%algo%next()
342 message(1) =
"Unsupported algorithmic operation."
343 write(
message(2),
'(A,A,A)') trim(operation%id),
": ", trim(operation%label)
356 class(
system_t),
intent(inout) :: this
357 integer,
intent(in) :: accumulated_iterations
363 character(len=MAX_INFO_LEN) :: extended_label
368 this%algo%iteration = this%algo%iteration - accumulated_iterations
372 call iter%start(this%interactions)
373 do while (iter%has_next())
374 interaction => iter%get_next()
375 interaction%iteration = interaction%iteration - accumulated_iterations
377 extended_label = trim(interaction%label)//
"-"//trim(interaction%partner%namespace%get())
379 interaction%iteration,
"reset"))
384 if (this%quantities(iq)%required)
then
385 this%quantities(iq)%iteration = this%quantities(iq)%iteration - accumulated_iterations
387 this%quantities(iq)%iteration,
"reset"))
409 class(
system_t),
intent(inout) :: this
414 integer :: i, ip, interaction_type
424 assert(
allocated(this%supported_interactions))
425 assert(
allocated(this%supported_interactions_as_partner))
429 call iter%start(available_partners)
430 do while (iter%has_next())
431 partner => iter%get_next()
432 call partner%add_partners_to_list(partners)
434 call iter%start(partners)
435 do while (iter%has_next())
436 partner => iter%get_next()
439 if (partner%namespace%get() == this%namespace%get()) cycle
443 call partners%empty()
447 options = interaction_factory%options(this%namespace, this%supported_interactions)
450 do i = 1,
size(this%supported_interactions)
451 interaction_type = this%supported_interactions(i)
456 assert(count(this%supported_interactions == interaction_type) == 1)
459 call iter%start(available_partners)
460 do while (iter%has_next())
461 partner => iter%get_next()
462 call partner%add_partners_to_list(partners, interaction_type)
466 select case (options(i)%mode)
472 call partners%empty()
476 call iter%start(partners)
477 do while (iter%has_next())
478 partner => iter%get_next()
480 do ip = 1,
size(options(i)%partners)
481 if (partner%namespace%is_contained_in(options(i)%partners(ip)))
then
486 if (.not. in_list)
then
487 call partners%delete(partner)
493 do ip = 1,
size(options(i)%partners)
494 call iter%start(partners)
495 do while (iter%has_next())
496 partner => iter%get_next()
497 if (partner%namespace%is_contained_in(options(i)%partners(ip)))
then
498 call partners%delete(partner)
506 call iter%start(partners)
507 do while (iter%has_next())
508 partner => iter%get_next()
510 interaction => interaction_factory%create(interaction_type, partner)
513 interaction%intra_interaction = partner%namespace%get() == this%namespace%get()
516 interaction%timing = options(i)%timing
518 select type (partner => interaction%partner)
520 if (this%algo%iteration%global_step() /= partner%algo%iteration%global_step() .and. &
521 .not. all(partner%quantities(interaction%couplings_from_partner)%always_available))
then
522 write(
message(1),
'(2a)')
"InteractionTiming was set to exact timing, but systems ", &
523 trim(this%namespace%get())
524 write(
message(2),
'(3a)')
"and ", trim(partner%namespace%get()),
" have incompatible steps."
531 call this%init_interaction(interaction)
532 call interaction%partner%init_interaction_as_partner(interaction)
535 if (
allocated(interaction%system_quantities))
then
536 this%quantities(interaction%system_quantities)%required = .
true.
538 if (
allocated(interaction%couplings_from_partner))
then
539 partner%quantities(interaction%couplings_from_partner)%required = .
true.
543 call this%interactions%add(interaction)
547 call partners%empty()
560 class(
system_t),
intent(inout) :: this
568 call iter%start(this%interactions)
569 do while (iter%has_next())
570 interaction => iter%get_next()
572 select type (partner => interaction%partner)
576 if (partner%algo%iteration + 1 >= this%algo%iteration)
then
577 call interaction%update_partner_couplings(this%algo%iteration)
582 call interaction%update_partner_couplings(this%algo%iteration)
585 all_updated = all_updated .and. interaction%partner_couplings_up_to_date
597 class(
system_t),
intent(inout) :: this
599 integer :: iq, q_id, n_quantities
607 call this%update_interactions_start()
610 call iter%start(this%interactions)
611 do while (iter%has_next())
612 interaction => iter%get_next()
615 if (
allocated(interaction%system_quantities))
then
616 n_quantities =
size(interaction%system_quantities)
620 do iq = 1, n_quantities
622 q_id = interaction%system_quantities(iq)
624 if (.not. this%quantities(q_id)%iteration == this%algo%iteration)
then
627 if (.not. this%quantities(q_id)%updated_on_demand)
then
630 if (.not. this%quantities(q_id)%iteration == this%algo%iteration .and. &
631 .not. this%quantities(q_id)%always_available)
then
632 write(
message(1),
'(5a)')
"Interaction ", trim(interaction%label),
" is incompatible with the selected algorithm."
634 " at a iteration it is not available."
646 if (this%quantities(q_id)%iteration > this%algo%iteration)
then
647 message(1) =
"The quantity iteration is in advance compared to the requested iteration."
651 call this%update_quantity(q_id)
653 this%quantities(q_id)%iteration,
"set"))
658 call interaction%update(this%algo%iteration)
663 call this%update_interactions_finish()
670 class(
system_t),
intent(inout) :: this
682 class(
system_t),
intent(inout) :: this
694 class(
system_t),
intent(inout) :: this
696 logical :: restart_write
705 if (restart_write)
then
708 call this%iteration%restart_write(
'restart_iteration_system', this%namespace)
709 call this%algo%iteration%restart_write(
'restart_iteration_propagator', this%namespace)
710 call iter%start(this%interactions)
711 do while (iter%has_next())
712 interaction => iter%get_next()
713 call interaction%restart_write(this%namespace)
716 if (this%quantities(ii)%required)
then
717 call this%quantities(ii)%iteration%restart_write(
'restart_iteration_quantity_'//trim(
quantity_label(ii)), &
722 call this%restart_write_data()
723 message(1) =
"Wrote restart data for system "//trim(this%namespace%get())
733 class(
system_t),
intent(inout) :: this
743 system_restart_read = this%iteration%restart_read(
'restart_iteration_system', this%namespace)
745 this%algo%iteration%restart_read(
'restart_iteration_propagator', this%namespace)
746 call iter%start(this%interactions)
747 do while (iter%has_next())
748 interaction => iter%get_next()
751 interaction%iteration = interaction%iteration - 1
754 if (this%quantities(ii)%required)
then
756 this%quantities(ii)%iteration%restart_read(
'restart_iteration_quantity_'//trim(
quantity_label(ii)), &
759 if (this%quantities(ii)%updated_on_demand)
then
761 this%quantities(ii)%iteration = this%quantities(ii)%iteration - 1
768 message(1) =
"Successfully read restart data for system "//trim(this%namespace%get())
777 class(
system_t),
intent(inout) :: this
789 class(
system_t),
intent(inout) :: this
801 class(
system_t),
intent(inout) :: this
813 class(
system_t),
intent(inout) :: this
822 this%algo => factory%create(this)
824 call this%init_iteration_counters()
826 do ii = 1, number_barriers
827 this%barrier(ii)%active = .false.
828 this%barrier(ii)%target_time =
m_zero
839 finished = this%algo%finished()
851 class(
system_t),
intent(inout) :: this
859 call this%algo%init_iteration_counters()
862 call iter%start(this%interactions)
863 do while (iter%has_next())
864 interaction => iter%get_next()
865 interaction%iteration = this%algo%iteration - 1
869 where (this%quantities%required)
870 this%quantities%iteration = this%algo%iteration
875 where (this%quantities%updated_on_demand)
876 this%quantities%iteration = this%algo%iteration - 1
884 class(
system_t),
intent(inout) :: this
886 logical :: all_updated
888 integer,
allocatable :: updated_quantities(:)
893 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
896 all_updated = this%update_couplings()
897 if (.not. all_updated)
then
898 message(1) =
"Unable to update interactions when initializing the propagation."
901 call this%update_interactions()
904 if (this%algo%start_operation%id /=
skip)
then
905 if (.not. this%do_algorithmic_operation(this%algo%start_operation, updated_quantities))
then
906 message(1) =
"Unsupported algorithmic operation."
907 write(
message(2),
'(A,A,A)') trim(this%algo%start_operation%id),
": ", trim(this%algo%start_operation%label)
909 else if (
allocated(updated_quantities))
then
910 message(1) =
"Update of quantities not allowed in algorithmic operation."
911 write(
message(2),
'(A,A,A)') trim(this%algo%start_operation%id),
": ", trim(this%algo%start_operation%label)
917 call this%update_total_energy()
920 call this%output_start()
924 write(
message(1),
'(a6,1x,a14,1x,a13,1x,a10,1x,a15)')
'Iter',
'Time',
'Energy',
'SC Steps',
'Elapsed Time'
929 call this%algo%rewind()
938 class(
system_t),
intent(inout) :: this
941 integer,
allocatable :: updated_quantities(:)
946 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
949 call this%output_finish()
952 if (this%algo%final_operation%id /=
skip)
then
953 if (.not. this%do_algorithmic_operation(this%algo%final_operation, updated_quantities))
then
954 message(1) =
"Unsupported algorithmic operation."
955 write(
message(2),
'(A,A,A)') trim(this%algo%final_operation%id),
": ", trim(this%algo%final_operation%label)
957 else if (
allocated(updated_quantities))
then
958 message(1) =
"Update of quantities not allowed in algorithmic operation."
959 write(
message(2),
'(A,A,A)') trim(this%algo%final_operation%id),
": ", trim(this%algo%final_operation%label)
973 real(real64) :: energy
974 character(len=40) :: fmt
979 if (abs(energy) >= 1e5)
then
980 fmt =
'(i7,1x,f14.6,1X,es13.6,1X,i9,1X,'
982 fmt =
'(i7,1x,f14.6,1X,f13.6,1X,i9,1X,'
984 if (this%algo%elapsed_time < 1e-3)
then
985 fmt = trim(fmt)//
'es13.3)'
987 fmt = trim(fmt)//
'f13.3)'
990 write(
message(1), fmt) this%iteration%counter(), &
992 0, this%algo%elapsed_time
1000 class(
system_t),
intent(in) :: this
1012 class(
system_t),
intent(inout) :: this
1020 if (
associated(this%algo))
then
1021 deallocate(this%algo)
1024 call iter%start(this%interactions)
1025 do while (iter%has_next())
1026 interaction => iter%get_next()
1027 if (
associated(interaction))
then
1028 deallocate(interaction)
1042 select type (partner)
1044 call this%add_ptr(partner)
1064 select type (partner)
1067 call iterator%start(this)
1068 do while (iterator%has_next() .and. .not. contains)
1069 system => iterator%get_next()
1070 contains =
associated(system, partner)
1087 select type (ptr => this%get_next_ptr())
1102 class(
system_t),
intent(inout) :: this
1117 class(
system_t),
intent(inout) :: this
1118 real(real64),
intent(in) :: target_time
1119 integer,
intent(in) :: barrier_index
1123 this%barrier(barrier_index)%active = .
true.
1124 this%barrier(barrier_index)%target_time = target_time
1131 class(
system_t),
intent(inout) :: this
1132 integer,
intent(in) :: barrier_index
1136 this%barrier(barrier_index)%active = .false.
1137 this%barrier(barrier_index)%target_time =
m_zero
1144 class(
system_t),
intent(inout) :: this
1145 integer,
intent(in) :: barrier_index
1152 if (this%barrier(barrier_index)%active)
then
1153 iteration = this%iteration + 1
1154 if (iteration%value() > this%barrier(barrier_index)%target_time)
then
1164 class(
system_t),
intent(inout) :: this
1171 do ii = 1, number_barriers
1173 .or. this%arrived_at_barrier(ii)
1186 class(
system_t),
intent(inout) :: this
1193 this%potential_energy =
m_zero
1195 call iter%start(this%interactions)
1196 do while (iter%has_next())
1197 interaction => iter%get_next()
1198 if(.not. interaction%intra_interaction)
then
1199 call interaction%calculate_energy()
1200 this%potential_energy = this%potential_energy + interaction%energy
1213 class(
system_t),
intent(inout) :: this
1220 this%internal_energy =
m_zero
1221 call iter%start(this%interactions)
1222 do while (iter%has_next())
1223 interaction => iter%get_next()
1224 if(interaction%intra_interaction)
then
1225 call interaction%calculate_energy()
1226 this%internal_energy = this%internal_energy + interaction%energy
1238 class(
system_t),
intent(inout) :: this
1242 call this%update_kinetic_energy()
1243 this%total_energy = this%kinetic_energy
1246 call this%update_potential_energy()
1247 this%total_energy = this%total_energy + this%potential_energy
1250 call this%update_internal_energy()
1251 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_print_with_emphasis(msg, iunit, namespace)
character(len=512), private msg
subroutine, public messages_update_mpi_grp(namespace, mpigrp)
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
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 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_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 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_propagation_finish(this)
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 system_output_finish(this)
subroutine system_list_add_node(this, partner)
subroutine, public system_propagation_start(this)
subroutine, public system_reset_iteration_counters(this, accumulated_iterations)
subroutine, public system_init_algorithm(this, factory)
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.