72 integer,
parameter,
public :: &
73 NUMBER_BARRIERS = 1, &
81 class(algorithm_t),
pointer,
public :: algo => null()
83 integer,
public :: accumulated_loop_ticks
85 integer,
public :: interaction_timing
88 type(integer_list_t),
public :: supported_interactions
89 type(interaction_list_t),
public :: interactions
91 type(mpi_grp_t),
public :: grp
93 type(barrier_t) :: barrier(NUMBER_BARRIERS)
94 float,
public :: kinetic_energy
95 float,
public :: potential_energy
96 float,
public :: internal_energy
97 float,
public :: total_energy
127 procedure(system_init_interaction),
deferred :: init_interaction
128 procedure(system_initial_conditions),
deferred :: initial_conditions
129 procedure(system_do_algorithmic_operation),
deferred :: do_algorithmic_operation
130 procedure(system_is_tolerance_reached),
deferred :: is_tolerance_reached
131 procedure(system_update_quantity),
deferred :: update_quantity
132 procedure(system_update_exposed_quantity),
deferred :: update_exposed_quantity
133 procedure(system_restart_write_data),
deferred :: restart_write_data
134 procedure(system_restart_read_data),
deferred :: restart_read_data
135 procedure(system_update_kinetic_energy),
deferred :: update_kinetic_energy
145 class(system_t),
target,
intent(inout) :: this
146 class(interaction_t),
intent(inout) :: interaction
168 integer,
allocatable,
intent(out) :: updated_quantities(:)
176 float,
intent(in) :: tol
190 integer,
intent(in) :: iq
198 integer,
intent(in) :: iq
253 class(
system_t),
intent(inout) :: this
256 logical :: all_updated, at_barrier, operation_done
259 integer,
allocatable :: updated_quantities(:)
265 do while (.not. at_barrier)
267 operation = this%algo%get_current_operation()
270 system_clock=this%clock, prop_clock=this%algo%clock)
273 operation_done = this%do_algorithmic_operation(operation, updated_quantities)
274 if (
allocated(updated_quantities))
then
276 do iuq = 1,
size(updated_quantities)
277 iq = updated_quantities(iuq)
278 if (.not. this%algo%inside_scf)
then
279 this%quantities(iq)%clock = this%quantities(iq)%clock +
clock_tick
282 call this%quantities(iq)%clock%set_time(this%algo%clock)
286 this%quantities(iq)%clock,
"set"))
291 if (.not. operation_done)
then
292 operation_done = this%algo%do_operation(operation)
294 call this%algo%next()
298 if (.not. operation_done)
then
300 select case (operation%id)
303 call this%algo%next()
311 call this%update_total_energy()
314 call this%output_write()
317 call this%algo%update_elapsed_time()
322 call this%iteration_info()
324 call this%algo%next()
327 if (.not. this%arrived_at_any_barrier() .and. .not. this%algorithm_finished())
then
330 call this%algo%rewind()
341 all_updated = this%update_interactions()
345 if (all_updated)
then
346 this%accumulated_loop_ticks = this%accumulated_loop_ticks + 1
347 call this%algo%next()
349 this%algo%clock = this%algo%clock -
clock_tick
357 message(1) =
"Unsupported algorithmic operation."
358 write(
message(2),
'(A,A,A)') trim(operation%id),
": ", trim(operation%label)
371 class(
system_t),
intent(inout) :: this
372 integer,
intent(in) :: accumulated_ticks
378 character(len=MAX_INFO_LEN) :: extended_label
383 this%algo%clock = this%algo%clock - accumulated_ticks*
clock_tick
387 call iter%start(this%interactions)
388 do while (iter%has_next())
389 interaction => iter%get_next()
390 interaction%clock = interaction%clock - accumulated_ticks*
clock_tick
392 select type (interaction)
394 extended_label = trim(interaction%label)//
"-"//trim(interaction%partner%namespace%get())
396 extended_label = trim(interaction%label)
399 interaction%clock,
"reset"))
404 if (this%quantities(iq)%required)
then
405 this%quantities(iq)%clock = this%quantities(iq)%clock - accumulated_ticks*
clock_tick
407 this%quantities(iq)%clock,
"reset"))
419 class(
system_t),
intent(inout) :: partner
420 type(
clock_t),
intent(in) :: requested_time
423 logical :: ahead_in_time, right_on_time, need_to_copy
432 partner_clock = partner%clock, &
433 requested_clock = requested_time, &
434 interaction_clock = interaction%clock)
436 select type (interaction)
439 if (partner%algo%inside_scf .or. partner%algo%clock +
clock_tick < requested_time)
then
442 allowed_to_update = .false.
444 allowed_to_update = .
true.
445 need_to_copy = .
true.
446 do iq = 1,
size(interaction%partner_quantities)
448 q_id = interaction%partner_quantities(iq)
451 assert(partner%quantities(q_id)%required)
454 if (partner%quantities(q_id)%updated_on_demand)
then
455 if(partner%quantities(q_id)%clock < requested_time .and. &
456 (partner%quantities(q_id)%clock +
clock_tick <= requested_time .or. &
457 (partner%interaction_timing == option__interactiontiming__timing_retarded .and. &
458 partner%quantities(q_id)%clock +
clock_tick > requested_time)))
then
461 call partner%update_exposed_quantity(q_id)
463 partner%quantities(q_id)%clock = partner%quantities(q_id)%clock +
clock_tick
465 partner%quantities(q_id)%clock,
"set"))
469 if (partner%quantities(q_id)%available_at_any_time)
then
471 ahead_in_time = .false.
472 right_on_time = .
true.
475 ahead_in_time = partner%quantities(q_id)%clock > requested_time
476 right_on_time = partner%quantities(q_id)%clock == requested_time
479 select case (partner%interaction_timing)
480 case (option__interactiontiming__timing_exact)
482 allowed_to_update = allowed_to_update .and. right_on_time
483 need_to_copy = allowed_to_update
484 case (option__interactiontiming__timing_retarded)
486 allowed_to_update = allowed_to_update .and. &
487 (right_on_time .or. ahead_in_time)
488 need_to_copy = need_to_copy .and. .not. ahead_in_time
496 if (allowed_to_update .and. need_to_copy)
then
497 select type (interaction)
502 call partner%copy_quantities_to_interaction(interaction)
508 message(1) =
"A system can only expose quantities to an interaction as a partner."
513 partner_clock = partner%clock, &
514 requested_clock = requested_time, &
515 interaction_clock = interaction%clock)
522 class(
system_t),
intent(inout) :: this
529 call iter%start(this%interactions)
530 do while (iter%has_next())
531 interaction => iter%get_next()
532 select type (interaction)
536 call this%init_interaction(interaction)
537 call interaction%partner%init_interaction_as_partner(interaction)
539 call this%init_interaction(interaction)
548 class(
system_t),
intent(inout) :: this
550 logical :: none_updated
551 integer :: iq, q_id, n_quantities
560 none_updated = .
true.
561 call iter%start(this%interactions)
562 do while (iter%has_next())
563 interaction => iter%get_next()
564 if (interaction%clock == this%algo%clock)
then
565 none_updated = .false.
569 if (none_updated)
then
570 call this%update_interactions_start()
575 call iter%start(this%interactions)
576 do while (iter%has_next())
577 interaction => iter%get_next()
579 if (.not. interaction%clock == this%algo%clock)
then
580 if (
allocated(interaction%system_quantities))
then
581 n_quantities =
size(interaction%system_quantities)
587 do iq = 1, n_quantities
589 q_id = interaction%system_quantities(iq)
592 assert(this%quantities(q_id)%required)
594 if (.not. this%quantities(q_id)%updated_on_demand)
then
597 if (.not. this%quantities(q_id)%clock == this%algo%clock .and. .not. this%quantities(q_id)%available_at_any_time)
then
598 write(
message(1),
'(5a)')
"Interaction ", trim(interaction%label),
" is incompatible with the selected algorithm."
600 " at a time it is not available."
610 if (.not. this%quantities(q_id)%clock == this%algo%clock)
then
615 if (this%quantities(q_id)%clock > this%algo%clock)
then
616 message(1) =
"The quantity clock is in advance compared to the requested time."
620 call this%update_quantity(q_id)
622 this%quantities(q_id)%clock,
"set"))
628 all_updated = interaction%update(this%algo%clock) .and. all_updated
634 if (all_updated)
then
635 call this%update_interactions_finish()
643 class(
system_t),
intent(inout) :: this
655 class(
system_t),
intent(inout) :: this
667 class(
system_t),
intent(inout) :: this
669 logical :: restart_write
678 if (restart_write)
then
681 call this%clock%restart_write(
'restart_clock_system', this%namespace)
682 call this%algo%clock%restart_write(
'restart_clock_propagator', this%namespace)
683 call iter%start(this%interactions)
684 do while (iter%has_next())
685 interaction => iter%get_next()
686 call interaction%restart_write(this%namespace)
689 if (this%quantities(ii)%required)
then
690 call this%quantities(ii)%clock%restart_write(
'restart_clock_quantity_'//trim(
quantity_label(ii)), &
695 call this%restart_write_data()
696 message(1) =
"Wrote restart data for system "//trim(this%namespace%get())
706 class(
system_t),
intent(inout) :: this
718 this%algo%clock%restart_read(
'restart_clock_propagator', this%namespace)
719 call iter%start(this%interactions)
720 do while (iter%has_next())
721 interaction => iter%get_next()
724 interaction%clock = interaction%clock -
clock_tick
727 if (this%quantities(ii)%required)
then
729 this%quantities(ii)%clock%restart_read(
'restart_clock_quantity_'//trim(
quantity_label(ii)), &
732 if (this%quantities(ii)%updated_on_demand)
then
734 this%quantities(ii)%clock = this%quantities(ii)%clock -
clock_tick
741 message(1) =
"Successfully read restart data for system "//trim(this%namespace%get())
750 class(
system_t),
intent(inout) :: this
762 class(
system_t),
intent(inout) :: this
774 class(
system_t),
intent(inout) :: this
786 class(
system_t),
intent(inout) :: this
795 this%algo => factory%create(this)
797 call this%init_clocks()
812 option__interactiontiming__timing_exact, &
813 this%interaction_timing)
819 do ii = 1, number_barriers
820 this%barrier(ii)%active = .false.
821 this%barrier(ii)%target_time =
m_zero
832 finished = this%algo%finished()
838 class(
system_t),
intent(inout) :: this
846 this%algo%clock =
clock_t(time_step=this%algo%dt/this%algo%algo_steps)
849 this%clock =
clock_t(time_step=this%algo%dt)
852 call iter%start(this%interactions)
853 do while (iter%has_next())
854 interaction => iter%get_next()
855 interaction%clock = this%algo%clock -
clock_tick
859 where (this%quantities%required)
860 this%quantities%clock = this%algo%clock
862 where (this%quantities%updated_on_demand)
863 this%quantities%clock = this%algo%clock -
clock_tick
871 class(
system_t),
intent(inout) :: this
873 logical :: all_updated
875 integer,
allocatable :: updated_quantities(:)
880 system_clock = this%clock, prop_clock = this%algo%clock)
883 all_updated = this%update_interactions()
884 if (.not. all_updated)
then
885 message(1) =
"Unable to update interactions when initializing the propagation."
890 if (this%algo%start_step%id /=
skip)
then
891 if (.not. this%do_algorithmic_operation(this%algo%start_step, updated_quantities))
then
892 message(1) =
"Unsupported algorithmic operation."
893 write(
message(2),
'(A,A,A)') trim(this%algo%start_step%id),
": ", trim(this%algo%start_step%label)
895 else if (
allocated(updated_quantities))
then
896 message(1) =
"Update of quantities not allowed in algorithmic operation."
897 write(
message(2),
'(A,A,A)') trim(this%algo%final_step%id),
": ", trim(this%algo%final_step%label)
903 call this%update_total_energy()
906 call this%output_start()
910 write(
message(1),
'(a6,1x,a14,1x,a13,1x,a10,1x,a15)')
'Iter',
'Time',
'Energy',
'SC Steps',
'Elapsed Time'
915 call this%algo%rewind()
924 class(
system_t),
intent(inout) :: this
927 integer,
allocatable :: updated_quantities(:)
932 system_clock = this%clock, prop_clock = this%algo%clock)
935 call this%output_finish()
938 if (this%algo%final_step%id /=
skip)
then
939 if (.not. this%do_algorithmic_operation(this%algo%final_step, updated_quantities))
then
940 message(1) =
"Unsupported algorithmic operation."
941 write(
message(2),
'(A,A,A)') trim(this%algo%final_step%id),
": ", trim(this%algo%final_step%label)
943 else if (
allocated(updated_quantities))
then
944 message(1) =
"Update of quantities not allowed in algorithmic operation."
945 write(
message(2),
'(A,A,A)') trim(this%algo%final_step%id),
": ", trim(this%algo%final_step%label)
960 character(len=40) :: fmt
965 if (abs(energy) >= 1e5)
then
966 fmt =
'(i7,1x,f14.6,1X,es13.6,1X,i9,1X,'
968 fmt =
'(i7,1x,f14.6,1X,f13.6,1X,i9,1X,'
970 if (this%algo%elapsed_time < 1e-3)
then
971 fmt = trim(fmt)//
'es13.3)'
973 fmt = trim(fmt)//
'f13.3)'
976 write(
message(1), fmt) this%clock%get_tick(), &
978 0, this%algo%elapsed_time
998 class(
system_t),
intent(inout) :: this
1006 if (
associated(this%algo))
then
1007 deallocate(this%algo)
1010 call iter%start(this%interactions)
1011 do while (iter%has_next())
1012 interaction => iter%get_next()
1013 safe_deallocate_p(interaction)
1026 select type (partner)
1028 call this%add_ptr(partner)
1048 select type (partner)
1051 call iterator%start(this)
1052 do while (iterator%has_next() .and. .not. contains)
1053 system => iterator%get_next()
1054 contains =
associated(system, partner)
1071 select type (ptr => this%get_next_ptr())
1086 class(
system_t),
intent(inout) :: this
1101 class(
system_t),
intent(inout) :: this
1102 float,
intent(in) :: target_time
1103 integer,
intent(in) :: barrier_index
1107 this%barrier(barrier_index)%active = .
true.
1108 this%barrier(barrier_index)%target_time = target_time
1115 class(
system_t),
intent(inout) :: this
1116 integer,
intent(in) :: barrier_index
1120 this%barrier(barrier_index)%active = .false.
1121 this%barrier(barrier_index)%target_time =
m_zero
1128 class(
system_t),
intent(inout) :: this
1129 integer,
intent(in) :: barrier_index
1136 if (this%barrier(barrier_index)%active)
then
1138 if (
clock%time() > this%barrier(barrier_index)%target_time)
then
1148 class(
system_t),
intent(inout) :: this
1155 do ii = 1, number_barriers
1157 .or. this%arrived_at_barrier(ii)
1177 this%potential_energy =
m_zero
1179 call iter%start(this%interactions)
1180 do while (iter%has_next())
1181 interaction => iter%get_next()
1182 if(.not. interaction%intra_interaction)
then
1183 call interaction%calculate_energy()
1184 this%potential_energy = this%potential_energy + interaction%energy
1197 class(
system_t),
intent(inout) :: this
1204 this%internal_energy =
m_zero
1205 call iter%start(this%interactions)
1206 do while (iter%has_next())
1207 interaction => iter%get_next()
1208 if(interaction%intra_interaction)
then
1209 call interaction%calculate_energy()
1210 this%internal_energy = this%internal_energy + interaction%energy
1222 class(
system_t),
intent(inout) :: this
1226 call this%update_kinetic_energy()
1227 this%total_energy = this%kinetic_energy
1230 call this%update_potential_energy()
1231 this%total_energy = this%total_energy + this%potential_energy
1234 call this%update_internal_energy()
1235 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
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 step_done
character(len=algo_label_len), parameter, public skip
integer, parameter, public clock_tick
real(8), parameter, public m_zero
This module defines the abstract interaction_t class, and some auxiliary classes for interactions.
This module defines classes and functions for interaction partners.
This module implements fully polymorphic linked lists, and some specializations thereof.
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
subroutine, public messages_not_implemented(feature, namespace)
character(len=512), private msg
subroutine, public push_sub(sub_name)
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 pop_sub(sub_name)
subroutine, public messages_input_error(namespace, var, details, row, column)
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)
subroutine, public multisystem_debug_write_event_out(handle, extra, update, system_clock, prop_clock, interaction_clock, partner_clock, requested_clock)
type(event_handle_t) function, public multisystem_debug_write_event_in(system_namespace, event, extra, system_clock, prop_clock, interaction_clock, partner_clock, requested_clock)
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)
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)
logical function system_update_exposed_quantities(partner, requested_time, interaction)
update all exposed quantities of the system.
recursive logical function system_list_contains(this, partner)
subroutine system_init_all_interactions(this)
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)
subroutine, public system_init_clocks(this)
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
class(system_t) function, pointer system_iterator_get_next(this)
subroutine, public system_reset_clocks(this, accumulated_ticks)
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_init_algorithm(this, factory)
subroutine system_end_barrier(this, barrier_index)
logical function system_update_interactions(this)
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 algoritm 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 defining only minimal structures
abstract class for general interaction partners
iterator for the list of partners
Some interactions involve two systems. In this case the interaction is a unidirectional relationship ...
This class implements an iterator for the polymorphic linked list.
This is defined even when running serial.
events marking a clock update
events marking a function call
handle to keep track of in- out- events
These classes extends the list and list iterator to create a system list.
Abstract class for systems.