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))
431 call iter%start(available_partners)
432 do while (iter%has_next())
433 partner => iter%get_next()
434 call partner%add_partners_to_list(partners)
437 call iter%start(partners)
438 do while (iter%has_next())
439 partner => iter%get_next()
442 if (partner%namespace%get() == this%namespace%get()) cycle
453 call partners%empty()
457 options = interaction_factory%options(this%namespace, this%supported_interactions)
460 do i = 1,
size(this%supported_interactions)
461 interaction_type = this%supported_interactions(i)
466 assert(count(this%supported_interactions == interaction_type) == 1)
469 call iter%start(available_partners)
470 do while (iter%has_next())
471 partner => iter%get_next()
472 call partner%add_partners_to_list(partners, interaction_type)
476 select case (options(i)%mode)
482 call partners%empty()
486 call iter%start(partners)
487 do while (iter%has_next())
488 partner => iter%get_next()
490 do ip = 1,
size(options(i)%partners)
491 if (partner%namespace%is_contained_in(options(i)%partners(ip)))
then
496 if (.not. in_list)
then
497 call partners%delete(partner)
503 do ip = 1,
size(options(i)%partners)
504 call iter%start(partners)
505 do while (iter%has_next())
506 partner => iter%get_next()
507 if (partner%namespace%is_contained_in(options(i)%partners(ip)))
then
508 call partners%delete(partner)
516 call iter%start(partners)
517 do while (iter%has_next())
518 partner => iter%get_next()
520 interaction => interaction_factory%create(interaction_type, partner)
524 interaction%intra_interaction = partner%namespace%get() == this%namespace%get()
527 interaction%timing = options(i)%timing
529 select type (partner => interaction%partner)
531 if (this%algo%iteration%global_step() /= partner%algo%iteration%global_step() .and. &
532 .not. all(partner%quantities(interaction%couplings_from_partner)%always_available))
then
533 write(
message(1),
'(2a)')
"InteractionTiming was set to exact timing, but systems ", &
534 trim(this%namespace%get())
535 write(
message(2),
'(3a)')
"and ", trim(partner%namespace%get()),
" have incompatible steps."
542 call this%init_interaction(interaction)
543 call interaction%partner%init_interaction_as_partner(interaction)
546 if (
allocated(interaction%system_quantities))
then
547 this%quantities(interaction%system_quantities)%required = .
true.
549 if (
allocated(interaction%couplings_from_partner))
then
550 partner%quantities(interaction%couplings_from_partner)%required = .
true.
554 call this%interactions%add(interaction)
558 call partners%empty()
571 class(
system_t),
intent(inout) :: this
579 call iter%start(this%interactions)
580 do while (iter%has_next())
581 interaction => iter%get_next()
583 select type (partner => interaction%partner)
587 if (partner%algo%iteration + 1 >= this%algo%iteration)
then
588 call interaction%update_partner_couplings(this%algo%iteration)
593 call interaction%update_partner_couplings(this%algo%iteration)
596 all_updated = all_updated .and. interaction%partner_couplings_up_to_date
608 class(
system_t),
intent(inout) :: this
610 integer :: iq, q_id, n_quantities
618 call this%update_interactions_start()
621 call iter%start(this%interactions)
622 do while (iter%has_next())
623 interaction => iter%get_next()
626 if (
allocated(interaction%system_quantities))
then
627 n_quantities =
size(interaction%system_quantities)
631 do iq = 1, n_quantities
633 q_id = interaction%system_quantities(iq)
635 if (.not. this%quantities(q_id)%iteration == this%algo%iteration)
then
638 if (.not. this%quantities(q_id)%updated_on_demand)
then
641 if (.not. this%quantities(q_id)%iteration == this%algo%iteration .and. &
642 .not. this%quantities(q_id)%always_available)
then
643 write(
message(1),
'(5a)')
"Interaction ", trim(interaction%label),
" is incompatible with the selected algorithm."
645 " at a iteration it is not available."
657 if (this%quantities(q_id)%iteration > this%algo%iteration)
then
658 message(1) =
"The quantity iteration is in advance compared to the requested iteration."
662 call this%update_quantity(q_id)
664 this%quantities(q_id)%iteration,
"set"))
669 call interaction%update(this%algo%iteration)
674 call this%update_interactions_finish()
681 class(
system_t),
intent(inout) :: this
693 class(
system_t),
intent(inout) :: this
705 class(
system_t),
intent(inout) :: this
707 logical :: restart_write
716 if (restart_write)
then
719 call this%iteration%restart_write(
'restart_iteration_system', this%namespace)
720 call this%algo%iteration%restart_write(
'restart_iteration_propagator', this%namespace)
721 call iter%start(this%interactions)
722 do while (iter%has_next())
723 interaction => iter%get_next()
724 call interaction%restart_write(this%namespace)
727 if (this%quantities(ii)%required)
then
728 call this%quantities(ii)%iteration%restart_write(
'restart_iteration_quantity_'//trim(
quantity_label(ii)), &
733 call this%restart_write_data()
734 message(1) =
"Wrote restart data for system "//trim(this%namespace%get())
744 class(
system_t),
intent(inout) :: this
754 system_restart_read = this%iteration%restart_read(
'restart_iteration_system', this%namespace)
756 this%algo%iteration%restart_read(
'restart_iteration_propagator', this%namespace)
757 call iter%start(this%interactions)
758 do while (iter%has_next())
759 interaction => iter%get_next()
762 interaction%iteration = interaction%iteration - 1
765 if (this%quantities(ii)%required)
then
767 this%quantities(ii)%iteration%restart_read(
'restart_iteration_quantity_'//trim(
quantity_label(ii)), &
770 if (this%quantities(ii)%updated_on_demand)
then
772 this%quantities(ii)%iteration = this%quantities(ii)%iteration - 1
779 message(1) =
"Successfully read restart data for system "//trim(this%namespace%get())
788 class(
system_t),
intent(inout) :: this
800 class(
system_t),
intent(inout) :: this
812 class(
system_t),
intent(inout) :: this
824 class(
system_t),
intent(inout) :: this
833 this%algo => factory%create(this)
835 call this%init_iteration_counters()
837 do ii = 1, number_barriers
838 this%barrier(ii)%active = .false.
839 this%barrier(ii)%target_time =
m_zero
850 finished = this%algo%finished()
862 class(
system_t),
intent(inout) :: this
870 call this%algo%init_iteration_counters()
873 call iter%start(this%interactions)
874 do while (iter%has_next())
875 interaction => iter%get_next()
876 interaction%iteration = this%algo%iteration - 1
880 where (this%quantities%required)
881 this%quantities%iteration = this%algo%iteration
886 where (this%quantities%updated_on_demand)
887 this%quantities%iteration = this%algo%iteration - 1
895 class(
system_t),
intent(inout) :: this
897 logical :: all_updated
899 integer,
allocatable :: updated_quantities(:)
904 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
907 all_updated = this%update_couplings()
908 if (.not. all_updated)
then
909 message(1) =
"Unable to update interactions when initializing the propagation."
912 call this%update_interactions()
915 if (this%algo%start_operation%id /=
skip)
then
916 if (.not. this%do_algorithmic_operation(this%algo%start_operation, updated_quantities))
then
917 message(1) =
"Unsupported algorithmic operation."
918 write(
message(2),
'(A,A,A)') trim(this%algo%start_operation%id),
": ", trim(this%algo%start_operation%label)
920 else if (
allocated(updated_quantities))
then
921 message(1) =
"Update of quantities not allowed in algorithmic operation."
922 write(
message(2),
'(A,A,A)') trim(this%algo%start_operation%id),
": ", trim(this%algo%start_operation%label)
928 call this%update_total_energy()
931 call this%output_start()
935 write(
message(1),
'(a6,1x,a14,1x,a13,1x,a10,1x,a15)')
'Iter',
'Time',
'Energy',
'SC Steps',
'Elapsed Time'
940 call this%algo%rewind()
949 class(
system_t),
intent(inout) :: this
952 integer,
allocatable :: updated_quantities(:)
957 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
960 call this%output_finish()
963 if (this%algo%final_operation%id /=
skip)
then
964 if (.not. this%do_algorithmic_operation(this%algo%final_operation, updated_quantities))
then
965 message(1) =
"Unsupported algorithmic operation."
966 write(
message(2),
'(A,A,A)') trim(this%algo%final_operation%id),
": ", trim(this%algo%final_operation%label)
968 else if (
allocated(updated_quantities))
then
969 message(1) =
"Update of quantities not allowed in algorithmic operation."
970 write(
message(2),
'(A,A,A)') trim(this%algo%final_operation%id),
": ", trim(this%algo%final_operation%label)
984 real(real64) :: energy
985 character(len=40) :: fmt
990 if (abs(energy) >= 1e5)
then
991 fmt =
'(i7,1x,f14.6,1X,es13.6,1X,i9,1X,'
993 fmt =
'(i7,1x,f14.6,1X,f13.6,1X,i9,1X,'
995 if (this%algo%elapsed_time < 1e-3)
then
996 fmt = trim(fmt)//
'es13.3)'
998 fmt = trim(fmt)//
'f13.3)'
1001 write(
message(1), fmt) this%iteration%counter(), &
1003 0, this%algo%elapsed_time
1011 class(
system_t),
intent(in) :: this
1023 class(
system_t),
intent(inout) :: this
1031 if (
associated(this%algo))
then
1032 deallocate(this%algo)
1035 call iter%start(this%interactions)
1036 do while (iter%has_next())
1037 interaction => iter%get_next()
1038 if (
associated(interaction))
then
1039 deallocate(interaction)
1054 select type (partner)
1056 call this%add_ptr(partner)
1076 select type (partner)
1079 call iterator%start(this)
1080 do while (iterator%has_next() .and. .not. contains)
1081 system => iterator%get_next()
1082 contains =
associated(system, partner)
1099 select type (ptr => this%get_next_ptr())
1114 class(
system_t),
intent(inout) :: this
1129 class(
system_t),
intent(inout) :: this
1130 real(real64),
intent(in) :: target_time
1131 integer,
intent(in) :: barrier_index
1135 this%barrier(barrier_index)%active = .
true.
1136 this%barrier(barrier_index)%target_time = target_time
1143 class(
system_t),
intent(inout) :: this
1144 integer,
intent(in) :: barrier_index
1148 this%barrier(barrier_index)%active = .false.
1149 this%barrier(barrier_index)%target_time =
m_zero
1156 class(
system_t),
intent(inout) :: this
1157 integer,
intent(in) :: barrier_index
1164 if (this%barrier(barrier_index)%active)
then
1165 iteration = this%iteration + 1
1166 if (iteration%value() > this%barrier(barrier_index)%target_time)
then
1176 class(
system_t),
intent(inout) :: this
1183 do ii = 1, number_barriers
1185 .or. this%arrived_at_barrier(ii)
1198 class(
system_t),
intent(inout) :: this
1205 this%potential_energy =
m_zero
1207 call iter%start(this%interactions)
1208 do while (iter%has_next())
1209 interaction => iter%get_next()
1210 if(.not. interaction%intra_interaction)
then
1211 call interaction%calculate_energy()
1212 this%potential_energy = this%potential_energy + interaction%energy
1225 class(
system_t),
intent(inout) :: this
1232 this%internal_energy =
m_zero
1233 call iter%start(this%interactions)
1234 do while (iter%has_next())
1235 interaction => iter%get_next()
1236 if(interaction%intra_interaction)
then
1237 call interaction%calculate_energy()
1238 this%internal_energy = this%internal_energy + interaction%energy
1250 class(
system_t),
intent(inout) :: this
1254 call this%update_kinetic_energy()
1255 this%total_energy = this%kinetic_energy
1258 call this%update_potential_energy()
1259 this%total_energy = this%total_energy + this%potential_energy
1262 call this%update_internal_energy()
1263 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)
add system to list
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.