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.