Octopus
multisystem.F90
Go to the documentation of this file.
1!! Copyright (C) 2019-2020 M. Oliveira, Heiko Appel
2!! Copyright (C) 2021 S. Ohlmann
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
47 use debug_oct_m
48 use global_oct_m
55 use loct_oct_m
57 use mpi_oct_m
62 use system_oct_m
63 implicit none
64
65 private
66 public :: &
69
76 type, extends(system_t), abstract :: multisystem_t
77 type(system_list_t) :: list
78 contains
79 procedure :: execute_algorithm => multisystem_execute_algorithm
80 procedure :: next_time_on_largest_dt => multisystem_next_time_on_largest_dt
81 procedure :: reset_iteration_counters => multisystem_reset_iteration_counters
82 procedure :: new_algorithm => multisystem_new_algorithm
83 procedure :: algorithm_finished => multisystem_algorithm_finished
84 procedure :: init_iteration_counters => multisystem_init_iteration_counters
85 procedure :: add_partners_to_list => multisystem_add_partners_to_list
86 procedure :: create_interactions => multisystem_create_interactions
87 procedure :: algorithm_start => multisystem_algorithm_start
88 procedure :: algorithm_finish => multisystem_algorithm_finish
89 procedure :: init_interaction => multisystem_init_interaction
90 procedure :: write_interaction_graph => multisystem_write_interaction_graph
91 procedure :: initialize => multisystem_initialize
92 procedure :: do_algorithmic_operation => multisystem_do_algorithmic_operation
93 procedure :: is_tolerance_reached => multisystem_is_tolerance_reached
94 procedure :: update_quantity => multisystem_update_quantity
95 procedure :: init_interaction_as_partner => multisystem_init_interaction_as_partner
96 procedure :: copy_quantities_to_interaction => multisystem_copy_quantities_to_interaction
97 procedure :: process_is_slave => multisystem_process_is_slave
98 procedure :: start_barrier => multisystem_start_barrier
99 procedure :: end_barrier => multisystem_end_barrier
100 procedure :: arrived_at_barrier => multisystem_arrived_at_barrier
101 procedure :: restart_write => multisystem_restart_write
102 procedure :: restart_read => multisystem_restart_read
103 procedure :: restart_write_data => multisystem_restart_write_data
104 procedure :: restart_read_data => multisystem_restart_read_data
105 procedure :: update_kinetic_energy => multisystem_update_kinetic_energy
106 procedure :: update_potential_energy => multisystem_update_potential_energy
107 procedure :: update_internal_energy => multisystem_update_internal_energy
108 procedure :: get_flat_list => multisystem_get_flat_list
109 end type multisystem_t
110
111contains
112
113 ! ---------------------------------------------------------------------------------------
114 recursive function multisystem_next_time_on_largest_dt(this) result(next_time_on_largest_dt)
115 class(multisystem_t), intent(inout) :: this
116 real(real64) :: next_time_on_largest_dt
117
118 type(system_iterator_t) :: iter
119 class(system_t), pointer :: system
120 type(iteration_counter_t) :: iteration
121
123
124 next_time_on_largest_dt = m_zero
125 call iter%start(this%list)
126 do while (iter%has_next())
127 system => iter%get_next()
128 select type (system)
129 class is (multisystem_t)
130 next_time_on_largest_dt = max(next_time_on_largest_dt, system%next_time_on_largest_dt())
131 class default
132 iteration = system%iteration + 1
133 next_time_on_largest_dt = max(next_time_on_largest_dt, iteration%value())
134 end select
135 end do
136
140 ! ---------------------------------------------------------------------------------------
141 recursive subroutine multisystem_execute_algorithm(this)
142 class(multisystem_t), intent(inout) :: this
143
144 type(system_iterator_t) :: iter
145 class(system_t), pointer :: system
146
147 type(event_handle_t) :: debug_handle
148
150
151 debug_handle = multisystem_debug_write_event_in(this%namespace, event_function_call_t("multisystem_dt_operation"), &
152 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
153
154 ! Multisystem
155 call system_execute_algorithm(this)
156
157 ! Subsystems
158 call iter%start(this%list)
159 do while (iter%has_next())
160 system => iter%get_next()
161 call system%execute_algorithm()
162 end do
163
164 call multisystem_debug_write_event_out(debug_handle, system_iteration = this%iteration, algo_iteration = this%algo%iteration)
165
167 end subroutine multisystem_execute_algorithm
168
169 ! ---------------------------------------------------------------------------------------
170 recursive subroutine multisystem_reset_iteration_counters(this, accumulated_iterations)
171 class(multisystem_t), intent(inout) :: this
172 integer, intent(in) :: accumulated_iterations
173
174 type(system_iterator_t) :: iter
175 class(system_t), pointer :: system
179 ! Multisystem iteration counters
180 call system_reset_iteration_counters(this, accumulated_iterations)
182 ! Subsystems iteration counters
183 call iter%start(this%list)
184 do while (iter%has_next())
185 system => iter%get_next()
186 call system%reset_iteration_counters(accumulated_iterations)
187 end do
192 ! ---------------------------------------------------------------------------------------
193 recursive subroutine multisystem_new_algorithm(this, factory)
194 class(multisystem_t), intent(inout) :: this
195 class(algorithm_factory_t), intent(in) :: factory
197 type(system_iterator_t) :: iter
198 class(system_t), pointer :: system
202 ! Now initialized the algorithms of the subsystems
203 call iter%start(this%list)
204 do while (iter%has_next())
205 system => iter%get_next()
206 call system%new_algorithm(factory)
207 end do
208
209 ! Initialize the algorithm of the multisystem. By default the
210 ! multisystem itself and its own quantities are kept unchanged
211 ! by using the static propagator. However, the subsystems are allowed to have
212 ! their own propagators and those do not have to be static.
213 ! Needs to be done after initializing the subsystems propagators,
214 ! as we use the largest dt of the subsystems.
215 this%algo => factory%create_static(this)
216 call this%algo%rewind()
217
219
221 end subroutine multisystem_new_algorithm
222
223 ! ---------------------------------------------------------------------------------------
224 recursive function multisystem_algorithm_finished(this) result(finished)
225 class(multisystem_t), intent(in) :: this
226 logical :: finished
227
228 type(system_iterator_t) :: iter
229 class(system_t), pointer :: system
230
231 ! Check if multisystem itself is finished
232 finished = this%algo%finished()
233
234 ! Check subsystems
235 call iter%start(this%list)
236 do while (iter%has_next())
237 system => iter%get_next()
238 finished = finished .and. system%algorithm_finished()
239 end do
240
242
243 ! ---------------------------------------------------------------------------------------
246 recursive subroutine multisystem_init_iteration_counters(this)
247 class(multisystem_t), intent(inout) :: this
248
249 type(system_iterator_t) :: iter
250 class(system_t), pointer :: system
251
253
254 ! initialize multisystem iteration counters
256
257 ! initialize iteration counters of subsystems
258 call iter%start(this%list)
259 do while (iter%has_next())
260 system => iter%get_next()
261 call system%init_iteration_counters()
262 end do
263
266
267 ! ---------------------------------------------------------------------------------------
270 recursive subroutine multisystem_algorithm_start(this)
271 class(multisystem_t), intent(inout) :: this
272
273 type(system_iterator_t) :: iter
274 class(system_t), pointer :: system
275
276 type(event_handle_t) :: debug_handle
277
279
280 debug_handle = multisystem_debug_write_event_in(this%namespace, event_function_call_t("multisystem_algorithm_start"), &
281 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
282
283 ! Now start the execution of the subsystems
284 call iter%start(this%list)
285 do while (iter%has_next())
286 system => iter%get_next()
287 call system%algorithm_start()
288 end do
289
290 ! Once the subsystems are initialized start the propagation of the multisystem
291 call system_algorithm_start(this)
292
293 call multisystem_debug_write_event_out(debug_handle, system_iteration = this%iteration, algo_iteration = this%algo%iteration)
294
296 end subroutine multisystem_algorithm_start
297
298 ! ---------------------------------------------------------------------------------------
301 recursive subroutine multisystem_algorithm_finish(this)
302 class(multisystem_t), intent(inout) :: this
303
304 type(system_iterator_t) :: iter
305 class(system_t), pointer :: system
306
307 type(event_handle_t) :: debug_handle
308
310
311 debug_handle = multisystem_debug_write_event_in(this%namespace, event_function_call_t("multisystem_algorithm_finish"), &
312 system_iteration = this%iteration, algo_iteration = this%algo%iteration)
313
314 ! Finish the execution of the multisystem
315 call system_algorithm_finish(this)
316
317 ! Now finish the execution of the subsystems
318 call iter%start(this%list)
319 do while (iter%has_next())
320 system => iter%get_next()
321 call system%algorithm_finish()
322 end do
323
324 call multisystem_debug_write_event_out(debug_handle, system_iteration = this%iteration, algo_iteration = this%algo%iteration)
325
327 end subroutine multisystem_algorithm_finish
328
329 ! ---------------------------------------------------------
337 recursive subroutine multisystem_add_partners_to_list(this, list, interaction_type)
338 class(multisystem_t), intent(in) :: this
339 class(partner_list_t), intent(inout) :: list
340 integer, optional, intent(in) :: interaction_type
342 type(system_iterator_t) :: iter
343 class(system_t), pointer :: system
344
345 if (present(interaction_type)) then
346 if (any(this%supported_interactions_as_partner == interaction_type)) then
347 call list%add(this)
348 end if
349 else
350 call list%add(this)
351 end if
352
353 call iter%start(this%list)
354 do while (iter%has_next())
355 system => iter%get_next()
356 call system%add_partners_to_list(list, interaction_type)
357 end do
358
360
361 ! ---------------------------------------------------------
369
370 recursive subroutine multisystem_create_interactions(this, interaction_factory, available_partners)
371 class(multisystem_t), intent(inout) :: this
372 class(interactions_factory_abst_t), intent(in) :: interaction_factory
373 class(partner_list_t), target, intent(in) :: available_partners
374
375 type(system_iterator_t) :: iter
376 class(system_t), pointer :: subsystem
377
378 ! Create the multisystem interactions
379 call system_create_interactions(this, interaction_factory, available_partners)
380
381 ! Create the subsystems interactions
382 call iter%start(this%list)
383 do while (iter%has_next())
384 subsystem => iter%get_next()
385 call subsystem%create_interactions(interaction_factory, available_partners)
386 end do
387
389
390 ! ---------------------------------------------------------
397 subroutine multisystem_init_interaction(this, interaction)
398 class(multisystem_t), target, intent(inout) :: this
399 class(interaction_t), intent(inout) :: interaction
400
402
403 ! The multisystem class should never know about any specific interaction.
404 ! Only classes that extend it can know about specific interactions.
405 ! Such classes should override this method to add new supported interactions.
406 message(1) = "Trying to initialize an interaction in the multi-system container class"
407 call messages_fatal(1, namespace=this%namespace)
408
410 end subroutine multisystem_init_interaction
411
412 ! ---------------------------------------------------------------------------------------
415 recursive subroutine multisystem_write_interaction_graph(this, iunit, include_ghosts)
416 class(multisystem_t), intent(in) :: this
417 integer, intent(in) :: iunit
418 logical, intent(in) :: include_ghosts
419
420 class(system_t), pointer :: system
421 class(interaction_t), pointer :: interaction
422 type(system_iterator_t) :: sys_iter
423 type(interaction_iterator_t) :: inter_iter
424
426
427 ! Loop over all the subsystems
428 call sys_iter%start(this%list)
429 do while (sys_iter%has_next())
430 system => sys_iter%get_next()
431
432 ! Loop over the interactions that this subsystem has
433 call inter_iter%start(system%interactions)
434 do while (inter_iter%has_next())
435 interaction => inter_iter%get_next()
436
437 ! Write interaction to DOT graph if this interaction has a partner
438 select type (interaction)
439 type is (ghost_interaction_t)
440 if (include_ghosts) then
441 write(iunit, '(2x,a)') '"' + trim(system%namespace%get()) + '" <- "' + trim(interaction%partner%namespace%get()) + &
442 '" [label="'+ interaction%label + '"];'
443 end if
444 ! Do not include systems connected by ghost interactions
445 class default
446 write(iunit, '(2x,a)') '"' + trim(system%namespace%get()) + '" <- "' + trim(interaction%partner%namespace%get()) + &
447 '" [label="'+ interaction%label + '"];'
448 end select
449 end do
450
451 ! If this subsystem is also a multisystem, then we also need to traverse it
452 select type (system)
453 class is (multisystem_t)
454 call system%write_interaction_graph(iunit, include_ghosts)
455 end select
456 end do
457
460
461 ! ---------------------------------------------------------
462 recursive subroutine multisystem_initialize(this)
463 class(multisystem_t), intent(inout) :: this
464
465 type(system_iterator_t) :: iter
466 class(system_t), pointer :: system
467
468 push_sub(multisystem_initialize)
469
470 call iter%start(this%list)
471 do while (iter%has_next())
472 system => iter%get_next()
473 call system%initialize()
474 end do
475
477 end subroutine multisystem_initialize
478
479 ! ---------------------------------------------------------
480 logical function multisystem_do_algorithmic_operation(this, operation, updated_quantities) result(done)
481 class(multisystem_t), intent(inout) :: this
482 class(algorithmic_operation_t), intent(in) :: operation
483 character(len=:), allocatable, intent(out) :: updated_quantities(:)
484
486
487 ! Currently there are no multisystem specific algorithmic operations
488 done = .false.
489
493 ! ---------------------------------------------------------
494 recursive logical function multisystem_is_tolerance_reached(this, tol) result(converged)
495 class(multisystem_t), intent(in) :: this
496 real(real64), intent(in) :: tol
497
498 type(system_iterator_t) :: iter
499 class(system_t), pointer :: system
500
502
503 converged = .true.
504 call iter%start(this%list)
505 do while (iter%has_next())
506 system => iter%get_next()
507 if (.not. system%is_tolerance_reached(tol)) converged = .false.
508 end do
509
512
513 ! ---------------------------------------------------------
514 subroutine multisystem_update_quantity(this, label)
515 class(multisystem_t), intent(inout) :: this
516 character(len=*), intent(in) :: label
517
519
520 ! The multisystem class should never know about any specific quantities.
521 ! Only classes that extend it can know about specific quantities.
522 ! Such classes should override this method to add new supported quantities.
523 message(1) = "Trying to update a quantity in the multi-system container class"
524 call messages_fatal(1, namespace=this%namespace)
525
527 end subroutine multisystem_update_quantity
528
529 ! ---------------------------------------------------------
530 subroutine multisystem_init_interaction_as_partner(partner, interaction)
531 class(multisystem_t), intent(in) :: partner
532 class(interaction_surrogate_t), intent(inout) :: interaction
533
535
536 ! The multisystem class should never know about any specific interaction.
537 ! Only classes that extend it can know about specific interactions.
538 ! Such classes should override this method to add new supported interactions.
539 message(1) = "Trying to initialize an interaction as partner in the multi-system container class"
540 call messages_fatal(1, namespace=partner%namespace)
541
544
545 ! ---------------------------------------------------------
546 subroutine multisystem_copy_quantities_to_interaction(partner, interaction)
547 class(multisystem_t), intent(inout) :: partner
548 class(interaction_surrogate_t), intent(inout) :: interaction
549
551
552 ! The multisystem class should never know about any specific quantities.
553 ! Only classes that extend it can know about specific quantities.
554 ! Such classes should override this method to add new supported quantities.
555 message(1) = "Trying to copy quantities to interaction in the multi-system container class"
556 call messages_fatal(1, namespace=partner%namespace)
560
561 ! ---------------------------------------------------------
562 recursive logical function multisystem_process_is_slave(this) result(is_slave)
563 class(multisystem_t), intent(in) :: this
564
565 type(system_iterator_t) :: iter
566 class(system_t), pointer :: system
567
569
570 is_slave = .false.
571 call iter%start(this%list)
572 do while (iter%has_next())
573 system => iter%get_next()
574 if (system%process_is_slave()) is_slave = .true.
575 end do
576
579
580 !--------------------------------------------------------------------
584 recursive subroutine multisystem_update_kinetic_energy(this)
585 class(multisystem_t), intent(inout) :: this
586
588
589 ! We currently do not have the center of mass coordinates implemented for multisystems,
590 ! hence we set the kinetic energy to zero.
591 ! The kinetic energies of the constituents are contributing to the internal energy.
592
593 this%kinetic_energy = m_zero
594
597
598 !---------------------------------------------------------
599 recursive subroutine multisystem_update_internal_energy(this)
600 class(multisystem_t), intent(inout) :: this
601
602 class(system_t), pointer :: system
603 class(system_t), pointer :: system_2
604 type(system_iterator_t) :: system_iter
605 type(system_iterator_t) :: system_iter_2
606
608
609 ! The internal energy of the multisystem contains the kinetic and internal energies of the consistuents
610 !TODO: the kinetic energy wrt the center of mass motion should be subtracted.
611
612 this%internal_energy = m_zero
613
614 call system_iter%start(this%list)
615 do while (system_iter%has_next())
616
617 system => system_iter%get_next()
618
619 ! First add the kinetic energies of the subsystems
620 call system%update_kinetic_energy()
621 this%internal_energy = this%internal_energy + system%kinetic_energy
622
623 ! First add the internal energies of the subsystems
624 call system%update_internal_energy()
625 this%internal_energy = this%internal_energy + system%internal_energy
626
627 ! Now add the (inter-) interactions between the systems in the container.
628 call system_iter_2%start(this%list)
629 do while(system_iter_2%has_next())
630
631 system_2 => system_iter_2%get_next()
632
633 ! exclude self-interactions (intra-interactions) as they are included in the internal energy
634 ! of the subsystem, which was already added above.
635 if(.not. associated(system, system_2)) then
636 this%internal_energy = this%internal_energy + multisystem_pair_energy(system, system_2)
637 end if
638 end do ! system_iter_2
639
640 end do ! system_iter
644
645 ! ---------------------------------------------------------
659 class(multisystem_t), intent(inout) :: this
660
661 type(system_iterator_t) :: system_iter
662 class(system_t), pointer :: system
663 type(interaction_iterator_t) :: interaction_iter
664 class(interaction_t), pointer :: interaction
665 type(system_list_t) :: flat_list
666
668
669 this%potential_energy = m_zero
670
671 ! We need to handle interactions of the container itself:
673
674 ! generate a list of all systems inside the container and its subcontainers:
675 call this%get_flat_list(flat_list)
676
677 ! loop over all systems inside the container
678 call system_iter%start(flat_list)
679 do while (system_iter%has_next())
680
681 system => system_iter%get_next()
682
683 ! Even though we are not using the potential energy of the subsystems here, we need to trigger their calculation
684 call system%update_potential_energy()
685
686 ! loop over all interactions and discard those with partners inside the container
687 call interaction_iter%start(system%interactions)
688 do while (interaction_iter%has_next())
689 interaction => interaction_iter%get_next()
690 if(.not. flat_list%contains(interaction%partner) .and. .not. interaction%intra_interaction) then
691 call interaction%calculate_energy()
692 this%potential_energy = this%potential_energy + interaction%energy
693 end if
694 end do
695
696 end do
697
700
701 ! ---------------------------------------------------------
708 recursive real(real64) function multisystem_pair_energy(partner_A, partner_B) result(pair_energy)
709 class(interaction_partner_t), intent(in) :: partner_a
710 class(interaction_partner_t), intent(in) :: partner_b
711
712 class(system_t), pointer :: system_a
713 class(system_t), pointer :: system_b
714 type(system_iterator_t) :: system_iterator_a
715 type(system_iterator_t) :: system_iterator_b
716
718
719 pair_energy = m_zero
720
721 select type(partner_a)
722 class is (multisystem_t) ! partner_A is container
723
724 call system_iterator_a%start(partner_a%list)
725 do while( system_iterator_a%has_next() )
726
727 system_a => system_iterator_a%get_next()
728
729 select type(partner_b)
730 class is (multisystem_t)
731
732 call system_iterator_b%start(partner_b%list)
733 do while( system_iterator_b%has_next() )
734 system_b => system_iterator_b%get_next()
735 pair_energy = pair_energy + multisystem_pair_energy(system_a, system_b)
736 end do
737
738 class is (system_t)
739 pair_energy = pair_energy + interaction_energy(partner_a, partner_b)
740 class default
741 assert(.false.) ! partner_A must be a system_t
742 end select
743 end do
744
745 class is (system_t) ! partner_A is non-container system
746
747 select type(partner_b)
748 class is (multisystem_t) ! partner_B is container
749
750 call system_iterator_b%start(partner_b%list)
751 do while( system_iterator_b%has_next() )
752 system_b => system_iterator_b%get_next()
753 pair_energy = pair_energy + multisystem_pair_energy(partner_a, system_b)
754 end do
755
756 class default ! both partner_A and partner_B are explicit: we need to calculate
757 pair_energy = pair_energy + interaction_energy(partner_a, partner_b)
758 end select
759
760 class default
761 assert(.false.)
762 end select
763
765
766 contains
767
768 real(real64) function interaction_energy(system, partner) result (energy)
769 class(system_t), target, intent(in) :: system
770 class(interaction_partner_t), target, intent(in) :: partner
771
772 type(interaction_iterator_t) :: interaction_iterator
773 class(interaction_t), pointer :: interaction
774
775 energy = m_zero
776
777 call interaction_iterator%start(system%interactions)
778 do while(interaction_iterator%has_next())
779 interaction => interaction_iterator%get_next()
780 if( associated(interaction%partner, partner)) then
781 call interaction%calculate_energy()
782 energy = energy + interaction%energy
783 end if
784 end do
785 end function interaction_energy
786
787 end function multisystem_pair_energy
788
789
790 ! ---------------------------------------------------------
793 recursive subroutine multisystem_get_flat_list(this, flat_list)
794 class(multisystem_t), intent(in) :: this
795 type(system_list_t), intent(out) :: flat_list
796
797 class(interaction_partner_t), pointer :: partner
798 type(partner_iterator_t) :: iterator
799
801
802 call iterator%start(this%list)
803 do while (iterator%has_next())
804 partner => iterator%get_next()
805
806 call flat_list%add(partner)
807
808 select type (partner)
809 class is (multisystem_t)
810 ! Also include the subsystems of a multisystem
811 call partner%get_flat_list(flat_list)
812 end select
813
814 end do
815
817
818 end subroutine multisystem_get_flat_list
819
820 ! ---------------------------------------------------------
821 recursive subroutine multisystem_end(this)
822 class(multisystem_t), intent(inout) :: this
823
824 type(system_iterator_t) :: iter
825 class(system_t), pointer :: system
826
827 push_sub(multisystem_end)
828
829 call iter%start(this%list)
830 do while (iter%has_next())
831 system => iter%get_next()
832 if (associated(system)) then
833 deallocate(system)
834 end if
835 end do
836
837 call system_end(this)
838
839 pop_sub(multisystem_end)
840 end subroutine multisystem_end
841
842 ! ---------------------------------------------------------
843 recursive subroutine multisystem_start_barrier(this, target_time, barrier_index)
844 class(multisystem_t), intent(inout) :: this
845 real(real64), intent(in) :: target_time
846 integer, intent(in) :: barrier_index
847
848 type(system_iterator_t) :: iter
849 class(system_t), pointer :: system
850
852
853 call iter%start(this%list)
854 do while (iter%has_next())
855 system => iter%get_next()
856 call system%start_barrier(target_time, barrier_index)
857 end do
858
860 end subroutine multisystem_start_barrier
861
862 ! ---------------------------------------------------------
863 recursive subroutine multisystem_end_barrier(this, barrier_index)
864 class(multisystem_t), intent(inout) :: this
865 integer, intent(in) :: barrier_index
866
867 type(system_iterator_t) :: iter
868 class(system_t), pointer :: system
869
871
872 call iter%start(this%list)
873 do while (iter%has_next())
874 system => iter%get_next()
875 call system%end_barrier(barrier_index)
876 end do
877
879 end subroutine multisystem_end_barrier
880
881 ! ---------------------------------------------------------
882 recursive logical function multisystem_arrived_at_barrier(this, barrier_index)
883 class(multisystem_t), intent(inout) :: this
884 integer, intent(in) :: barrier_index
885
886 type(system_iterator_t) :: iter
887 class(system_t), pointer :: system
890
892 call iter%start(this%list)
893 do while (iter%has_next())
894 system => iter%get_next()
896 system%arrived_at_barrier(barrier_index)
897 end do
898
901
902 ! ---------------------------------------------------------
903 recursive subroutine multisystem_restart_write(this)
904 class(multisystem_t), intent(inout) :: this
905
906 type(system_iterator_t) :: iter
907 class(system_t), pointer :: system
908
910
911 ! do generic restart steps
912 call system_restart_write(this)
913
914 ! loop over all subsystems
915 call iter%start(this%list)
916 do while (iter%has_next())
917 system => iter%get_next()
918 call system%restart_write()
919 end do
920 message(1) = "Wrote restart data for multisystem "//trim(this%namespace%get())
921 call messages_info(1, namespace=this%namespace)
922
924 end subroutine multisystem_restart_write
925
926 ! ---------------------------------------------------------
927 recursive logical function multisystem_restart_read(this)
928 class(multisystem_t), intent(inout) :: this
929
930 type(system_iterator_t) :: iter
931 class(system_t), pointer :: system
932
934
935 ! read generic restart data
936 multisystem_restart_read = system_restart_read(this)
937 call iter%start(this%list)
938 do while (iter%has_next())
939 system => iter%get_next()
940 ! TODO: adapt logics here for consistent restarting
942 system%restart_read()
943 end do
944
946 message(1) = "Successfully read restart data for multisystem "//trim(this%namespace%get())
947 call messages_info(1, namespace=this%namespace)
948 end if
949
951 end function multisystem_restart_read
952
953 ! ---------------------------------------------------------
954 subroutine multisystem_restart_write_data(this)
955 class(multisystem_t), intent(inout) :: this
956
959 ! do not write restart data for multisystem_t
960
962 end subroutine multisystem_restart_write_data
963
964 ! ---------------------------------------------------------
965 ! this function returns true if restart data could be read
966 logical function multisystem_restart_read_data(this)
967 class(multisystem_t), intent(inout) :: this
968
970
972
975
976end module multisystem_oct_m
real(real64) function interaction_energy(system, partner)
This module defines the abstract interfact for algorithm factories.
This module implements the basic elements defining algorithms.
Definition: algorithm.F90:143
real(real64), parameter, public m_zero
Definition: global.F90:200
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 defines the abstract class for the interaction factory.
System information (time, memory, sysname)
Definition: loct.F90:117
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
This module implements the multisystem debug functionality.
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 implements the abstract multisystem class.
recursive subroutine multisystem_new_algorithm(this, factory)
recursive subroutine, public multisystem_end(this)
recursive logical function multisystem_process_is_slave(this)
recursive logical function multisystem_arrived_at_barrier(this, barrier_index)
recursive subroutine multisystem_update_internal_energy(this)
recursive subroutine multisystem_algorithm_start(this)
call the algorithm_start routine for all contained systems
recursive subroutine multisystem_create_interactions(this, interaction_factory, available_partners)
create the interactions of the multisystem
recursive subroutine multisystem_restart_write(this)
recursive subroutine multisystem_add_partners_to_list(this, list, interaction_type)
add interaction partners contained in the multisystem to a list
subroutine multisystem_init_interaction(this, interaction)
initialize a specific interaction
subroutine multisystem_update_potential_energy(this)
Calculate the potential energy for a container.
recursive subroutine multisystem_reset_iteration_counters(this, accumulated_iterations)
recursive logical function multisystem_restart_read(this)
recursive subroutine multisystem_initialize(this)
subroutine multisystem_init_interaction_as_partner(partner, interaction)
recursive logical function multisystem_is_tolerance_reached(this, tol)
recursive real(real64) function multisystem_next_time_on_largest_dt(this)
recursive subroutine multisystem_algorithm_finish(this)
call the algorithm_finish routine for all contained systems
subroutine multisystem_update_quantity(this, label)
subroutine multisystem_copy_quantities_to_interaction(partner, interaction)
recursive real(real64) function multisystem_pair_energy(partner_A, partner_B)
This function calculates the complete interaction energy between partner_A and partner_B,...
recursive subroutine multisystem_execute_algorithm(this)
recursive subroutine multisystem_get_flat_list(this, flat_list)
Generate a list of all systems contained in a multisystem, including those inside child containers.
logical function multisystem_restart_read_data(this)
subroutine multisystem_restart_write_data(this)
recursive subroutine multisystem_end_barrier(this, barrier_index)
recursive subroutine multisystem_update_kinetic_energy(this)
Calculate the kinetic energy: The kinetic energy of a container (multisystem) is defined by the kinet...
recursive subroutine multisystem_init_iteration_counters(this)
initialize the iteration counters of the contained systems
recursive subroutine multisystem_start_barrier(this, target_time, barrier_index)
recursive logical function multisystem_algorithm_finished(this)
recursive subroutine multisystem_write_interaction_graph(this, iunit, include_ghosts)
write a graphical representation of the interactions
logical function multisystem_do_algorithmic_operation(this, operation, updated_quantities)
This module defines the quantity_t class and the IDs for quantities, which can be exposed by a system...
Definition: quantity.F90:140
This module implements the abstract system type.
Definition: system.F90:120
subroutine, public system_algorithm_start(this)
Definition: system.F90:1023
subroutine, public system_init_iteration_counters(this)
Initialize the iteration counters of the system and its interactions, algorithms and quantities.
Definition: system.F90:986
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...
Definition: system.F90:1327
subroutine, public system_algorithm_finish(this)
Definition: system.F90:1075
recursive subroutine, public system_create_interactions(this, interaction_factory, available_partners)
create the interactions of the system
Definition: system.F90:519
subroutine, public system_execute_algorithm(this)
perform one or more algorithmic operations
Definition: system.F90:339
subroutine, public system_reset_iteration_counters(this, accumulated_iterations)
Definition: system.F90:465
Abstract class for the algorithm factories.
Descriptor of one algorithmic operation.
Definition: algorithm.F90:165
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
surrogate interaction class to avoid circular dependencies between modules.
handle to keep track of in- out- events
the abstract multisystem class
These classes extends the list and list iterator to create a system list.
Definition: system.F90:310
Abstract class for systems.
Definition: system.F90:175
int true(void)